
This page is part of our MCP specification reference, a plain-English guide to the Model Context Protocol spec (version 2026-07-28), within The MCP Guide. Building a server? See MCP development.
MCP servers report tool errors in two ways. Problems with the request itself, like an unknown tool name, go back as standard JSON-RPC errors. Problems that happen while running the tool, like a bad date or a failed API call, go back as a normal result with isError: true and a message the model can read.
Status in the 2026-07-28 spec: core. The two-mechanism model has been in the spec since 2024-11-05. The line between them was clarified in 2025-11-25.
Choosing the right one matters. A model can see and fix an isError result. It usually cannot recover from a protocol error. This page is based on the "Error Handling" section of the 2026-07-28 Tools page, checked on 28 October 2026.
Key Takeaways
- Protocol errors are JSON-RPC errors for unknown tools, malformed requests and server errors.
- Tool execution errors are results with
isError: truefor API failures, input validation errors and business logic errors. - Since 2025-11-25, input validation errors belong in tool execution errors, so the model can correct its arguments.
- Clients SHOULD pass tool execution errors to the model. They MAY pass protocol errors, but recovery is less likely.
- In 2026-07-28, MCP reserves error codes
-32020to-32099for the spec, so do not invent codes in that range.
What the two mechanisms are
The spec draws a clear line.
| Type | Use it for | How it is sent |
|---|---|---|
| Protocol error | Unknown tool, request that fails the CallToolRequest schema, server errors | JSON-RPC error object |
| Tool execution error | API failures, input validation errors such as a date in the wrong format or a value out of range, business logic errors | result with isError: true and content |
The spec says protocol errors "indicate issues with the request structure itself that models are less likely to be able to fix." Tool execution errors "contain actionable feedback that language models can use to self-correct and retry with adjusted parameters."
Why there are two
The difference is who sees the error. A JSON-RPC error goes to the client software. Depending on the client, the model may never see it. A result with isError: true is a normal tool result, so the model reads the message and can try again.
The 2026-07-28 schema explains this in its description of isError. Errors that come from the tool "SHOULD be reported inside the result object, with isError set to true, not as an MCP protocol-level error response. Otherwise, the LLM would not be able to see that an error occurred and self-correct."
How it works
A protocol error
The spec's example for an unknown tool:
{
"jsonrpc": "2.0",
"id": 3,
"error": {
"code": -32602,
"message": "Unknown tool: invalid_tool_name"
}
}
Code -32602 is the standard JSON-RPC "Invalid params" code. Our guide to JSON-RPC in MCP explains the standard codes.
A tool execution error
The spec's example for a bad input value:
{
"jsonrpc": "2.0",
"id": 4,
"result": {
"resultType": "complete",
"content": [
{
"type": "text",
"text": "Invalid departure date: must be in the future. Current date is 08/08/2025."
}
],
"isError": true
}
}
Look at the message. It says what was wrong and gives the model what it needs to fix it: the current date. That is the pattern to copy.
Note that resultType is complete even though the call failed. In 2026-07-28, resultType says whether the request finished or needs more input. It does not say whether the tool succeeded. If isError is not set, the schema says it is assumed to be false.
Expired handles
The spec's guidance on stateful tools adds one more case. If a call uses an expired or unknown handle, such as an old basket ID, the server should return a tool execution error that says so. The model can then create a new one.
What changed across spec versions
| Version | Change |
|---|---|
| 2024-11-05 | Two mechanisms defined; "invalid arguments" listed under protocol errors (2024-11-05 Tools) |
| 2025-06-18 | Same split, still listing "invalid arguments" as a protocol error (2025-06-18 Tools) |
| 2025-11-25 | Clarified that input validation errors should be tool execution errors, to enable self-correction (SEP-1303, changelog) |
| 2026-07-28 | Results carry resultType; error code allocation policy added; client guidance on passing errors to models (changelog) |
The 2026-07-28 page no longer lists "invalid arguments" under protocol errors. It lists malformed requests that fail the CallToolRequest schema instead. A value that is well-formed but wrong, like a past date, is a tool execution error.
Error code ranges
The 2026-07-28 base protocol partitions the JSON-RPC server-error range. Codes -32000 to -32019 are legacy, and new implementations should not use them. Codes -32020 to -32099 are reserved for the MCP spec. The spec says new application error codes should sit outside the JSON-RPC reserved range of -32768 to -32000.
Two related changes affect other features. A missing resource now returns -32602, not -32002. See MCP resources explained.
Common mistakes
- Letting bad input escape as a JSON-RPC error. Check how your SDK reports exceptions from tool handlers. Catch validation failures and return
isError: truewith a clear message. - Vague messages. "Error" or "Bad request" gives the model nothing to fix. Say which field failed and what a valid value looks like.
- Leaking internals. Stack traces, database errors and file paths can expose sensitive details. The spec says servers must sanitize tool outputs, and that includes error text. See the MCP security center.
- Inventing codes in the reserved range. Implementations must not emit codes from
-32020to-32099that the spec does not define. - Assuming
resultType: "complete"means success. CheckisError.
Our Learn MCP lesson on error handling turns these rules into working code.
Next step
Good errors depend on good tool design. Read MCP tool names and descriptions next, or return to the MCP specification reference.
Frequently asked questions
What does isError mean in an MCP tool result?
isError: true tells the client and model that the tool ran but failed. The content explains why. If isError is missing, it is assumed to be false.
Should input validation errors be protocol errors or isError results?
Since the 2025-11-25 spec, input validation errors should be returned as tool execution errors with isError: true. That lets the model read the problem and retry with better arguments.
When should a server return a JSON-RPC error for a tool call?
Use a JSON-RPC error when the tool does not exist, the request is malformed against the CallToolRequest schema, or the server itself fails. These are problems the model is unlikely to fix.
Will the AI model see a protocol error?
Maybe. The spec says clients may provide protocol errors to the model but should provide tool execution errors. Do not count on the model seeing protocol errors.
What error code means "resource not found" in MCP?
In the 2026-07-28 spec it is -32602 (Invalid Params). Earlier versions used -32002, and clients should still accept that code from older servers.











