---
title: "Discussion on \"MCP Tool Error Handling: 5 Calls, One Failure Hidden as Success\" | Hashnode"
description: "Discussion on \"MCP Tool Error Handling: 5 Calls, One Failure Hidden as Success\". A reproducible TypeScript SDK test of isError, thrown handlers, and unknown tools"
url: "https://hashnode.com/posts/mcp-tool-error-handling-5-calls-one-failure-hidden-as-success/6af181e5dca8f65f12d06742"
---

[Feed](https://hashnode.com/feed) /

Discussion

# [MCP Tool Error Handling: 5 Calls, One Failure Hidden as Success](https://reliable-agent-notes.hashnode.dev/mcp-tool-error-handling-5-calls-one-failure-hidden-as-success?utm_source=hashnode&utm_medium=feed)

A reproducible TypeScript SDK test of isError, thrown handlers, and unknown tools

4d ago · 9 min read · reliable-agent-notes.hashnode.dev  
Read the article

-   [#mcp](https://hashnode.com/tag/mcp)
-   [#typescript](https://hashnode.com/tag/typescript)
-   [#testing](https://hashnode.com/tag/testing)
-   [#ai-agents](https://hashnode.com/tag/ai-agents)

## Written by

[Daniel Martin](https://hashnode.com/@averyellistech)

@averyellistech

  
[View profile](https://hashnode.com/@averyellistech)

Writing about developer experience, APIs, and reliable agent workflows.

I build AgentSEO.dev and write about developer tools, APIs, and reliable agent workflows.

## Responses 5

Markdown supported · ⌘↵ to post

[Kartik N V J K](https://hashnode.com/@kartik-nvj)

[3d ago](https://hashnode.com/posts/mcp-tool-error-handling-5-calls-one-failure-hidden-as-success/6af181e5dca8f65f12d06742/comment/6af3554df452f9a8a3de40d1)

I did not expect the unknown-tool row. The spec describes it as a JSON-RPC protocol error, and your SDK 1.26.0 fixture got a resolved result carrying isError true instead, so the split I was treating as reliable, protocol rejection versus tool failure, depends on the SDK version. I hit something similar chasing retry behavior across MCP servers, so a pinned version-specific test reads like the only safe answer.

[AI Developer](https://hashnode.com/@lycore)

[4d ago](https://hashnode.com/posts/mcp-tool-error-handling-5-calls-one-failure-hidden-as-success/6af181e5dca8f65f12d06742/comment/6af260e1329931c7e4fa8646)

The distinction between a resolved call and a successful operation is easy to miss. In addition to checking isError, a client can validate a strict success schema and treat absent required fields or an unexpected error envelope as an integration failure, not as an empty successful result. It would be useful to add malformed JSON and a valid JSON object with the wrong shape to the fixture, and assert that neither reaches the next tool. Keeping protocol errors, flagged tool failures, and schema failures as separate telemetry categories would also make version changes easier to diagnose.

[Daniel Martin](https://hashnode.com/@averyellistech)

[4d ago](https://hashnode.com/posts/mcp-tool-error-handling-5-calls-one-failure-hidden-as-success/6af181e5dca8f65f12d06742/comment/6af260e1329931c7e4fa8646#reply-6af274f39d376fde14853faf)

Thanks, that is a useful extension. The five-call fixture stops at the returned result, so it does not test what a client does with malformed JSON or a valid object that has the wrong shape. I would add those as separate application-level checks, assert they are rejected before downstream dispatch, and keep schema failures distinct from MCP protocol errors and tool-level isError results. That would test the client policy you describe without treating it as behavior guaranteed by the SDK.

[Mike Dabydeen](https://hashnode.com/@firelinks)

[4d ago](https://hashnode.com/posts/mcp-tool-error-handling-5-calls-one-failure-hidden-as-success/6af181e5dca8f65f12d06742/comment/6af1bb7f6d1ced13cda358e3)

A flagged error from a tool that writes something still doesn't tell the agent whether the write happened. Your thrown\_error row is the one I'd extend: if the handler throws "upstream timeout" after the upstream already committed, the client gets isError: true, and the obvious recovery is to call again, which repeats the write.

For side-effecting tools I'd put the effect state in the error text itself: not applied, applied, or unknown. Unknown is the honest answer for a timeout, and it should tell the agent to check status before retrying. If the tool also takes an idempotency key and the client reuses it on the retry, the server can return the first result instead of doing the work twice. That would make a sixth row for the fixture: a handler that commits and then throws, followed by a second call with the same key.

[Daniel Martin](https://hashnode.com/@averyellistech)

[4d ago](https://hashnode.com/posts/mcp-tool-error-handling-5-calls-one-failure-hidden-as-success/6af181e5dca8f65f12d06742/comment/6af1bb7f6d1ced13cda358e3#reply-6af1c02ac2533db561567690)

Good catch. My five-call fixture records the SDK result; it doesn’t test whether a write committed before a timeout. For a side-effecting tool, `isError: true` alone isn’t a safe retry instruction. A useful follow-up would commit once, simulate a timeout, retry with the same idempotency key, and check that the effect isn’t duplicated. Thanks for pointing out the gap.
