Skip to content

feat(fetch): add retry/backoff for transient 429/5xx and network errors - #4456

Closed
chakshu-dhannawat wants to merge 1 commit into
modelcontextprotocol:mainfrom
chakshu-dhannawat:fix/fetch-retry-backoff
Closed

chakshu-dhannawat wants to merge 1 commit into
modelcontextprotocol:mainfrom
chakshu-dhannawat:fix/fetch-retry-backoff

Conversation

@chakshu-dhannawat

@chakshu-dhannawat chakshu-dhannawat commented Jul 2, 2026 •

Copy link
Copy Markdown

Summary

Resolves #4449.

The Python fetch server currently raises McpError immediately on any HTTP error or non-2xx status. This means a single transient 429 (rate-limit), 503 (overloaded server), or momentary network timeout causes the fetch to fail completely, forcing the LLM to retry the whole tool call.

Changes:

  • Retry on 429, 500, 502, 503, 504 with configurable max_retries (default 3)
  • Retry on httpx.TransportError (covers TimeoutException, ConnectError, etc.)
  • Respect Retry-After header on 429; fall back to full-jitter exponential backoff capped at 30 s
  • --max-retries CLI flag so operators can tune or disable retries (--max-retries 0)
  • 12 new tests covering: 503→success, 429 Retry-After, exhausted retries, 404 non-retry, network error retry, network error exhaustion, and _retry_wait unit tests

Non-retryable errors (400, 401, 403, 404, etc.) still raise immediately — unchanged behavior.

Test plan

  • All 32 tests pass: uv run pytest -v
  • No ruff issues: uv run ruff check .
  • pyright: 0 errors, 0 warnings: uv run pyright
  • Tested with --max-retries 0 to verify backwards-compatible opt-out

- Retry on HTTP 429, 500, 502, 503, 504 and httpx.TransportError
- Respect Retry-After header on 429; fall back to full-jitter exponential
  backoff capped at 30 s
- Default 3 retries; configurable via max_retries param and --max-retries CLI flag
- Add 12 new tests covering retry path, exhaustion, 404 non-retry, and
  Retry-After parsing
@chakshu-dhannawat

Copy link
Copy Markdown
Author

Hi, I've refreshed this against main. Could a maintainer take a look when possible? Thanks.

@cliffhall cliffhall added the closed-out-of-scope Closed: out of scope here; listings and new servers go to the MCP Registry (#4875) label Oct 20, 2026
@cliffhall

Copy link
Copy Markdown
Member

Thank you for this pull request, and apologies for the long wait for a response.

These servers are reference implementations: they exist to show how each part of MCP is used, not to be general-purpose products, so new features are taken selectively, and this change isn't one the maintainers plan to take. This repository also now accepts issues, not pull requests, from anyone but its maintainers; the policy is in CONTRIBUTING.md.

This is not a judgment on the idea or on you. A server in the MCP Registry may well offer it, and anyone is welcome to build on these servers to do so. If you think we've misread it, please open an issue describing the problem and the expected behavior.

This is part of the backlog triage in #4875.

@cliffhall cliffhall closed this Oct 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

closed-out-of-scope Closed: out of scope here; listings and new servers go to the MCP Registry (#4875)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fetch: no retry/backoff on transient 429/5xx or network errors

2 participants