warehouse-mcp
Provides read-only query access to PostgreSQL databases for AI agents, with a parsed SQL guard, row limits, statement timeouts, PII masking, and audit logging.
Can connect to Snowflake through a SQLAlchemy URL so agents can query it subject to the server's SQL guard, row limits, and masking. Database-level read-only transaction and timeout enforcement for Snowflake are not yet implemented.
Provides read-only query access to SQLite databases for AI agents, with SQL guard enforcement, row caps, timeout enforcement via a progress handler, PII masking, and audit logging.
This server does not currently have a deployable release on Glama. Follow the repository's setup instructions to install and configure it for your MCP client, including any required credentials and local dependencies.
warehouse-mcp
An MCP server that lets AI agents query a SQL database without being able to change it, stall it, or leak personal data from it.
When a team puts an agent in front of its real data, the first question is "what stops it from running DELETE, or dumping every customer's email?". This server answers that with layered controls you can explain to a security reviewer, plus an audit log they can read.
agent ──MCP──▶ list_tables / describe_table / run_query
│
┌──────────────▼──────────────┐
│ 1. SQL guard (parsed AST) │ one SELECT only; no writes, locks, INTO,
│ │ side-effect functions, system catalogs
│ 2. Row cap │ wraps the query: LIMIT max_rows + 1
├─────────────────────────────┤
│ 3. Read-only transaction │ enforced by the database itself
│ 4. Statement timeout │ stopped by the database itself
├─────────────────────────────┤
│ 5. PII masking │ by column, through aliases, and by value
│ 6. Audit log (JSONL) │ every call; never the result data
└─────────────────────────────┘Why each layer exists
Layer | Stops | Why it isn't enough on its own |
SQL guard: parses with sqlglot and rejects anything but one read-only query |
| Parsers have edge cases |
Read-only transaction: | Any write the guard missed. The tests bypass the guard entirely to prove this. | Doesn't limit cost |
Statement timeout: | Runaway joins and recursive CTEs | Doesn't limit result size |
Row cap: fetches | Agents pulling a whole table into context | — |
PII masking |
| Pattern-based; see limitations |
Audit log | "What did the agent look at?" | — |
Rejections come back as tool errors that say why (for example Query rejected: DELETE is not allowed in a read-only query.), so the agent can fix its query instead of retrying the same one.
Related MCP server: Governor SQL MCP
Quickstart
pip install -e ".[postgres]" # drop [postgres] for SQLite only
python examples/seed_demo.py # demo e-commerce DB with fake PII
WAREHOUSE_URL=sqlite:///examples/demo.db warehouse-mcpConnect it to an MCP client
Claude Desktop, Cursor, VS Code and other MCP clients use the same shape:
{
"mcpServers": {
"warehouse": {
"command": "warehouse-mcp",
"env": {
"WAREHOUSE_URL": "postgresql+psycopg://readonly_agent@db.internal:5432/analytics",
"WAREHOUSE_ALLOWED_SCHEMAS": "analytics,reporting",
"WAREHOUSE_MAX_ROWS": "200"
}
}
}
}Example
Agent: Which product categories sold the most units, delivered orders only?
// run_query
{"sql": "SELECT p.category, SUM(o.quantity) AS units FROM orders o JOIN products p ON p.id = o.product_id WHERE o.status = 'delivered' GROUP BY p.category ORDER BY units DESC"}
// → {"columns": ["category","units"], "rows": [...], "row_count": 6, "truncated": false, "masked_columns": [], "elapsed_ms": 4}// run_query
{"sql": "SELECT id, email AS contact, region FROM customers LIMIT 3"}
// → {"columns": ["id","contact","region"], "rows": [[1,"***","EU"], ...], "masked_columns": ["contact"]}// run_query
{"sql": "WITH d AS (DELETE FROM orders RETURNING *) SELECT * FROM d"}
// → error: Query rejected: DELETE is not allowed in a read-only query.Configuration
Variable | Default | |
| (required) | Any SQLAlchemy URL. Tested with PostgreSQL 16 and SQLite. |
| all | Comma-separated allow list |
|
| Row cap per query |
|
| Statement timeout |
| built-in list | Extra column-name patterns to mask, added to the defaults ( |
|
| Empty string disables it |
In production, also connect as a role with only SELECT grants. This server is defense in depth, not a replacement for database permissions.
Tests
pip install -e ".[dev]"
pytest -qThere are 45 tests: guard attack cases, PII tracing through aliases, value-level masking, end-to-end calls through a real MCP client, and audit-log contents. Read-only and timeout behaviour are tested against the database with the guard bypassed. CI runs everything against a real PostgreSQL 16 on Python 3.10, 3.11 and 3.12.
Limitations
PII detection is name- and pattern-based. It won't recognise a column called
notesthat holds home addresses, so add those columns withWAREHOUSE_PII_COLUMNS.Masking follows aliases and expressions but not every path. For example,
string_aggover a PII column is masked, while a join that reconstructs PII from non-PII columns isn't detected.Snowflake, BigQuery and other SQLAlchemy dialects will connect, but only Postgres and SQLite have read-only and timeout enforcement at the database level today.
Roadmap
Snowflake and BigQuery read-only session enforcement
Per-table row-level filters (for example
region = 'EU'for an EU-only agent)Query cost estimate from
EXPLAINbefore execution, rejecting full scans over a thresholdOpenTelemetry spans per tool call
Streamable HTTP transport with OAuth for shared deployments
Related MCP Connectors
Safe, read-only Postgres and MySQL access for AI agents. Audit log + column-level controls.
Query 40 databases from Claude, ChatGPT, or Cursor — on any device. Read-only, encrypted, audited.
Deterministic safety, correctness & cost gate that vets Postgres SQL before your AI agent runs it.
Database guardrails for AI agents: check SQL against your Vericto rules before it runs.
Related MCP Servers
- 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 gradedqualityBmaintenanceEnables AI agents to safely query SQL databases through read-only tools for describing entities, reading records, and aggregating records, with view-based access and fail-closed per-user row-level security.MIT
- AlicenseNot gradedqualityCmaintenanceEnables AI agents to query Postgres, BigQuery and DuckDB read-only through policy-checked SQL, with AST-based guards that refuse writes and dangerous functions, column masking on the way out, and an audit log of every query. Also exposes schema browsing and query-planning tools so agents can see allowed tables, columns and costs before running anything.MIT
- AlicenseNot gradedqualityCmaintenanceEnables AI agents to securely discover database schemas and execute read-only SQL queries through guardrailed tools that block mutations and clamp result sizes.MIT