A Spring Boot-based MCP server that provides SQL query execution and data visualization capabilities across multiple database types (MySQL, Oracle, SQL Server). It uses an LLM (Ollama) to generate SQL from natural language and Python for visualization.
This Java/Spring Boot HTTP MCP server exposes 6 database tools with moderate structural quality but significant gaps in LLM-optimization. Tool names are clear and verb-prefixed (list, connect, insert, delete, execute, disconnect), meeting basic naming standards. However, parameter descriptions are sparse, output schemas are entirely undocumented, and error handling provides no recovery guidance. The server relies on deprecated Sampling and Roots patterns without evidence of current spec alignment. Most critically, the execute() tool returns 'generated visualization (PNG as base64 data URL)' but no output schema is visible in code, forcing LLMs to guess response structure. Connection credentials (password, username) are exposed as required parameters in insert(), violating secret injection rules. The schema quality varies: insert() has detailed enum and type definitions, but connect(), delete(), and disconnect() use QUERY_PARAMETER types without clear descriptions of how the LLM should construct these. Average per-tool score: 42/100.
Establish a connection to a specific database by type and connection ID. Returns a token for subsequent operations.
Delete a stored database connection by type and ID
Close a database connection by token
Execute a natural language query against a connected database. Returns SQL markdown and a generated visualization (PNG as base64 data URL).
Add a new database connection (MySQL, Oracle, or SQL Server). Validates connectivity before saving.
List all database connections across all database types (MySQL, Oracle, SQL Server)
Output schemas entirely undocumented. The execute() tool claims to return 'SQL markdown and generated visualization (PNG as base64 data URL)' but no schema is visible. LLMs cannot plan downstream actions or extract structured data without documented return types.
Credentials exposed as required parameters. insert() accepts username, password, host as required string parameters. Per pattern:secret-injection, these must never appear in tool signatures, use server-side secret injection or encrypted vault storage. Agent traces will log these credentials.
QUERY_PARAMETER inputs lack actionable descriptions. connect(), delete(), and disconnect() use type='QUERY_PARAMETER' but do not explain HOW the LLM should construct these (URL query string format, comma-separated, etc.). Parameter descriptions are minimal ('Database type', 'Connection ID to delete'), under the baseline 72-char average and lack usage context.
Inferred effective spec: <=2025-11-25.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | F | 38 | <=2025-11-25 | v2 |
| 2026-03-09 | F | 47 | - | v1 |
No error handling guidance. Tool descriptions do not explain failure modes, recovery steps, or when to retry. For example, insert() may fail if the database is unreachable, but the description offers no hint about what error to expect or how to recover.
execute() tool output claim is vague. Description says 'Returns SQL markdown and a generated visualization (PNG as base64 data URL)' but the response structure, field names, and whether visualization generation is always successful are undocumented. LLMs cannot validate or extract this data reliably.
No pagination or result limits documented. list() tool description does not specify: how many connections it returns, whether results are paginated, or what the maximum result size is. Without pagination, large result sets will exhaust context windows.
Irreversible delete operation lacks confirmation pattern. delete() removes a stored connection permanently, but tool definition includes no mention of dry-run, confirmation, or undo capability. Agents may accidentally delete connections without user approval.
Missing idempotency and transactionality guarantees. The connect() tool description does not state whether repeated calls with the same parameters reuse an existing token or create new connections. This affects retry logic and agent planning.