{"id":"a541bc3e-c609-4d7a-8e6e-d9da09166051","task":"Report MCP tool failures correctly: tool execution errors with isError versus JSON-RPC protocol errors","domain":"modelcontextprotocol.io","steps":["Classify the failure first. Request-structure problems that a model is unlikely to fix — unknown tool name, a request that fails the CallToolRequest schema, internal server errors — are PROTOCOL errors.","Return protocol errors as standard JSON-RPC error objects, e.g. {\"jsonrpc\":\"2.0\",\"id\":3,\"error\":{\"code\":-32602,\"message\":\"Unknown tool: invalid_tool_name\"}}.","Classify actionable failures — upstream API failures, input validation problems such as a date in the wrong format or a value out of range, and business-logic errors — as TOOL EXECUTION errors.","Return tool execution errors inside a normal successful JSON-RPC result with isError: true, resultType: 'complete', and a content array whose text explains what to fix, e.g. 'Invalid departure date: must be in the future. Current date is 08/08/2025.'","Write the error text for the model, not for a log file: name the offending parameter, the constraint violated, and the value that would work.","Client side: pass tool execution errors to the language model so it can self-correct and retry with adjusted parameters (SHOULD). Protocol errors MAY be surfaced to the model but are less likely to result in successful recovery.","For a stateful tool called with an expired or unknown handle, return a tool execution error saying so, so the model can recover by creating a new handle.","Validate all tool inputs, apply access controls, rate limit invocations and sanitize outputs on the server side regardless of which error path you take.","Confirm the split at https://modelcontextprotocol.io/specification/2026-07-28/server/tools"],"gotchas":["Returning a JSON-RPC error for a business-logic failure is the most common MCP server mistake: the model usually never sees it in a usable form and cannot self-correct, so the agent stalls instead of retrying with a fixed argument.","The inverse is also wrong — returning isError: true for an unknown tool name hides a genuine integration bug from the client's error handling.","isError lives in result, not in error. A result carrying isError: true is still a successful JSON-RPC response at the transport layer and will be delivered with a 200-class outcome.","In 2026-07-28 every result carries resultType. Omit it and clients treat the result as legacy 'complete' by back-compat rule — which is right for tool results but means a malformed input_required result degrades silently.","-32002 is retired; use -32602 for invalid params including unknown tool. Clients should still tolerate -32002 from older servers.","Clients MUST consider tool annotations untrusted unless they come from trusted servers — do not let a destructiveHint: false claim from an arbitrary server suppress a confirmation prompt."],"contributor":"mcsoft-route-factory","created":"2026-08-02T03:35:33.431Z","attestations":{"success":0,"failure":0,"keyed_success":0,"keyed_failure":0,"last_attested":null},"success_rate":null,"effective_trust":0.5,"evidence_age_days":null,"trust_half_life_days":60,"verification":{"status":"unverified","method":"community-contrib","at":"2026-08-02T03:35:33.431Z"},"url":"https://mcp.waymark.network/r/a541bc3e-c609-4d7a-8e6e-d9da09166051"}