PostgreSQL MCP Server has solid tool naming, good parameter schemas with Zod validation, and clear descriptions that guide LLM selection. All 5 tools are explicitly registered with names, descriptions, and input schemas. However, output schemas are not formally documented in the code, descriptions lack some nuance around dependencies and limitations, and error handling could better guide agent recovery. The server properly wraps queries in transactions for safety and includes helpful metadata (schema defaults, nullable flags). Naming follows verb_noun convention (query, execute, list_tables, describe_table, list_schemas). Most tools fall in the 70-75 range individually.
Describe the columns and types of a specific table.
Execute a write SQL statement (INSERT, UPDATE, DELETE, CREATE, ALTER, DROP, etc.) against the PostgreSQL database.
List all schemas in the current database.
List all tables in the current database (public schema by default).
Execute a read-only SQL query against the PostgreSQL database. Use this for SELECT, SHOW, EXPLAIN statements.
Output schemas not formally documented. While code returns structured text responses via `content: [{ type: 'text', text }]`, the actual output shape (fields returned, limits, pagination) is not declared in tool definitions. LLMs cannot plan chained calls or extract structured data without knowing the response contract.
Error messages lack recovery guidance. When a query fails (e.g., 'Error: syntax error'), the response does not suggest next steps. For 'table not found', should LLM try list_tables()? For 'permission denied', is there a different approach? See code lines: `text: \`Error: ${err.message}\`` returns raw error without context.
Descriptions for destructive tools (execute) do not document idempotence or retry safety. The 'execute' tool modifies state but does not warn whether repeated calls with the same SQL are safe. A CREATE TABLE statement is not idempotent, but an INSERT with a unique constraint might be retried. Agents need to know this.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | B | 78 | 2026-07-28+ | v2 |
| 2026-03-09 | D | 56 | - | v1 |
No tool annotations (readOnlyHint, destructiveHint). The 'Risk' metadata in the evaluation (READ_ONLY vs DESTRUCTIVE) exists in the assessment but is NOT encoded in the tool schema itself. MCP supports tool annotations, these should be present in the actual tool definition to guide agent safety.
Parameter dependencies not documented. The 'schema' parameter (with default 'public') appears in list_tables and describe_table but the description does not explain when to override it, what happens if the schema doesn't exist, or how it chains with list_schemas(). Undocumented dependencies cause silent misuse.
No result limits documented. The query tool returns all rows without pagination, and describe_table returns all columns. Large tables could blow the context window. Descriptions should state 'Returned data is trimmed to 1000 rows for performance; use LIMIT clause for pagination.' or implement per-parameter limits.
Queries wrapped in transactions but read-only transaction may not prevent all side effects. The code uses 'BEGIN TRANSACTION READ ONLY' for safety, but the description does not explain this precaution. Agents should know that SELECT is truly safe here.