Spot the error in how this MCP server reports a tool failure
Click any words you think contain an error. Click again to unmark.
A failed SQL query is a tool logic error, so it belongs in a successful result with isError true, not in the JSON-RPC error field reserved for protocol faults.
Think of ordering food through a delivery app. The app talking to the restaurant's computer is one layer; the kitchen actually cooking is another. If the app cannot even reach the restaurant, that is a broken connection, a protocol problem. But if the kitchen is simply out of an ingredient, that is not a broken connection at all. The order went through fine. The kitchen just has bad news to report back to you. The MCP server here treats a missing database table like a broken connection. In truth the tool ran perfectly and merely found bad news. That news should ride back inside a normal, successful reply so the model can read it and react, not get thrown away as a transport failure.
Detailed answer & concept explanation~8 min readEverything you need to truly understand this topic: intuition, mechanics, step by step explanation, code, formulas, and worked example. Click to expand.
Everything you need to truly understand this topic: intuition, mechanics, step by step explanation, code, formulas, and worked example. Click to expand.
Everything you need to truly understand this topic: intuition, mechanics, step by step explanation, code, formulas, and worked example.
Everything important, quickly.
4 min: name the two error classes, place each in the right JSON-RPC field, give the correct isError result shape, and explain the silent failure mode plus the observability cost.
| Aspect | Protocol error (JSON-RPC error) | Tool error (result.isError) |
|---|---|---|
| Meaning | Request malformed or method unknown | Tool ran but its logic failed |
| Envelope | Top-level error object, no result | Successful result with isError true |
| Example | Parse error, unknown method, invalid params | SQL error, file not found, API timeout |
| Who consumes it | The host runtime | The model, via the tool result |
| Model can retry | No, it never sees it | Yes, it reads the message and adapts |
Real products, models, and research that use this idea.
- The official MCP TypeScript and Python SDKs return tool exceptions as a result with isError true, reserving JSON-RPC error for dispatch faults.
- Claude Code reads isError on each tool result, so a Postgres MCP server's failed query reaches the model and it retries with a corrected query.
- The mcp-inspector debugging tool surfaces a tool's isError result distinctly from a transport-level JSON-RPC error.
What an interviewer would ask next. Try answering before peeking at the approach.
QHow should the agent loop behave differently for an isError result versus a JSON-RPC protocol error?
QWhen IS it correct for an MCP tool call to produce a JSON-RPC error rather than isError?
Don't say thisRed flags and common mistakes that signal junior thinking. Click to expand.
Red flags and common mistakes that signal junior thinking. Click to expand.
Returning every tool failure as a JSON-RPC error. The model never sees the message, so the call looks like a transport fault and the agent cannot recover.
The night-before-the-interview bullets. Scan these on the way to the call.
Primary sources. Skim if you want the original framing.
Same topic, related formats. Practice these next.