MCP tool error or JSON-RPC error: where Sume's failures land

Sume returns tool failures as results with isError true and keeps JSON-RPC errors for protocol faults, per the 2025-11-25 MCP spec. Here is the split.

5 min readSume
All posts

When a Sume tool call fails, the failure comes back as a normal tool result with isError set to true, so the model can read it and react. JSON-RPC errors are reserved for protocol problems such as an invalid request or an unknown method. This matches the 2025-11-25 MCP specification, which says tool execution errors should be reported in the result so the model can see them, and protocol errors use JSON-RPC error responses.

Which failure is which

Failure shapes on Sume's hosted MCP (repo as of 2026-10-09; spec read 2026-10-09)
FailureShapeRetry?
Write tool under an mcp:read sessionTool result, isError true, code insufficient_scope, required_scope mcp:writeNo, re-consent with Write
Misspelled tool nameTool result, code tool_not_found, with a suggested name when one existsYes, with the exact name
Host at capacity for a tool callTool result, code wait_busy, HTTP status 429 in the payloadYes, with the same idempotency_key
Unsupported MCP-Protocol-Version headerHTTP 400 with JSON-RPC error -32600No, change client version
Malformed JSON-RPC requestJSON-RPC error -32600No, fix the client
Unknown methodJSON-RPC error -32601No
Host budget full on a non-tool methodJSON-RPC error -32000Yes, shortly

Why the split matters to your client

Many clients show a JSON-RPC error to the person but hand a tool result to the model. If a paid call fails with wait_busy, the model sees the message and can retry with the same idempotency_key. If your client turns every isError into an exception, the model never gets the chance, and a human sees a stack trace.

The supported protocol versions on Sume's host are 2025-03-26, 2025-06-18 and 2025-11-25. Older batch requests are limited to 4 messages, and current revisions need one message per request.

What to log

Branch your retry logic on these codes instead of on message text. A wait_busy is worth retrying after a second, while an insufficient_scope will fail identically until the person grants Write.

  • The error code field in the tool result, such as insufficient_scope or wait_busy.
  • The JSON-RPC code for protocol faults.
  • The idempotency_key and job id for write and paid calls, never the credential.

A small classifier

Write one function that takes a response and returns one of four classes: success, retry-same-call, fix-and-retry, and stop. Put wait_busy and read_busy in the first retry class, tool_not_found in fix-and-retry, and insufficient_scope and authorization failures in stop. Every agent loop then handles Sume the same way, and a new error code needs one new line rather than a new branch in each caller.

Log the class and the code, not the full payload. The payload can include job metadata you do not want sitting in shared logs.

Sources

Related posts

More in Integrations

All Integrations posts

Written by Sume