A Model Context Protocol (MCP) server that enables secure interaction with SingleStore databases. This server allows AI assistants to list tables, read data, and execute SQL queries through a controlled interface, making database exploration and analysis safer and more structured.
The SingleStore MCP server has three tools with basic parameter schemas and docstring descriptions, but exhibits significant gaps against production-grade patterns. The `execute_query` tool is particularly problematic: it accepts arbitrary SQL with optional parameters but lacks input validation guidance, destructive operation warnings, and clear error recovery patterns. The `list_resources` tool has an empty input schema (correct), but the resource descriptions are generic. Parameter descriptions exist but are minimal (20-40 chars), well below the 72-char baseline for A+ tools. No tool declares read-only vs. destructive semantics explicitly (no toolAnnotations). The codebase shows basic error handling (HTTPException with detail messages) but does not categorize errors as retryable vs. fatal or guide LLM recovery. Overall definitions are functional for a prototype but lack the depth, clarity, and safety guardrails expected of production MCP servers.
Executes a custom SQL query with optional parameters.
Retrieves the contents of a specific table.
Lists all available tables in the database as MCP resources.
execute_query lacks destructive operation warnings. The tool description does not state 'This tool can modify, insert, or delete data', critical for agents to understand irreversibility and retry safety.
No tool annotations (readOnlyHint, destructiveHint, idempotentHint) present. Protocol supports marking tools with semantic risk; list_resources and get_resource should be marked readOnly; execute_query should be marked destructive. This requires explicit tool registration in the MCP server.
Parameter 'query' in execute_query has minimal description ('The SQL query to execute'). No validation rules, constraints, or safety guidance. Should include: expected format, SQL dialect specifics, injection safeguards, and parameterized query requirement.
Inferred effective spec: <=2025-11-25.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | D | 50 | <=2025-11-25 | v2 |
| 2026-03-09 | F | 0 | - | v1 |
Error handling is generic. Errors return HTTPException with detail strings but do not categorize as retryable, user-fixable, or fatal. Missing recovery guidance: 'If table not found, call list_resources() to see available tables.'
Parameter 'resource_id' in get_resource documented as 'The name of the table to query' (21 chars). Below the 72-char baseline for production tools. Should include: what constitutes a valid table name, schema-qualified names (schema.table), and how to discover available tables.
Output schema for list_resources and get_resource not explicitly documented. While responses include 'data' and 'id' fields, there is no JSON Schema definition visible. Production tools must declare return types and field semantics to guide LLM extraction logic.
No pagination or result limits. get_resource calls 'SELECT * FROM {resource_id}' without LIMIT. Large tables will return unbounded rows, exhausting context windows. Should include optional 'limit' and 'offset' parameters and document the max result set size.
SQL injection risk in get_resource. Line uses f-string: 'SELECT * FROM {resource_id}' after parameterized table existence check. Table name is user-provided and cannot be parameterized in most SQL dialects, but no whitelist or validation shown. Should validate against a discovered table list or use an allowlist.
execute_query parameters field is documented as 'Optional parameters for query substitution' but schema defines it as type 'object' with no field structure. LLM cannot reason about what keys or values are expected. Should document or reject.