Field note progress0%
← All field notes

MCP observability / 10 min

Why Did My MCP Tool Call Fail? MCP Error Codes and Tool Errors Explained

What each MCP error code means, from -32602 to -32000 and -32001, how protocol errors differ from isError tool results, and who hit them.

On this page

An MCP tool call fails in one of three places: the connection or client SDK gives up (often shown as -32000 Connection closed or -32001 Request timed out, which are SDK codes, not specification codes), the server rejects the request with a JSON-RPC protocol error such as -32602 Invalid params, or the tool runs and returns a result with isError: true. Flowlines shows which of your tools fail, with which kind of error, and which users and AI clients those failures affect.

The codes below are checked against the MCP specification ↗ for the 2026-07-28, 2025-11-25 and 2025-06-18 revisions, and against the official TypeScript and Python SDK source. Where the specification and the SDKs disagree, this guide says so.

What is the difference between an MCP protocol error and a tool error?

A protocol error is a JSON-RPC error response that says the request could not be handled; a tool error is a normal result with isError: true that says the tool ran and failed. Flowlines counts both, separately, for every tool.

AspectProtocol errorTool error
Shape on the wireAn error object with code and messageA result with isError: true and text content
MeaningThe request could not be processedThe tool ran and reports a failure
Typical causesUnknown tool, malformed request, unsupported method, server crashUpstream API failed, record not found, invalid input values
Who sees itThe client, which may not show it to the modelThe model, which can read it and try again
OwnerMCP server or client integrationThe tool's own logic

A protocol error for an unknown tool looks like this:

{
  "jsonrpc": "2.0",
  "id": 3,
  "error": { "code": -32602, "message": "Unknown tool: search_custmers" }
}

A tool error is a successful JSON-RPC response whose result reports the failure:

{
  "jsonrpc": "2.0",
  "id": 4,
  "result": {
    "content": [{ "type": "text", "text": "start_date must be YYYY-MM-DD. Received: 22/10/2026." }],
    "isError": true
  }
}

The difference matters because the model only learns from what it sees. Since the 2025-11-25 revision, the specification says input validation errors, such as a date in the wrong format or a value out of range, should be returned as tool errors rather than protocol errors so the model can correct itself, and clients should pass tool errors to the model. The schema still describes -32602 as covering invalid tool arguments, so servers in production do both. Count them as separate classes and do not assume one convention.

What do MCP error codes mean?

MCP uses the five standard JSON-RPC codes, a few codes of its own, and several codes that only SDKs define. Flowlines groups failed calls by these classes so the right owner sees them.

CodeNameDefined byTypical causeFirst check
-32700Parse errorJSON-RPCThe message is not valid JSONStray output in the stream, especially on stdio
-32600Invalid requestJSON-RPCValid JSON, but not a valid requestClient and server protocol versions
-32601Method not foundJSON-RPCMethod not implemented, or a capability the server did not advertiseCapabilities and the protocol revision in use
-32602Invalid paramsJSON-RPCUnknown tool, invalid arguments, unknown resource (2026-07-28), invalid cursorTool name, input schema and arguments sent
-32603Internal errorJSON-RPCUnhandled exception in the serverServer logs and the stack trace for that request
-32002Resource not foundMCP, until 2025-11-25Unknown resource URIRetired in 2026-07-28, which uses -32602
-32042URL elicitation requiredMCP 2025-11-25 onlyThe user must complete a step in the browserRetired in 2026-07-28
-32020Header mismatchMCP 2026-07-28HTTP headers disagree with the request bodyProxies or clients that rewrite headers
-32021Missing required client capabilityMCP 2026-07-28The server needs a capability the client did not declareClient capabilities sent with the request
-32022Unsupported protocol versionMCP 2026-07-28The server does not support the requested revisionSupported versions returned by the server
-32000Connection closedTypeScript and Python SDKsThe transport closed before a responseServer process, command and stdout
-32001Request timed outTypeScript SDKNo response within the client timeoutTool duration and client timeout

The 2026-07-28 revision calls the range -32000 to -32019 legacy and implementation-defined, and tells receivers not to assume a meaning for those codes. In practice, -32000 and -32001 still appear in error messages from popular clients built on the SDKs, which is why people search for them.

What does MCP error -32000 "Connection closed" mean?

It means the connection to the server ended before the response arrived; the client SDK raises it locally, and the specification does not define it. For a local stdio server, the cause is almost always the server process.

  • The process crashed or exited at startup. Run the exact command from the client configuration in a terminal and read what it prints.
  • The command or path is wrong. Clients often start with a different PATH from your shell, so npx, uvx or node may not resolve. Use absolute paths.
  • Something writes to stdout. On stdio, stdout carries only protocol messages. A print or a library banner corrupts the stream; log to stderr instead.
  • A required environment variable is missing, so the server exits before it can respond.
  • For remote servers, a proxy or load balancer closed the stream, or the server restarted mid-request.

One trap: the TypeScript SDK v1 HTTP server also returns -32000 over the network for several HTTP-level problems, such as a missing session header or a server that was not initialized. If a client on the stateless 2026-07-28 revision talks to an older server, the message text tells you which case you have.

What does MCP error -32001 "Request timed out" mean?

It means the client stopped waiting; the TypeScript SDK raises -32001 locally after 60 seconds by default, and the specification assigns no code to timeouts. The tool may still be running on the server.

