MCP server for PostgreSQL — schema inspection and safe query execution
Three tools with clear verb-noun naming (list_tables, describe_table, run_query) and basic descriptions. All tools have input schemas with type definitions. However, descriptions are minimal (10-50 chars for list_tables and describe_table), falling below the 50-200 char LLM-optimized baseline. Parameter descriptions exist but lack detail on constraints, formats, and error recovery. No output schemas documented. Error handling is basic (ValueError for non-SELECT) without recovery guidance. No tool annotations (readOnlyHint, etc.). Composition is sound, each tool has one responsibility, but descriptions need expansion to guide LLM selection and parameter usage.
Return column names, types, and nullability for a given table. Args: table_name: Name of the table to inspect (must be in the public schema).
List all user tables in the public schema.
Run a read-only SELECT query and return results as a formatted table. Only SELECT statements are permitted. Any attempt to run INSERT, UPDATE, DELETE, DROP, or other mutating statements will be rejected. Args: query: A valid PostgreSQL SELECT statement.
Minimal descriptions for discovery tools. list_tables (10 chars) and describe_table (50 chars) lack context on when to call them, what they reveal, and how they chain to run_query. LLMs cannot infer discovery intent from bare names.
No output schemas documented. Tools return strings (list_tables, describe_table, run_query) but LLMs cannot parse unstructured text reliably. Returning structured JSON (e.g., {tables: [string], columns: [{name, type, nullable}], rows: [object]}) enables downstream tool chaining and reduces parsing errors.
run_query lacks pagination and result limits. Large result sets (1000+ rows) will blow context windows. No mention of max rows returned or offset/limit parameters. Baseline pattern requires pagination for list-returning tools.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | D | 53 | 2026-07-28+ | v2 |
Error handling is minimal. run_query rejects non-SELECT with ValueError but provides no recovery guidance. describe_table returns a string on table not found instead of a structured error. No error classification (retryable vs user-fixable vs fatal) to guide agent behavior.
No tool annotations. Tools lack readOnlyHint, destructiveHint, or idempotentHint metadata. All three are read-only and idempotent, but this is not declared in the schema, forcing LLMs to infer safety from descriptions alone.