An MCP server that provides SQL database connectivity for Highrise CRM and other JDBC-compatible data sources, exposing table metadata and query execution as tools
This server exposes three data-discovery tools (get_tables, get_columns, run_query) with moderate documentation. Tool names are clear and verb-prefixed (get_, run_), and all three tools have descriptions and declared input schemas. However, parameter descriptions are minimal or missing, output schemas are not documented, and error handling is sparse. The server returns CSV-formatted text rather than structured objects, which forces LLMs to parse unstructured output. Most parameters lack format constraints, range limits, or guidance on valid inputs. The implementation uses a custom Java framework with STDIO transport only, which caps the protocolReadiness score to 50 maximum.
Retrieves a list of fields, dimensions, or measures (as columns) for an object, entity or collection (table). Use the `get_tables` tool to get a list of available tables. The output of the tool will be returned in CSV format, with the first line containing column headers.
Retrieves a list of objects, entities, collections, etc. (as tables) available in the data source. Use the `get_columns` tool to list available columns on a table. Both `catalog` and `schema` are optional parameters. The output of the tool will be returned in CSV format, with the first line containing column headers.
Execute a SQL SELECT statement. Use the `get_tables` tool to get a list of available tables, and the `get_columns` tool to list table columns. The SQL dialect is mostly based around SQL-92. Identifiers should be quoted using `""` characters. Valid clauses: FROM, INNER JOIN, LEFT JOIN, GROUP BY, ORDER BY, LIMIT/OFFSET. The output of the tool will be returned in CSV format, with the first line containing column headers.
Output schemas not documented. Tools return CSV-formatted text, but LLMs cannot infer field names, types, or structure without explicit documentation. This forces LLMs to guess at output shape and parse unstructured strings, increasing errors.
Unstructured output format (CSV). Tools return raw CSV text instead of structured JSON objects with typed fields. This wastes tokens on parsing overhead, makes it harder for LLMs to extract specific fields, and risks misalignment with downstream tool parameters.
Parameter descriptions are sparse or generic. The 'catalog' and 'schema' parameters in get_tables and get_columns have one-sentence descriptions but lack guidance on when they are optional, what values are valid, or how to discover available catalogs/schemas.
Inferred effective spec: <=2025-11-25.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | D | 51 | <=2025-11-25 | v2 |
| 2026-03-09 | F | 35 | - | v1 |
run_query description duplicates the sql parameter description verbatim. The tool description repeats SQL dialect constraints, valid clauses, and identifier quoting rules that already appear in the 'sql' parameter description. This is redundant and suggests the parameter description was copied without clean separation of concerns.
No error handling guidance. Exceptions are caught and re-thrown with generic RuntimeException('ERROR: ' + message), providing no recovery path, classification, or context for the LLM. If a query fails or a table is not found, the LLM has no actionable next step.
No result limits or pagination. The tools do not document or enforce a maximum result size. If a database has 10,000 tables or a query returns millions of rows, the response will be enormous, exhausting the context window and degrading LLM reasoning.
No input validation or constraint documentation. The 'sql' parameter in run_query accepts freeform strings with no length limit, regex pattern, or explicit constraints. An LLM could pass a 1 MB SQL statement or a DROP TABLE command without rejection. Missing safety guardrails.
Destructive operations (run_query) lack confirmation or dry-run. The 'run_query' tool accepts any SELECT statement, but a malicious LLM prompt or a typo could inject UPDATE, DELETE, or DROP commands if the database connection has write privileges. No confirmation step or read-only enforcement.