{"slug": "let-ai-agents-use-production-data-without-handing-them-your-database", "title": "Let AI agents use production data without handing them your database", "summary": "A developer built Synapsor Runner, an Apache-2.0 runtime that sits between an MCP client and PostgreSQL or MySQL, replacing raw SQL execution with reviewed semantic capabilities. The tool enforces a boundary where the model never receives write authority, containing blast radius from prompt injection or confused models. It uses contracts to define tenant scope, allowed columns and rows, and supports tiered auto-approval for low-risk proposals while recording all operations in a ledger.", "body_md": "Hi Devs,\n\nIf you’ve connected an AI agent to a real database, you’ve probably felt the discomfort of the default approach: handing the model an `execute_sql(sql)`\n\ntool.\n\nRead-only roles, SQL validation, allowlists, and prompt instructions all help. But they still give the model raw database authority and then try to constrain it.\n\nI wanted the opposite: a boundary where the model never receives that authority in the first place.\n\nSo I built **Synapsor Runner**, an Apache-2.0 runtime that sits between an MCP client and PostgreSQL or MySQL. Instead of exposing SQL, it exposes reviewed semantic capabilities such as:\n\n```\nbilling.inspect_invoice\nbilling.propose_late_fee_waiver\nsupport.propose_plan_credit\n```\n\nNo database. No signup.\n\n```\nnpx -y -p @synapsor-runner audit --example dangerous-db-mcp\nnpx -y -p @synapsor-runner demo --quick\n```\n\nThe audit flags risky MCP tool shapes, such as raw SQL execution.\n\nThe quick demo walks through the **proposal → evidence → replay** boundary. It explains and records that boundary; it does not claim to test a live database.\n\nThe model can read only the columns and rows that a contract allows. It can propose changes, but the model-facing MCP surface contains **no approve tool and no apply tool**.\n\nCommit authority lives entirely outside the model loop.\n\nEveryone does allowlists. The part I care about is that there is literally no tool the model can call to write.\n\nThis does not stop prompt injection.\n\nWhat it does is contain the blast radius when injection—or simply a confused model—happens.\n\nIn my testing, I put a fleet of real LLM agents on one server. Several were given injection tasks such as:\n\nThe result:\n\nThat was not because the models resisted the prompts. It was because the boundary was enforced outside the models.\n\nThis is the same class of failure demonstrated in the recent Supabase MCP token-exfiltration example: a model is tricked into running attacker-controlled SQL. If there is no SQL tool and no commit tool to reach, that path closes.\n\nTenant scope, allowed columns, and allowed rows are fixed by the reviewed contract and trusted server-side context.\n\nThat context is bound outside the model’s arguments, never supplied through a tool parameter.\n\nThe model cannot widen what it sees.\n\nA proposal records the requested before-and-after state but does not modify the source database.\n\nApproval and writeback happen outside MCP.\n\nWhen an approved proposal is applied, Runner rechecks:\n\nA stale row becomes a conflict instead of a silent overwrite.\n\nEvery apply operation is recorded with a receipt and replay linkage.\n\nBy default, activity is stored in a local SQLite ledger.\n\nA shared PostgreSQL runtime store is also available for multi-process deployments.\n\nNot every change needs a human.\n\nA contract can define tiered auto-approval for small, low-risk proposals:\n\n```\nAUTO APPROVE WHEN amount_cents <= 2500\nLIMIT 20 PER DAY\n```\n\nPolicies can also define aggregate value ceilings.\n\nWhen a proposal exceeds a rule or budget, it falls back to human review, and the ledger records why.\n\nHigher-risk capabilities can require approvals from multiple distinct people.\n\nPolicy approval still gives the model no commit authority. A trusted Runner worker performs the guarded write outside MCP.\n\nFor reviewed batch operations:\n\nThis is not a path to arbitrary `UPDATE`\n\nstatements.\n\nRunner can record a bounded inverse and create a separate compensation proposal.\n\nReverting is not rollback or time travel. It is another reviewed proposal that passes through the same approval and writeback boundary.\n\nContracts are portable JSON documents.\n\nYou can hand-author the JSON or use an optional SQL-like DSL with constructs such as:\n\n`CREATE AGENT CONTEXT`\n\n`CREATE CAPABILITY`\n\nThe DSL compiles to the same JSON format.\n\nEither way, contracts can be reviewed and versioned in Git like application code.\n\nThis is a security tool, so I would rather under-claim.\n\nSynapsor Runner:\n\nIt is a scoped enforcement boundary that limits what a compromised or mistaken model can read, propose, and change.\n\nThe built-in guarded path intentionally excludes:\n\n`UPSERT`\n\nThose operations need an application-owned executor that is invoked only after approval, with the application retaining ownership of the transaction and security checks.\n\nA side benefit is that this approach also tends to use fewer tokens.\n\nBecause the model calls semantic tools instead of writing SQL:\n\n`list_tables`\n\nand `describe_table`\n\nround trips.`MAX ROWS`\n\n.`COUNT`\n\ninstead of sending many rows back into context.There is a caveat: every capability appears in the model’s `tools/list`\n\n.\n\nA contract that exposes hundreds of tools to one agent can lose the token savings through tool-definition bloat.\n\nThe real claim is:\n\nWell-scoped contract → net cheaper\n\nI would treat that as directional rather than a benchmarked number, but “safer and cheaper per run” appears to hold for the common case.\n\n[github.com/Synapsor/Synapsor-Runner](https://github.com/Synapsor/Synapsor-Runner)\n\nI’m the maintainer, and I would genuinely value feedback from people already connecting MCP clients to real databases:\n\n**What workflow did you want to give an agent, but held back because raw SQL or direct API authority felt like too much?**\n\nEven a reply such as “this shape wouldn’t fit because…” would be useful.", "url": "https://wpnews.pro/news/let-ai-agents-use-production-data-without-handing-them-your-database", "canonical_source": "https://dev.to/sandeshtiwari/let-ai-agents-use-production-data-without-handing-them-your-database-24en", "published_at": "2026-07-16 17:09:00+00:00", "updated_at": "2026-07-16 18:05:25.487693+00:00", "lang": "en", "topics": ["ai-safety", "ai-agents", "developer-tools", "ai-infrastructure"], "entities": ["Synapsor Runner", "PostgreSQL", "MySQL", "Supabase"], "alternates": {"html": "https://wpnews.pro/news/let-ai-agents-use-production-data-without-handing-them-your-database", "markdown": "https://wpnews.pro/news/let-ai-agents-use-production-data-without-handing-them-your-database.md", "text": "https://wpnews.pro/news/let-ai-agents-use-production-data-without-handing-them-your-database.txt", "jsonld": "https://wpnews.pro/news/let-ai-agents-use-production-data-without-handing-them-your-database.jsonld"}}