sql-guard-mcp
Provides safe, read-only access to SQLite databases, enabling AI agents to list tables, describe schemas, run capped SELECT queries, and explain query plans while enforcing table, column, and row-scope restrictions.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@sql-guard-mcpWhich product categories earned the most this year, excluding returns?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
sql-guard-mcp
An MCP server that lets an AI agent (Claude, ChatGPT, Cursor or your own) answer questions from a SQL database without being able to change data, read protected columns or see another customer's rows, whatever SQL the model writes.
"Which product categories earned the most this year, excluding returns?" The agent looks up the tables, writes the SQL, runs it through this server and answers with real numbers.
Giving a model a database connection is the fastest way to a demo and the slowest way to production. This repository shows the production version: a small, tested server where every safety rule is configuration, enforced twice.
What the agent gets
Four task-level tools, all marked read-only:
Tool | What it does |
| Tables the agent may use, with descriptions and row counts |
| Readable columns and types, plus three sample rows |
| Runs one SELECT and returns columns and rows (capped) |
| Shows the SQL that would run and SQLite's query plan, without running it |
Errors come back as JSON the model can act on:
{"error": {"code": "COLUMN_NOT_ALLOWED",
"message": "Column 'email' on 'customers' is protected and cannot be read.",
"retryable": true,
"hint": "Readable columns of customers: id, store_id, full_name, city, joined_on."}}The model fixes its query and tries again, instead of guessing or giving up.
Related MCP server: SQLGuard MCP
How it stays safe
flowchart LR
A[AI agent] -->|MCP tool call: SQL| G
subgraph S[sql-guard-mcp]
G[1. SQL guard<br/>parse, check, rewrite] --> D[2. Read-only connection<br/>3. SQLite authorizer]
G -.->|every call| L[(Audit log<br/>JSON lines)]
end
D --> DB[(Database)]
P[policy.toml] -.-> G
P -.-> DLayer | What it enforces |
1. SQL guard ( | Exactly one statement; SELECT only; only allowed tables; no protected columns; no |
2. Read-only connection ( | The file is opened with |
3. SQLite authorizer ( | SQLite asks the server to approve every table and column read while compiling a statement. Disallowed tables, protected columns and direct reads of scoped tables are refused by the engine itself, so a gap in the parser cannot leak data. |
Limits | Results capped ( |
Audit | One JSON line per call: tool, SQL, executed SQL, outcome, rows, duration. |
Row scoping (multi-tenant)
A table can carry a fixed scope predicate. The demo serves one store of two:
[tables.orders]
scope = "store_id = 1"At start-up the server creates a temporary view per scoped table that applies the predicate and drops protected columns. The guard rewrites every reference to the view, and the authorizer refuses to read the underlying table directly. The tenant comes from configuration, never from the model, so WHERE store_id = 2 simply returns nothing.
Configuration
Access is a config file, not code. See examples/policy.toml:
[database]
path = "shop.db"
[limits]
max_rows = 200
timeout_ms = 2000
[audit]
path = "audit.log.jsonl"
[tables.customers]
description = "Customers of the store. Contact details are protected."
hidden_columns = ["email", "phone"]
scope = "store_id = 1"
[tables.products]
description = "Product catalogue shared by all stores."The server checks the policy against the real schema at start-up and refuses to run if it names a table or column that does not exist.
Quick start
Python 3.11 or newer.
git clone https://github.com/pratikpande87/sql-guard-mcp.git
cd sql-guard-mcp
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
python examples/make_demo_db.py # builds examples/shop.db (fixed seed)
python examples/demo_client.py # starts the server over stdio and calls it like an agent wouldUse it from Claude Desktop
Add this to claude_desktop_config.json (Settings, Developer, Edit Config), with absolute paths:
{
"mcpServers": {
"shop-db": {
"command": "/path/to/sql-guard-mcp/.venv/bin/sql-guard-mcp",
"args": ["--policy", "/path/to/sql-guard-mcp/examples/policy.toml"]
}
}
}Restart Claude Desktop and ask: "Which customers in Pune ordered the most last quarter?" or "Compare monthly revenue for Electronics and Apparel in 2026."
To serve over HTTP instead of stdio:
sql-guard-mcp --policy examples/policy.toml --transport streamable-http --port 8000Tests
pytest30 tests cover the guard (write statements, stacked statements, protected columns, SELECT *, CTE tricks, scoping, limits), the engine-level backstop (queries that skip the parser are still refused), timeouts, the audit log and the MCP surface (tool list, annotations, error shape).
Design notes
Few, task-named tools. Four tools that match how an analyst works beat one tool per table or per endpoint: the model picks the right one more often.
Two independent enforcement points. The parser gives good errors; the engine gives guarantees. Neither trusts the other.
Everything is configuration. Onboarding a new database or tenant is a new policy file.
Limitations
SQLite only in this version. For PostgreSQL, the same design maps to a read-only role,
default_transaction_read_only,statement_timeoutand row-level security keyed on a session setting the server controls.SQLite flattens simple views, so a bare
COUNT(*)that bypassed the parser could not be attributed to a scope view by the authorizer. Column reads always can. Queries through the server always go through the views.
License
MIT
This server cannot be deployed
Maintenance
Related MCP Connectors
Safe, read-only Postgres and MySQL access for AI agents. Audit log + column-level controls.
Deterministic safety, correctness & cost gate that vets Postgres SQL before your AI agent runs it.
Query 40 databases from Claude, ChatGPT, or Cursor — on any device. Read-only, encrypted, audited.
Query PostgreSQL databases in plain English — LLM-generated, safety-validated SQL.
Related MCP Servers
- AlicenseNot gradedqualityBmaintenanceLets AI clients ask natural-language questions about a SQL database with production-safe guardrails, schema grounding, and read-only enforcement.MIT
- AlicenseNot gradedqualityCmaintenanceEnforces safety and governance for SQL queries executed by AI agents, providing read-only enforcement, cost estimation, and audit trails.Apache 2.0
- AlicenseAqualityAmaintenanceEnables AI agents to query PostgreSQL databases securely with read-only defaults, PII masking, rate limiting, and human-approved, expiring mutation tokens.91Apache 2.0
- AlicenseNot gradedqualityCmaintenanceEnables AI agents to query a Postgres database read-only through a policy layer rather than a raw connection string. Enforces table and column allowlists, row limits, mandatory predicates, PII masking and append-only audit logging, while refusing writes, joins, subqueries and unlisted functions.MIT