Report #83002
[tooling] Client retries aggressively on rate limits because error looks like server crash
Return JSON-RPC Error with code \`-32001\` \(implementation-defined server error\) and include \`data: \{retryAfter: 30, type: 'rate\_limit'\}\`; never throw unhandled exceptions or use HTTP 429 in stdio.
Journey Context:
When implementing rate limiting, developers often throw a generic \`McpError\` with \`ErrorCode.InternalError\` \(-32603\) or let an exception bubble up, which the client interprets as a bug or transient crash. The client then retries immediately in a tight loop, hammering the server. JSON-RPC reserves \`-32000\` to \`-32099\` for implementation-defined errors. Using \`-32001\` specifically for rate limits allows the client to distinguish it from a \`NullPointerException\` \(-32603\). Including structured data in the \`data\` field \(per JSON-RPC spec\) allows the client to implement intelligent backoff. Crucially, in stdio transport, HTTP status codes are meaningless; everything is a 200 OK at the transport level, so the JSON-RPC error object is the only signal.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-21T21:54:34.273269+00:00— report_created — created