A Model Context Protocol server for SQL databases, supporting PostgreSQL, MySQL, and SQLite with read-only and write query execution, table introspection, and database information retrieval.
The SQLx MCP server provides 5 tools with basic schemas and descriptions, but falls short of production quality. All tools have descriptions (10 - 67 chars), which is adequate but minimal. Input schemas are present but lack depth: parameters have type declarations but descriptions are sparse or generic. Tool names follow verb_noun convention (get_*, list_*, execute_*), which is correct. However, critical issues undermine quality: (1) no output schemas documented anywhere, LLMs cannot know what fields to expect from tool responses, (2) parameter descriptions are often one-liner generic text that does not explain purpose or constraints, (3) no error handling guidance, error responses will not direct LLMs to recovery actions, (4) no pagination support despite tools like list_tables returning unbounded lists, (5) security concerns around database_url parameter exposed as a tool input (though fallback to env var mitigates somewhat), (6) no idempotency guidance for write operations, and (7) no input validation constraints (enum/pattern/min-max) despite accepting SQL queries directly. The execute_write_query tool marked as IRREVERSIBLE but has no confirmation or dry-run capability. Average per-tool score: 52.
Execute read-only SQL query (SELECT, WITH, SHOW, DESCRIBE, EXPLAIN)
Execute write SQL query (INSERT, UPDATE, DELETE, CREATE, DROP, ALTER)
Get database basic information
Get table structure information
List all tables with metadata (name, comment, row count, etc.)
No output schemas documented. Tools return data but LLMs cannot know field names, types, or structure in advance. This forces runtime discovery and risks context loss when fields are missing. Every tool must declare what it returns.
execute_write_query is marked IRREVERSIBLE but has no confirmation step or dry-run mode. Agents cannot verify before destructive operations (DROP TABLE, DELETE). This violates the confirmation-request pattern.
Parameter descriptions lack detail. 'Database URL to connect to (optional, falls back to command line or environment variable)' is present in all tools but does not explain format, valid protocols (postgresql://, mysql://, sqlite://), or what happens if both env var and parameter are set. Ambiguous parameter guidance invites errors.
Inferred effective spec: <=2025-11-25.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | D | 58 | <=2025-11-25 | v2 |
| 2026-03-09 | F | 37 | - | v1 |
No pagination support or result limits. list_tables() can return unbounded rows. Large result sets blow context windows and dilute signal. Baselines show paginated tools accept page/limit and return total_count or next_cursor.
No error handling guidance. Tools will return errors (connection failed, syntax error, permission denied) but LLMs cannot determine if the error is retryable, user-fixable, or fatal. Errors must categorize and suggest recovery actions.
execute_readonly_query and execute_write_query accept free-form SQL strings with no validation constraints. LLMs can pass SQL injection payloads, malformed syntax, or queries forbidden by policy (e.g., schema changes in read-only tool). Input must be validated with clear error messages.
database_url exposed as a tool parameter. While fallback to env var/CLI provides some protection, passing credentials in tool params risks leaking them into logs and prompt history. Use server-side secret injection only; database_url should not be a parameter.
No tool composition guidance. If an agent wants to 'insert data into table X', it must call list_tables, get_table_structure, then execute_write_query. These steps should be chained automatically (get_table_structure response should include enough info to guide INSERT). Missing chaining IDs or context.
execute_write_query offers no idempotency guidance. Agents retry on ambiguous failures. If an INSERT succeeds but response times out, a retry inserts a duplicate row. Tool must declare idempotency or provide conflict handling (ON DUPLICATE KEY, upsert semantics).