Complete the correct MCP error response shape for a tool logic failure
Same topic, related formats. Practice these next.
Same topic, related formats. Practice these next.
A tool logic failure rides the JSON-RPC `result` with `isError: true` so the model sees it; only protocol faults like unknown methods use the `error` field.
Imagine ordering food through a waiter. If the kitchen burns your dish, the waiter still comes back to your table and tells you 'sorry, the dish failed' so you can decide what to do next. That is a tool error: the request was understood, but the work failed, and the result comes back to you with a 'this went wrong' note attached. Now imagine you mumble an order for a dish that does not exist on the menu. The waiter cannot even take the order. That is a protocol error: the request itself was malformed. MCP keeps these two cases on separate tracks, so the model gets handed the kitchen failures it can react to, while the truly broken requests bounce back differently.
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.
5 min: the two error channels + why tool errors ride the result with isError + which faults use the error field + the production exception-handling trap + the injection risk of error content.
// Tool logic failure -> result with isError, NOT a thrown JSON-RPC error
server.setRequestHandler(CallToolRequestSchema, async (request) => {
try {
const rows = await runQuery(request.params.arguments.sql);
return { content: [{ type: "text", text: JSON.stringify(rows) }] };
} catch (err) {
return {
content: [{ type: "text", text: `Query failed: ${err.message}` }],
isError: true // model sees this and can react
};
}
});| Aspect | Tool execution error | JSON-RPC protocol error |
|---|---|---|
| Where it lives | result, with isError true | error field, with a code |
| What failed | Tool logic ran and threw | Request never executed |
| Examples | DB timeout, missing file, API 500 | Unknown method, bad params, malformed JSON |
| Who reacts | The model reads and retries | The host catches and logs |
| Visible to model | Yes, in the content array | No, intercepted by the host |
Real products, models, and research that use this idea.
What an interviewer would ask next. Try answering before peeking at the approach.
Red flags and common mistakes that signal junior thinking. Click to expand.
Returning a tool failure as a JSON-RPC error. That hides it from the model, which can no longer see the message or self-correct on the next turn.
The night-before-the-interview bullets. Scan these on the way to the call.
Primary sources. Skim if you want the original framing.