An MCP server for executing SQL queries against PostgreSQL databases with GitHub OAuth authentication and role-based access control
Three tools with generally well-structured definitions, good descriptions, and explicit schemas. Tools follow verb_noun naming convention (listTables, queryDatabase, executeDatabase). All three tools have non-empty descriptions (161-236 chars, within 10-1024 baseline). Schemas are present and properly typed. However, there are gaps: parameter descriptions are minimal, error handling is present but generic, and some security/composition concerns exist around the destructive tool design. The server demonstrates solid fundamentals but lacks the polish and completeness of an A-grade tool suite.
Execute any SQL statement against the PostgreSQL database, including INSERT, UPDATE, DELETE, and DDL operations. This tool is restricted to specific GitHub users and can perform write transactions. **USE WITH CAUTION** - this can modify or delete data.
Get a list of all tables in the database along with their column information. Use this first to understand the database structure before querying.
Execute a read-only SQL query against the PostgreSQL database. This tool only allows SELECT statements and other read operations. All authenticated users can use this tool.
queryDatabase and executeDatabase lack parameter constraints. The 'sql' parameter accepts free-form strings with minimal validation guidance. Description says 'SELECT queries only' for queryDatabase but provides no enum or regex to prevent LLMs from passing UPDATE/INSERT/DELETE. Validation happens at runtime (validateSqlQuery), not schema-time.
Parameter descriptions are missing. The 'sql' parameter in queryDatabase has description 'SQL query to execute (SELECT queries only)', adequate but sparse. No guidance on format, length limits, or expected structure. The rubric baseline shows 100% of A+ tools have descriptions for ALL params; this falls short.
executeDatabase is exposed as a runtime conditional tool (registered only if user is in ALLOWED_USERNAMES set). This is a security gate, but it violates tool composition, LLMs cannot reason about tool availability if tools appear/disappear. The tool should always be registered but return a 'permission denied' error for unauthorized users, enabling proper error recovery guidance.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | B | 70 | 2026-07-28+ | v2 |
| 2026-03-09 | D | 50 | - | v1 |
Output schema for queryDatabase and executeDatabase not documented. The tools return structured JSON (via createSuccessResponse), but the LLM has no formal schema for the response shape. The code shows 'content' array with 'type' and 'text' fields, but this is inferred from code inspection, not documented.
listTables returns raw information_schema.columns data with no pagination or limit. If a database has hundreds of tables and thousands of columns, the response could be massive, wasting tokens and risking context window exhaustion. No mention of result limits or pagination in description.
Error responses use generic handleError() with Sentry event IDs but lack actionable recovery guidance. The error message tells users to 'report to support' but does not guide the LLM on next steps (retry? different tool? user correction?). Errors should classify as retryable, user-fixable, or fatal.
No dry-run or confirmation mechanism for executeDatabase. This is a DESTRUCTIVE tool that can DELETE data, yet agents have no way to preview the impact before committing. A confirm_before_execute pattern would prevent catastrophic accidents.