MCP server that exposes granular tools for querying financial data via SQL and Neo4j knowledge graphs. Provides two-step SQL workflow: retrieve schema then execute queries, with safety guardrails for read-only operations.
The server exposes 2 tools with functional descriptions and clear workflow intent. However, there are significant gaps in schema documentation, parameter type clarity, and error handling guidance. Tool names are action-oriented (get_, run_) but descriptions are verbose and procedural rather than declarative. Input schemas are present but lack formal JSON Schema structure. Output format is plain text rather than structured JSON, making downstream tool chaining difficult. The server enforces read-only constraints well but does not guide recovery from common errors (e.g., missing tables, schema mismatches).
STEP 1 OF 2 — MANDATORY INTERMEDIATE STEP. This tool returns table schemas only. You MUST always follow this with run_sql_query() to get actual data. NEVER present the schema output to the user as a final answer. Search for relevant SQL tables based on the user's question. Returns CREATE TABLE definitions for the identified tables. ARGUMENTS: - question: The original user question. - search_terms: Key business entities or table names from the question. Example: For "Who bought iPhones?", search_terms=["customers", "products", "iPhone"]. WORKFLOW (you must complete ALL steps): 1. Call get_sql_schema() ← you are here 2. Read the returned schema carefully. 3. Write an accurate SQL SELECT query using only the columns that exist in the schema. 4. Call run_sql_query() with your SQL — this is the only way to get real data. 5. Present run_sql_query() results to the user.
STEP 2 OF 2 — Execute a SQL query and return the actual data to the user. This is the FINAL step. Always call this after get_sql_schema(). The results from this tool are what you present to the user as your answer. Executes a read-only SELECT query on the MySQL database. Returns results as a formatted table. RULES: - Only SELECT, SHOW, DESCRIBE, EXPLAIN are allowed. - Always use the exact column and table names from the schema returned by get_sql_schema().
Output schemas not documented. Both tools return plain-text strings instead of structured JSON objects. LLMs cannot reliably extract field values or plan downstream operations. LLMs need to know what fields to expect so they can plan downstream tool calls and extract the right data.'
Input parameter 'search_terms' in get_sql_schema lacks formal type definition in visible schema. The code shows list[str] in Python, but no JSON Schema 'items' constraint or enum of known tables is visible.
Descriptions are procedural and verbose (150+ chars) rather than declarative. Example: 'STEP 1 OF 2, MANDATORY INTERMEDIATE STEP...' reads like a user manual, not a tool description for LLM selection.
Inferred effective spec: <=2025-11-25.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | D | 55 | <=2025-11-25 | v2 |
| 2026-03-09 | F | 49 | - | v1 |
Error messages are generic and do not guide recovery. Example: 'Error in get_sql_schema: {e}' leaves the agent with a stack trace. A raw error code or stack trace gives the agent nothing to act on.' Missing recovery guidance like 'Try search_terms=["table_name"] for specific tables.'
Tools are tightly coupled: get_sql_schema and run_sql_query form a mandatory 2-step workflow. The description for get_sql_schema explicitly instructs the LLM to call run_sql_query next, violating tool autonomy.
The 'query' parameter in run_sql_query has no stated format constraints, length limits, or examples in the description.
No pagination support. Neither tool implements limit, offset, or result count parameters. If a query returns 10,000 rows, the agent receives all of them, potentially exhausting context.
run_sql_query has no dry-run or confirmation step for destructive operations. Although the tool enforces read-only checks, if a future iteration adds INSERT/UPDATE, there is no safety gate.
The 'question' parameter in get_sql_schema is not constrained (no max length, no format). LLMs could pass arbitrarily long or malformed prompts. Validate inputs early and return clear error messages.'