fix(mcp-server): return tool errors as isError results per MCP spec#1458
fix(mcp-server): return tool errors as isError results per MCP spec#1458
Conversation
|
Coverage Impact This PR will not change total coverage. Modified Files with Diff Coverage (1)
🛟 Help
|
4ba700a to
91ca294
Compare
| try { | ||
| return await handler(args as TArgs, extra); | ||
| } catch (error) { | ||
| const message = error instanceof Error ? error.message : String(error); |
There was a problem hiding this comment.
I think JSON.stringify(error) is better than String(error) to avoid returning things like "[object]"
8356eaf to
3be6265
Compare
Code review1 issue found — weak assertions in 4 test files. Weak
|
Per the MCP specification, tool execution errors should be reported within the result object (isError: true) rather than thrown as protocol-level errors. This ensures the LLM receives the actual error message and can handle it appropriately. See: https://modelcontextprotocol.io/docs/concepts/tools Co-Authored-By: Claude Opus 4.6 <[email protected]>
Co-Authored-By: Claude Opus 4.6 <[email protected]>
JSON.stringify returns undefined for undefined/Symbol/Function values, and throws on circular references. Add fallback to String() for both cases to ensure error message is always a string. Co-Authored-By: Claude Opus 4.6 <[email protected]>
Replace expect.any(String) with exact expected value since the output is deterministic (JSON.stringify of the thrown object). Co-Authored-By: Claude Opus 4.6 <[email protected]>
d8be9b9 to
ff13fbe
Compare
## @forestadmin/mcp-server [1.8.1](https://github.com/ForestAdmin/agent-nodejs/compare/@forestadmin/[email protected]...@forestadmin/[email protected]) (2026-02-12) ### Bug Fixes * **mcp-server:** return tool errors as isError results per MCP spec ([#1458](#1458)) ([4703cb8](4703cb8))

Summary
tool-with-logging.tsand return them as{ isError: true }results instead of throwingProblem
When a tool handler throws an error, the MCP SDK catches it and may replace the original message with a generic text. This means the LLM client receives an unhelpful error message and cannot adapt its behavior.
Solution
By returning
{ content: [{ type: 'text', text: message }], isError: true }instead of throwing, the error message is preserved and forwarded to the LLM as-is.Test plan
yarn workspace @forestadmin/mcp-server test— 483 tests passyarn workspace @forestadmin/mcp-server lint— 0 errors🤖 Generated with Claude Code