fix(mcp): return isError=True on tool failures - #2715
Conversation
There was a problem hiding this comment.
Graphify reviewed this change.
Looks safe to merge — no coupling regressions and no blocking issues, checked against the code graph (not a self-assessment).
Formal verification. No changes could be formally verified in this run.
Graphify review — findings
This PR changes the call_tool function in graphify/serve.py to return a types.CallToolResult object directly instead of a raw list of TextContent. In the error and unknown-tool paths, it now sets isError=True on the returned result. The _on_call_tool handler is updated accordingly to pass through the result rather than wrapping the previous list return value.
No blocking issues surfaced. 3 lower-confidence candidates did not survive cross-model review.
Analysis details — impact, health, verification
Impact & health
Graphify review
Impact — 435 functions depend on the 114 functions this change touches.
Health — grade A; 10 existing hotspot(s) in the area this change touches (pre-existing, not introduced here):
dispatch_command()— 2 callers, 117 callees (high)_query_graph_text()— 18 callers, 8 callees (high)_score_query()— 15 callers, 5 callees (high)_query_terms()— 17 callers, 3 callees (high)run_benchmark()— 16 callers, 3 callees (high)_build_server()— 2 callers, 16 callees (high)_load_graph()— 9 callers, 3 callees (medium)_query_subgraph_tokens()— 7 callers, 3 callees (medium)- …and 2 more
Verification — 435 functions in the blast radius were not formally verified this run (proofs are advisory here).
Gate & verification
graphify gate
PASS — objectively clean (no health regressions, tests not run — proofs not run this pass (advisory)). Grounded, not self-assessed.
Advisory (not blocking):
- verification_scope: 285 function(s) in the blast radius were not formally verified this run
Formal verification
Could not verify: Could not verify \_build\_server.
The verifier did not have enough to check \_build\_server, so it is saying so rather than guessing. No false assurance is the whole point.
Guarantee: No guarantee either way, this is an honest abstention, not a pass.
Note: Reason: not verifiable: all 23 sampled inputs raised on both versions — the function never executed, so 'no divergence' would be vacuous (mostly ImportError — names the real obstacle, not a sampling gap)
Fixes #2714