A single-binary MCP server for MySQL, MariaDB, PostgreSQL, and SQLite with PII redaction and write-prevention
dbmcp provides 13 tools with consistent naming (verb_noun pattern: list*, read*, create*, drop*, write*, explain*) and structured JSON Schema input definitions. However, tool descriptions are extremely terse (6-32 characters), parameter descriptions lack actionable constraints (format, range, allowed values), and output schemas are not documented. The server implements database-agnostic patterns (MySQL, PostgreSQL, SQLite) with proper risk classification (READ_ONLY, WRITE, DESTRUCTIVE) and error handling via rmcp framework. No tool annotations (readOnlyHint/destructiveHint) are visible in the source, and critical parameter relationships (database requirement in 'unpinned mode') are mentioned in descriptions but not enforced via schema constraints. All tools are explicitly defined with input schemas, so no inference penalty applies.
Create a new database
Drop a database
Drop a table
Get execution plan for a query
List all databases
List functions in a database
List materialized views in a database
List procedures in a database
Tool descriptions are critically short (6-32 characters). LLMs cannot determine when or why to select each tool, and cannot distinguish between similar list_* tools.
No output schemas are documented. LLMs cannot plan downstream calls or know what fields to expect. For example, readQuery likely returns rows/columns, but without explicit schema definition, agents must guess structure. This violates the requirement that 100% of A+ tools have documented return types.
Inferred effective spec: <=2025-11-25.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | D | 56 | <=2025-11-25 | v2 |
List tables in a database
List triggers in a database
List views in a database
Execute a read-only query
Execute a write query (INSERT, UPDATE, DELETE, etc.)
Parameter descriptions lack actionable constraints. 'Database name (required only in unpinned mode)' is vague, what is 'pinned mode'? How do clients know which mode they're in? What format is valid for database name (alphanumeric only, max length, reserved words)? Rubric requires format, range, and constraint specifications in parameter descriptions.
No tool annotations visible. Risk classifications (READ_ONLY, WRITE, DESTRUCTIVE) are documented in the data but not exposed as tool annotations (readOnlyHint, destructiveHint, idempotentHint). This prevents MCP clients from marking destructive tools (dropDatabase, dropTable) with visual warnings or confirmation gates.
readQuery and writeQuery accept arbitrary SQL strings without validation visible in schema. No constraints on query type (SELECT for readQuery, INSERT/UPDATE/DELETE for writeQuery). LLMs could pass UPDATE queries to readQuery or vice versa. Parameter description should enumerate allowed operations or include a regex pattern.
No pagination support visible in list_* tools (listDatabases, listTables, listViews, etc.). If a database contains thousands of tables, does the tool return all of them? Rubric requires paginated results with limit and offset/cursor, especially for discovery tools that could return large result sets.
Error handling messages not visible in source. When a query fails or a database is not found, what error does the tool return? Does it guide the LLM on recovery ('Database not found. Try listDatabases() first.')? Rubric requires error responses to be actionable and categorize errors as retryable/user-fixable/fatal.