I've been running Cursor and Claude Code with MCP for a while now, and one thing became obvious pretty quickly:
Giving an agent a generic execute_sql tool is usually a terrible idea.
The first problem is context explosion. If an agent needs to understand a database, it often starts by pulling huge schema dumps, table definitions, or query results directly into the conversation. Context gets consumed incredibly fast.
The second problem is what I call the agent loop trap. The model writes a query, gets an error, rewrites it, gets another error, and continues indefinitely. If you're using paid models, this can become surprisingly expensive.
To explore a different approach, I spent the last few weeks building DBeast, an open-source MCP server for PostgreSQL focused on discovery, diagnostics, and safety rather than unrestricted SQL execution.
Instead of exposing a single powerful database tool, DBeast exposes 21 specialized tools.
A few design decisions that ended up working well:
1. Schema mapping instead of schema dumping
Rather than feeding entire DDL definitions into context, the server reads information_schema and system catalogs to generate compact structural representations.
The goal is to help the model understand:
- table relationships
- foreign keys
- cardinality
- dependency graphs
without flooding the context window.
In many cases, a compact graph representation is dramatically more useful than thousands of lines of SQL.
2. Safety enforced at the tool layer
I didn't want agents performing unrestricted writes.
Read-oriented tools automatically enforce result limits, and mutation attempts are intercepted before execution.
For potentially destructive operations, the server can return an impact assessment instead:
- estimated rows affected
- dependency information
- potential blast radius
This gives the model enough information to reason about consequences without actually making changes.
3. Breaking self-correction loops
One thing I noticed is that agents often treat database errors as invitations to keep retrying forever.
When PostgreSQL returns certain classes of errors, DBeast wraps them into structured responses that encourage the agent to stop, reassess, or ask for clarification instead of endlessly burning tokens.
4. Keeping everything local
The server runs locally using AsyncIO and standard MCP stdio transport.
Connection pools remain isolated, and no database metadata leaves the machine unless the host application chooses to send it to the model.
The project is MIT licensed and still early.
I'm particularly interested in how others are handling:
- schema discovery
- permission scoping
- context management
- preventing runaway agent/tool loops
- safe database mutations
For those building MCP servers around data systems, what approaches have worked well for you?
GitHub: https://github.com/snss10/DBeast
Top comments (0)