trackmcp
All posts
EngineeringFeb 6, 2026·7 min read

The errors hiding inside a 200 OK

MCP returns tool errors inside a successful response. Your HTTP logs and APM stay green while agents retry and give up.

Krishna GoyalKrishna GoyalFounder, TrackMCP
Key takeaways
  • MCP puts tool errors in the response body, not the HTTP status.
  • APM and log-based alerts stay green while agents silently retry and give up.
  • Count isError responses per tool, separately from transport errors.

The most expensive failures on an MCP server are the ones nothing alerts on. The transport returns 200. Your APM shows healthy latency. But the tool inside that response failed, and the agent quietly moved on.

Why this happens

MCP encodes tool-level errors in the response body, often with an isError flag, rather than as an HTTP status. That is a reasonable protocol decision: a tool failing is not the same as the server failing. But it means every layer built around status codes is blind to it.

{
  "content": [{ "type": "text", "text": "to: expected array" }],
  "isError": true
}
A healthy 200 OK can carry a failed tool call. Status codes never see it.

What the agent does next

It rarely surfaces the error to the user. It retries, sometimes with the same malformed arguments, then abandons the task. From the user's side the assistant just 'didn't do it.' From your side, everything looks fine.

How to catch it

  • Read the payload, not just the status code
  • Count isError responses per tool, separately from transport errors
  • Track retries within a session to spot give-up loops
  • Alert on error-rate spikes at the tool level

Once you separate transport health from tool health, send_email failing 94 percent of the time stops being invisible and becomes the first thing you fix.

See this on your own server

TrackMCP turns your MCP server's calls into adoption, workflows, and outcomes. One line to install.

Keep reading