feat(client): honor Retry-After on HTTP 429 responses#1965
Open
MukundaKatta wants to merge 2 commits intomodelcontextprotocol:mainfrom
Open
feat(client): honor Retry-After on HTTP 429 responses#1965MukundaKatta wants to merge 2 commits intomodelcontextprotocol:mainfrom
MukundaKatta wants to merge 2 commits intomodelcontextprotocol:mainfrom
Conversation
StreamableHTTPClientTransport now treats 429 Too Many Requests as a retryable signal. When the server returns 429 the transport parses the Retry-After header (delta-seconds or HTTP-date per RFC 7231 §7.1.3), waits for the indicated duration (clamped to a configurable ceiling), and retries the original POST/GET. After a configurable number of consecutive 429 responses the transport surfaces a typed SdkErrorCode.ClientHttpRateLimited so callers can react. Behaviour is configurable via the new rateLimitOptions transport option. Setting maxRetries to 0 disables automatic retries entirely for applications that want to handle rate limiting themselves. Closes modelcontextprotocol#1892.
🦋 Changeset detectedLatest commit: 0d047ed The changes in this PR will be included in the next version bump. This PR includes changesets to release 2 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
@modelcontextprotocol/client
@modelcontextprotocol/server
@modelcontextprotocol/express
@modelcontextprotocol/fastify
@modelcontextprotocol/hono
@modelcontextprotocol/node
commit: |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
Closes #1892.
StreamableHTTPClientTransportfalls through 429 to a genericSdkError, so any client talking to a server that rate-limits with429 Too Many Requests(e.g. theexpress-rate-limitdefault, the MiYo Kado MCP gateway, Cloudflare-fronted servers) crashes on the very first throttled response instead of waiting and retrying. Every consumer of this SDK has to reinvent client-side rate-limit handling.What
Retry-Afterheader on 429 (delta-seconds and HTTP-date forms per RFC 7231 §7.1.3) inside both the POST_sendpath and the GET_startOrAuthSsepath.defaultRetryAfterMswhen the header is missing or unparsable.SdkErrorCode.ClientHttpRateLimitedwith the originalRetry-Aftervalue attached toerror.dataso callers can react.rateLimitOptionstransport option (maxRetries,defaultRetryAfterMs,maxRetryAfterMs). Defaults: 3 retries, 1s fallback, 60s cap. SetmaxRetries: 0to opt out entirely.AbortControllersotransport.close()cancels in-flight Retry-After sleeps.Tested
vitestunit tests inpackages/client/test/client/streamableHttp.test.tscovering:Retry-After: 2waits ~2s then succeedsRetry-Afteris parsed and respectedRetry-Afterfalls back todefaultRetryAfterMsRetry-Afteris clamped tomaxRetryAfterMsClientHttpRateLimitedmaxRetries: 0disables retries_parseRetryAfterhelper across all input shapes (null, undefined, empty, garbage, integer, fractional, future/past HTTP-date)StreamableHTTPClientTransporttest suite still passes (no logic changes outside the new 429 branch).