The interesting part isn't the bug — it's the failure signature. HTTP 200 + error-in-body is the worst possible shape for a defect like this because it looks like user error, not a routing mismatch. You'd blame your Cypher query, not the key name being passed between layers.
The structural fix that prevents the whole class: typed input at the tool handler boundary. execute_cypher_query should accept a validated schema (Pydantic, dataclass, whatever), not raw args.get('cypher_query'). Then any caller passing the wrong key fails loudly at the call site instead of quietly downstream. Most MCP servers skip this because the happy path gets tested — the wrong-key path doesn't.