mcp

MCP tool errors: when to return isError: true and when to return a protocol error

MCP gives tools two ways to report failure. A **protocol error** is a standard JSON-RPC error for problems with the request itself: an unknown tool, a request that fails the `CallToolRequest` schema, or a server error. A **tool execution error** is a normal tool result with `isError: true`, used when the request was valid but the tool failed: an API failure, an input validation error, or a business logic error. The tools spec's Error Handling section says tool execution errors "contain actionable feedback that language models can use to self-correct and retry with adjusted parameters," while protocol errors are issues "that models are less likely to be able to fix" (spec 2026-07-28).

Which mechanism to use

All rows below follow the Error Handling section of the tools spec, 2026-07-28.

FailureMechanismHow it's returned
Unknown tool nameProtocol errorJSON-RPC error (spec example: code `-32602`, "Unknown tool: invalid_tool_name")
Malformed request (fails `CallToolRequest` schema)Protocol errorJSON-RPC error
Server errorProtocol errorJSON-RPC error
Upstream API failureTool execution errorResult with `isError: true`
Input validation (wrong date format, value out of range)Tool execution errorResult with `isError: true`
Business logic errorTool execution errorResult with `isError: true`
Expired or unknown handle in a stateful toolTool execution errorResult that says so, "so the model can recover by creating a new one"

Why the split matters

The spec ties the two mechanisms to what the client does with them: "Clients MAY provide protocol errors to language models, though these are less likely to result in successful recovery. Clients SHOULD provide tool execution errors to language models to enable self-correction" (spec 2026-07-28). If you report a fixable input problem as a JSON-RPC error, you are using the mechanism the spec treats as less likely to reach the model.

A tool execution error looks like an ordinary result:

json
{
  "jsonrpc": "2.0",
  "id": 4,
  "result": {
    "content": [
      { "type": "text", "text": "Invalid date '10/14/2026'. Expected format YYYY-MM-DD." }
    ],
    "isError": true
  }
}

Error codes for protocol errors

The base protocol page marks `-32000` to `-32019` as legacy: new codes MUST NOT be allocated there and new implementations SHOULD NOT use them. `-32020` to `-32099` is reserved for the MCP spec (spec 2026-07-28).

Pitfalls

  • Throwing a JSON-RPC error for bad input. A wrong date format or out-of-range value is a tool execution error per the spec; return it with `isError: true`.
  • Vague error text. "Something went wrong" gives the model nothing to act on. Say what failed and what valid input looks like.
  • Returning success for a stale handle. For stateful tools, the spec says to return a tool execution error that says the handle is expired or unknown.
  • Picking codes in the legacy range. Avoid `-32000` to `-32019` for new protocol errors.

How to check it

Call your server with an unknown tool name and confirm you get a JSON-RPC error. Then call a real tool with a deliberately invalid argument and confirm you get a `result` with `isError: true` and text that says how to fix the input.

Where the kit fits

The MCP Starter Kit ($27) is built for teams putting OAuth-protected remote MCP servers in front of Cursor and Claude Connect. Soft path: start at /free; Cheat Sheet for the skim checklist mindset; kit when you want the auth-ready layout.

Soft next step

Go through each tool's failure paths and sort them into request problems (protocol errors) and fixable tool failures (`isError: true`), with error text the model can act on. Soft ladder: /free, then the MCP Starter Kit ($27). Related: OAuth pillar, MCP OAuth failure card, MCP tool annotations.

FAQ

What is the difference between isError and a JSON-RPC error in MCP?+

A JSON-RPC error is a protocol error about the request itself, like an unknown tool or a malformed call. A result with `isError: true` is a tool execution error: the request was valid, but the tool failed (MCP specification 2026-07-28).

When should an MCP tool return isError: true?+

When the model could fix the problem and retry, such as an API failure, an input validation error like a wrong date format, or a business logic error. The spec says these errors carry actionable feedback the model can use to self-correct.

Is an unknown tool a protocol error or a tool error?+

A protocol error. The spec's example returns a standard JSON-RPC error with code -32602 and the message \"Unknown tool: invalid_tool_name.\"

Does the client pass tool errors to the model?+

The spec says clients SHOULD provide tool execution errors to the model so it can self-correct, and MAY provide protocol errors, which are less likely to lead to recovery (MCP specification 2026-07-28).

What should the error text in an isError result say?+

What went wrong and how to fix it, in terms the model can act on, such as the expected format or allowed range. For an expired or unknown handle, the spec says to say so, so the model can create a new one.

Which JSON-RPC error codes should a new MCP server avoid?+

The range -32000 to -32019 is legacy, so new implementations SHOULD NOT use it, and -32020 to -32099 is reserved for the MCP spec (MCP specification 2026-07-28).

Get the free starter

Value first, then a kit when you are ready. No fake urgency. Start with Harness Desk Starter at /free.