SituationWhat to do
The tool is genuinely slowMeasure p95 duration per tool, then speed up or split the work
The tool is slow but makes progressSend progress notifications and let the client reset its timeout on progress
The work is long by designReturn early with a handle and let the agent check back, or use the tasks extension in 2026-07-28
Only one client times outThat client may use a shorter timeout; compare durations per client

The same number can mean something else: the TypeScript SDK v1 HTTP server sends -32001 with "Session not found" when a client presents a session that no longer exists, for example after a server restart. The Python SDK v1 reports timeouts with code 408 instead. Read the message, not just the number.

What does MCP error -32602 "Invalid params" mean for a tool call?

For tools/call it most often means the tool name is unknown, and some servers also use it for arguments that do not match the input schema. In the 2026-07-28 revision it also covers a resource URI that does not exist and an invalid pagination cursor.

  1. Compare the tool name with `tools/list`. Names are case-sensitive. A renamed or removed tool, or a client that cached an old list, produces this error.
  2. Validate the arguments against the input schema you publish, including required fields and formats.
  3. Check which client sent it. If one client produces most -32602 errors, it may send arguments your schema does not expect.
  4. Prefer tool errors for bad argument values. A message such as "date must be YYYY-MM-DD" in an isError result lets the model fix the call.

Why does my MCP tool return isError: true?

Because the tool ran and decided the call failed: an upstream API refused or timed out, a record was not found, or an argument value was invalid. These are the errors the model can act on, so the message text is part of your tool's design.

Weak tool errorBetter tool error
"Error 500""The billing API is unavailable. Try again in a minute or ask the user to retry later."
"Invalid input""start_date must be YYYY-MM-DD and before end_date."
"Not found""No customer matches acme.io. Search by company name with search_customers."
A stack traceOne sentence on what failed and what the agent can do next

Track tool errors per tool and per error message. A tool whose errors are followed by the same call over and over is telling the model too little; why agents ignore your MCP tools covers repeated calls in detail.

Which MCP error codes changed in the 2026-07-28 specification?

The five standard JSON-RPC codes did not change; resource not found moved to -32602, the URL elicitation code was retired, and three new codes cover headers, capabilities and versions.

Code2025-11-252026-07-28
-32002Resource not foundRetired; servers use -32602, and clients should still accept -32002 from older servers
-32042URL elicitation requiredRetired
-32020Not definedHeader mismatch
-32021Not definedMissing required client capability
-32022Not definedUnsupported protocol version
-32000 to -32019Not reservedLegacy, implementation-defined

If you saw -32001, -32003 or -32004 for these new conditions in a release candidate, those numbers were draft-only and were renumbered before the final release. For the other changes in the revision, read MCP analytics after the stateless spec.

How do I find which users hit MCP errors?

Record a few fields on every failed call and group failures by tool, then by user and AI client; Flowlines does this grouping for you and shows the sessions behind each failure.

Field to recordWhy it matters
Tool nameRanks failures by tool, not by server
Error class: transport, protocol, tool error, timeoutSends each failure to the right owner
JSON-RPC code and a short messageSeparates unknown tools from internal errors
AI client name and versionFinds problems that only one client has
Permitted user or account identifierShows whether one customer or many are affected
Server versionLines failures up with releases

Then read the pattern. One user failing many times is usually account data or permissions; many users failing once each points to the tool. MCP tool analytics shows which users hit errors, and MCP user analytics shows each user's clients and sessions. Keep error ratios and p95 latency per tool in your metrics backend as well; the MCP monitoring guide covers success rate and alert rules, and alerts when MCP errors spike has starting thresholds.

Key takeaway: separate transport, protocol and tool errors before you count them, read the message as well as the code, and connect each failure to the users and clients it affects. Flowlines shows failing tools with the users and sessions behind them, and the Free plan includes 100 analyzed MCP sessions per month.

Sources

Frequently asked questions

What is the difference between an MCP protocol error and a tool error?

A protocol error is a JSON-RPC error response: the request could not be handled, for example an unknown tool or a malformed request. A tool error is a normal result with isError: true: the tool ran and reports that it failed. Clients should pass tool errors to the model so it can correct itself.

What does MCP error -32000 Connection closed mean?

The connection to the server ended before a response arrived. The MCP specification does not define -32000; the TypeScript and Python SDKs use it locally. For stdio servers, the usual causes are a process that crashed or exited, a wrong command or path, or log output written to stdout.

What does MCP error -32001 Request timed out mean?

The client SDK stopped waiting for a response. The TypeScript SDK raises -32001 locally after 60 seconds by default. Make the tool faster, send progress notifications and let the client reset its timeout on progress, or raise the timeout in the client. The specification itself assigns no code to timeouts.

What does MCP error -32602 Invalid params mean?

The request parameters were rejected. For tools/call it usually means an unknown tool name, and some servers also use it for arguments that do not match the input schema. In the 2026-07-28 revision it is also the code for a resource that does not exist and for an invalid pagination cursor.

Did MCP error codes change in the 2026-07-28 specification?

Yes. Resource not found moved from -32002 to -32602, the URL elicitation code -32042 was retired, and three codes were added: -32020 header mismatch, -32021 missing required client capability and -32022 unsupported protocol version. The five standard JSON-RPC codes did not change.

How do I find which users hit MCP tool errors?

Record the tool name, error class, JSON-RPC code, AI client and a permitted user identifier on every failed call, then group failures by tool and user. Flowlines shows which tools fail, with which kind of error, and which users and AI clients the failures affect.

100 MCP sessions a month, free

See what people do with your MCP.