fix: return isError instead of throwing InternalError on chart failures#292
Conversation
When chart rendering fails (e.g., due to invalid/empty data), the catch
block threw McpError(InternalError) which maps to MCP error -32603.
MCP clients treat -32603 as a server crash, so agents cannot recover
or self-correct.
Changed to return { content: [...], isError: true } with a descriptive
error message. This lets agents understand what went wrong and retry
with corrected input. McpError and ValidateError are still thrown
(they produce proper MCP error responses).
This fixes the 9 tools that crash on empty/invalid data:
generate_fishbone_diagram, generate_mind_map, generate_organization_chart,
generate_flow_diagram, generate_network_graph, generate_funnel_chart,
generate_venn_chart, generate_district_map, generate_radar_chart
Fixes #291
There was a problem hiding this comment.
Code Review
This pull request updates the error handling in callTool.ts to return a structured error response instead of throwing an InternalError, which prevents MCP client crashes and allows agents to self-correct. Feedback was provided to improve the robustness of error message extraction by accounting for cases where the error might be a string.
|
How to verified with mcp-assert? it is a GitHub action? |
|
mcp-assert is both a CLI tool and a GitHub Action. CLI (quickest way to try it): # Install
brew install blackwell-systems/tap/mcp-assert
# or: npx @blackwell-systems/mcp-assert
# or: pip install mcp-assert
# Generate assertion stubs for all your tools
mcp-assert generate --server "npx -y @antv/mcp-server-chart" --output evals/
# Run them
mcp-assert run --suite evals/GitHub Action (for CI): - uses: blackwell-systems/mcp-assert-action@v1
with:
suite: evals/The assertion YAML files in this PR's linked issue (#291) were generated with |
|
you can help to add the action into ci. |
|
Happy to add the CI integration. I'll submit a follow-up PR after this one merges that adds:
The CI job will catch regressions on every push and PR. Once this fix lands, all 25 tools should pass (the 9 that currently crash will return Want me to wait for this PR to merge first, or submit both in parallel? |
|
Hi @hustcc, following up on your request to add CI integration. Happy to submit the follow-up PR with the |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #292 +/- ##
==========================================
- Coverage 82.10% 81.94% -0.17%
==========================================
Files 43 43
Lines 2040 2044 +4
Branches 34 34
==========================================
Hits 1675 1675
- Misses 363 367 +4
Partials 2 2
🚀 New features to boost your workflow:
|
|
I feel this is still an exception and should throw an error. The best solution is to avoid this error at the source, for example: solve the problem at the rendering layer, or restrict the input requirements in the JSON schema. |
|
Agree that fixing the source is ideal. Stricter JSON Schema validation and rendering-layer guards would prevent most of these errors from happening in the first place. But the two approaches complement each other. Even with perfect validation, unexpected errors can still occur (network issues, resource limits, edge cases in chart data). The MCP protocol distinguishes between these intentionally:
This PR converts unhandled exceptions into Happy to also help add stricter JSON Schema constraints for the tool inputs in a follow-up if that's useful. |
Summary
callTool.tsthrewMcpError(InternalError)which maps to MCP error -32603{ content: [...], isError: true }with a descriptive error messageMcpErrorandValidateErrorare still thrown as before (they produce proper MCP error responses)Tools fixed
All 9 tools from #291:
generate_fishbone_diagram,generate_mind_map,generate_organization_chart,generate_flow_diagram,generate_network_graph,generate_funnel_chart,generate_venn_chart,generate_district_map,generate_radar_chartBefore/After
Before: Agent receives
-32603with a raw stack trace:After: Agent receives
isError: truewith actionable message:{ "content": [{"type": "text", "text": "Failed to generate chart: Cannot read properties of undefined (reading 'category'). Please check that the data matches the expected format for this chart type."}], "isError": true }Test plan
tsc --noEmitpassesFixes #291