MCP server for exploring and querying SQLite databases with safety controls
Four tools with clear names and basic descriptions. All tools have input schemas with type definitions. However, parameter descriptions are minimal or absent (e.g., 'run_query' has only 'A read-only SELECT SQL statement' for the 'sql' param, lacking format/constraint guidance). Output schemas are undocumented, LLMs cannot infer what fields to expect from responses. Error handling is present in code but not surfaced in tool descriptions. No tool annotations (readOnlyHint, destructiveHint). Descriptions average ~120 chars, within acceptable range but lack actionable detail on when/why to use each tool.
Describe the columns of one table: name, type, and whether it is required.
List the names of every table in the database.
Check that the server is alive.
Run a read-only SELECT query and return the rows. At most 500 rows come back; if the query matched more, "truncated" is true and you should add a LIMIT or aggregate instead. Queries running longer than 5 seconds are aborted.
Output schemas undocumented. LLMs cannot infer response structure (e.g., run_query returns dict with 'rows', 'truncated', 'error' fields, but this is invisible in tool definition). Agents cannot plan downstream operations without knowing what fields to extract.
Parameter descriptions lack actionable constraints. 'sql' param in run_query says 'A read-only SELECT SQL statement' but does not specify: max query length, timeout behavior (5s mentioned in tool description, not param), or what happens if query exceeds 500 rows. LLMs cannot self-correct invalid input.
No tool annotations. All tools are read-only (risk=READ_ONLY in metadata), but tool definitions lack readOnlyHint annotation. Agents cannot distinguish safe tools from destructive ones without external metadata.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | D | 57 | 2026-07-28+ | v2 |
Error handling not surfaced in descriptions. Code validates SQL (only SELECT allowed), enforces timeouts, and blocks sensitive columns, but tool descriptions do not explain what errors to expect or how to recover. E.g., 'run_query' does not mention ValueError for non-SELECT or DatabaseError for timeout.
describe_table parameter 'table' lacks enum or discovery hint. LLMs must call list_tables first to learn valid table names, but tool description does not guide this dependency. No error message suggests 'call list_tables() first'.