Two design choices carry this. Running several named queries in one call collapses the usual back-and-forth where an agent asks a question, gets a number, and needs three more round trips to make sense of it. And the read-only guarantee is parsed from the SQL's syntax tree rather than pattern-matched, which is what makes it hold against a comment-wrapped write. The author still recommends a read-only database user on top — defence in depth, not a substitute for it.
A database MCP server built around three complaints about the others: one query per call, connection details repeated every time, and results double-encoded inside JSON strings. Connections are pre-registered at startup, several named queries run in one call, and rows come back as compact TSV inside a structured envelope. Every statement is parsed by SQLGlot before execution and writes are blocked.
- `execute` — the core tool: a batch of named queries against one default connection, returning per-query rows, a truncation flag and timing, with pagination
- `search_objects` for schema exploration at three detail levels, plus `login`, `logout` and `list_connections` for connection management, where the listing shows project, environment, database and type but never a DSN or password
- Five database engines from one install with all drivers bundled: PostgreSQL and SQLite natively async, MySQL and MariaDB, Oracle, and SQL Server
- Read-only enforced at the AST level, not by keyword matching — INSERT, UPDATE, DELETE, DROP, TRUNCATE, ALTER, CREATE, GRANT and REVOKE are blocked, multi-statement attacks and comment-wrapped writes are caught, and SELECT, UNION, EXPLAIN, SHOW, DESCRIBE and PRAGMA are allowed
- Error messages enriched with context — a wrong column name comes back with a did-you-mean suggestion and the available columns with their types, instead of a bare failure
- TSV as the default row format, which the project measures at 40-60% fewer tokens than JSON rows for a 100-row, 5-column result, with `format="json"` available when you want column names on every row
- Pre-registered connections through `--register` in the MCP config, so the agent can query immediately without calling login first
Database credentials for whatever you connect to. `pip install a2db` brings every driver with it. Register connections at launch — `claude mcp add -s user a2db -- a2db-mcp --register myapp/prod/main 'postgresql://user:${DB_PASSWORD}@host/mydb'` — or run `a2db-mcp` bare and let the agent call login on demand. Passwords use `${ENV_VAR}` syntax inside the DSN and are expanded only at connection time, so the secret stays in your environment rather than on disk; saved connections live as TOML files under `~/.config/a2db/connections/`. It currently runs as a local stdio server inheriting the environment of whatever launched it; remote HTTP transport with OAuth is listed as planned. Write support exists in the core but is deliberately not exposed over MCP yet. Apache 2.0 licensed.
One command plus a key — pip install a2db, then supply credentials
