PostgreSQL operations as Python library, LangChain tools, and MCP server
Server has 17 tools with basic descriptions and input schemas, but significant quality gaps limit production readiness. All tools have descriptions (good), but many are generic and lack actionable guidance. Parameter descriptions are present but often minimal. Critical issue: params like 'params', 'data', 'where', 'columns' accept raw strings instead of structured types, forcing LLMs to construct JSON manually and increasing error likelihood. No output schemas documented. Error handling is absent, no recovery guidance, no categorization of retryable vs fatal errors. Tool naming is verb-noun compliant (run_query, list_tables, create_table), but composition issues exist: run_query and run_query_one are near-duplicates; insert_row, update_rows, delete_rows could benefit from batch variants. No tool annotations (readOnlyHint, destructiveHint) despite clear risk stratification in the data. Security concern: no evidence of SQL injection prevention or parameterized query enforcement in tool descriptions.
Add a column to a table. Args: table_name: Name of the table column_name: Name of the new column column_type: Column type definition (e.g., 'VARCHAR(255) NOT NULL') schema: Schema name (default: public)
Create an index on a table. Args: table_name: Name of the table columns: Comma-separated column names to index index_name: Name for the index (auto-generated if not provided) unique: Create a unique index schema: Schema name (default: public)
Create a new table. Args: table_name: Name for the new table columns: JSON array of column definitions, e.g.: [{"name": "id", "type": "SERIAL PRIMARY KEY"}, {"name": "email", "type": "VARCHAR(255) NOT NULL"}, {"name": "created_at", "type": "TIMESTAMP DEFAULT NOW()"}] schema: Schema name (default: public)
Delete rows from a table matching a WHERE clause. Args: table_name: Name of the table where: WHERE clause (without 'WHERE' keyword) schema: Schema name (default: public)
Get column information for a table. Args: table_name: Name of the table schema: Schema name (default: public)
String-typed parameters accept raw JSON instead of structured types. 'params', 'data', 'columns', 'where' are all strings, forcing LLMs to construct JSON manually. This increases parsing errors and SQL injection risk.
No output schemas documented. LLMs cannot predict response structure, forcing them to guess field names for downstream tool calls. Increases hallucination and context waste.
No error handling guidance. Descriptions do not explain what errors are retryable, what user input is needed, or how to recover. LLMs cannot self-correct on failures.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | C | 64 | 2026-07-28+ | v2 |
Drop a table. Args: table_name: Name of the table to drop schema: Schema name (default: public) cascade: Also drop dependent objects
Get active database connections.
Get the total size of the database.
Get indexes for a table. Args: table_name: Name of the table schema: Schema name (default: public)
Get size information for a table. Args: table_name: Name of the table schema: Schema name (default: public)
Insert a row into a table. Data is a JSON string of column:value pairs. Args: table_name: Name of the table data: JSON object with column:value pairs to insert schema: Schema name (default: public)
List all schemas in the database.
List all tables in a schema. Args: schema: Schema name (default: public)
Execute a SQL query and return results. Args: query: SQL query to execute params: Optional JSON array of parameters for parameterized queries
Execute a SQL query and return single row. Args: query: SQL query to execute params: Optional JSON array of parameters
Update rows in a table matching a WHERE clause. Args: table_name: Name of the table data: JSON object with column:value pairs to update where: WHERE clause (without 'WHERE' keyword) schema: Schema name (default: public)
Vacuum a table to reclaim space and update statistics. Args: table_name: Name of the table schema: Schema name (default: public) analyze: Also update statistics (default: True)
No tool annotations (readOnlyHint, destructiveHint, idempotentHint). Risk levels are clear in the data (READ_ONLY, WRITE, DESTRUCTIVE) but not exposed to the MCP client, preventing safety guardrails.
Duplicate/near-duplicate tools: run_query and run_query_one differ only in return cardinality. LLMs waste reasoning cycles choosing between them. Consolidate into one tool with an optional 'single_row' parameter.