MCP stdio server that gives AI agents access to Postgres, MySQL, Redshift and SQL Server — with SSH/AWS SSM tunnels and pluggable secret providers (env, Vault, AWS Secrets Manager, RDS IAM).
db-access-mcp demonstrates strong engineering fundamentals with consistent schema definitions, clear descriptions, and thoughtful parameter design across 11 tools. All tools have names starting with action verbs (list_, query, connection_*), comprehensive parameter descriptions, and documented input schemas. Output handling is explicit (e.g., max_rows truncation, CSV/JSONL export formats). However, several patterns from the 54 Agentic Tool Patterns are underutilized: error recovery guidance is minimal, no tool annotations (readOnlyHint/destructiveHint), and responses lack some chaining IDs that would enable seamless multi-tool workflows. The tool set is well-composed with clear responsibility boundaries (query vs query_to_file vs query_plan), but descriptions could be tightened to align with the 10-200 character baseline for A+ tools. Risk annotations (READ_ONLY, WRITE, REVERSIBLE) suggest security awareness but are not formally exposed in schema.
Re-read the configuration files (config.json + conf.d/*.json, or --config <file>) into the running server, so connections and tunnels added or edited on disk become usable WITHOUT a restart. Open pools and running tunnels are never touched: they keep their previous definition until they are closed (idle timeout, down_tunnel, shutdown) and are reported in "warnings". Returns the files that were read plus the connections/tunnels added, removed and changed. On an invalid config nothing is swapped — the server keeps running on the previous configuration and the validation errors are returned.
Find configured database connections by parameters: host, port, database, type, read_only and/or metadata key-value pairs. All provided filters are combined with AND. Username/password filters are ignored. Returns the same sanitized shape as connection_list.
List configured database connections (postgres, mysql, redshift). Returns key, type, description, read_only flag, host/port/database and metadata. Credentials are never included. Use the returned key with the query, query_plan and up_tunnel tools.
Test a configured connection end-to-end: resolves secrets, opens the tunnel if configured, connects and runs a one-row server-info query. Returns ok=true with server version, user, database and latency — or ok=false with the failure code and hint (an unreachable database is a valid test result, not a tool error).
Error handling lacks recovery guidance. Tools return errors but do not guide the LLM on what to do next (e.g., 'Connection failed. Try connection_test() first' or 'Invalid query syntax. Verify with query_plan()'). Raw error codes and failure messages do not enable agent self-correction.
Tool annotations missing. Destructive tools (query with WRITE, query_to_file, down_tunnel, config_reload) lack destructiveHint annotations in schema. Read-only tools (query with SELECT, dialect_list, connection_list) lack readOnlyHint. This prevents LLMs and UI clients from routing to confirmation flows or marking tools as safe for autonomous execution.
Inferred effective spec: <=2025-11-25.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | C | 63 | <=2025-11-25 | v2 |
List the database dialects this server supports. Returns each dialect name (usable as the "type" field of a connection in the config), its default port and the execution-plan format produced by query_plan.
Close a tunnel previously opened with up_tunnel, by its tunnel_id. By default only the up_tunnel pin is released: if live connection pools still use the tunnel it stays open and their keys are returned in remaining_holders. With force=true the holder pools are drained and the tunnel is closed unconditionally (the next query recreates them).
Execute a SQL query on a configured connection (use connection_list to discover keys). Results are truncated to max_rows (default from config, typically 1000) with truncated=true set; add LIMIT for large tables. Connections marked read_only reject writes at the session level. Multi-statement scripts are passed to the driver as-is (for mysql they require multipleStatements enabled in the connection options).
Get the execution plan (EXPLAIN) for a SQL query without running it. postgres/mysql return a JSON plan; redshift returns a text plan (Redshift supports neither FORMAT JSON nor EXPLAIN ANALYZE, and its cost numbers are relative — do not compare them to postgres costs).
Execute a SQL query and write the full result to a file (csv or jsonl) instead of returning rows — use this for large exports that must not go through the model context. Relative file_path resolves under the export dir (default /tmp/db-access-mcp/exports); absolute or ~-prefixed paths must fall under the export dir or a configured allow_export_paths root. Parent directories are created. Existing files are not overwritten unless overwrite=true. postgres/mysql stream rows (no row limit by default); redshift/mssql buffer in memory and are capped at 100_000 rows.
List the tunnels currently open in THIS MCP instance, with a live health probe each. tunnel_id is accepted by down_tunnel; "connections" are the pools holding the tunnel, "pins" are up_tunnel holds. Configured-but-not-open tunnels are visible via connection_list (the tunnel field).
Open (or reuse) the tunnel configured for a connection WITHOUT connecting to the database. Returns the local host/port to connect through and a tunnel_id for down_tunnel. The tunnel is closed by down_tunnel, on idle timeout or when this MCP instance exits. Pass local_port to bind an exact local port; this fails if the tunnel is already open on a different port or the port is taken.
Some descriptions exceed recommended length (80+ chars is acceptable, but descriptions like connection_find at ~200 chars and query_to_file at ~300 chars waste tokens for secondary details that could live in implementation docs). Examples include complex path resolution rules and credential-filtering notes that LLMs rarely need during planning.
Limited chaining support. Response schemas do not explicitly document which IDs/references are returned to enable downstream tool calls. For example, connection_list returns 'key', but it is not labeled as the identifier that query, query_plan, and tunnel tools require. Agents must infer this dependency.
No confirmation/dry-run pattern for irreversible operations. Tools like query (with DELETE/DROP/TRUNCATE) and config_reload (which swaps configuration) modify state with no pre-execution approval step. Agents can accidentally destroy data.
Parameter validation rules not documented. The query tool accepts arbitrary SQL and timeout_ms without stating bounds. query_to_file accepts file_path without documented rules for path traversal safety (although implementation notes mention validation). LLMs cannot infer these constraints and may pass invalid values.