Skip to content

Fix HTTP transport timeout defaulting to 5 seconds#2848

Merged
jlowin merged 2 commits intorelease/2.xfrom
fix-http-transport-timeout
Jan 12, 2026
Merged

Fix HTTP transport timeout defaulting to 5 seconds#2848
jlowin merged 2 commits intorelease/2.xfrom
fix-http-transport-timeout

Conversation

@jlowin
Copy link
Copy Markdown
Member

@jlowin jlowin commented Jan 12, 2026

When StreamableHttpTransport was updated to use the new streamable_http_client API, the code path for creating an httpx client when no factory is provided used httpx.AsyncClient() directly. Without an explicit timeout, httpx defaults to 5 seconds for all operations.

This caused tools taking longer than 5 seconds to fail with a 409 Conflict error as the client's SSE stream would timeout and trigger reconnection logic that conflicts with the existing GET stream.

The fix uses create_mcp_http_client() from the MCP SDK which sets appropriate defaults (30s connect, 5min read timeout) and enables follow_redirects.

Fixes #2842, fixes #2845

Use create_mcp_http_client() instead of bare httpx.AsyncClient()
when no httpx_client_factory is provided. This ensures proper MCP
timeouts (30s connect, 5min read) instead of httpx's 5-second default.

Fixes #2842, fixes #2845
@marvin-context-protocol marvin-context-protocol Bot added bug Something isn't working. Reports of errors, unexpected behavior, or broken functionality. client Related to the FastMCP client SDK or client-side functionality. http Related to HTTP transport, networking, or web server functionality. labels Jan 12, 2026
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7b940dc028

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

transport=StreamableHttpTransport(streamable_http_server)
) as client:
# This should NOT timeout since we fixed the default timeout
result = await client.call_tool("slow_tool", {"duration": 6})
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep test runtime under pytest 5s timeout

This test forces a 6-second tool run (duration=6), but pytest-timeout is globally set to 5 seconds in pyproject.toml ([tool.pytest.ini_options].timeout = 5). As written, the test will be terminated by pytest-timeout before the tool completes, so CI will fail even when the HTTP fix works. Use a shorter duration or add a per-test timeout marker to keep it within the configured limit.

Useful? React with 👍 / 👎.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jan 12, 2026

Walkthrough

This PR updates src/fastmcp/client/transports.py to import create_mcp_http_client, compute a timeout from read_timeout_seconds in StreamableHttpTransport.connect_session, and pass that timeout (optionally) into the HTTP client creation path. If httpx_client_factory is provided it is invoked with explicit headers/auth/follow_redirects and the optional timeout; otherwise create_mcp_http_client is used as the default client creation path. Comments/documentation were updated to reflect MCP-appropriate timeouts.

Possibly related PRs

  • PR 2620 (jlowin/fastmcp): Modifies StreamableHttpTransport client construction and timeout handling in src/fastmcp/client/transports.py, changing how factories/default clients are created and how timeout/header parameters are passed.
🚥 Pre-merge checks | ✅ 4 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically summarizes the main change: fixing HTTP transport timeout defaulting to 5 seconds.
Description check ✅ Passed The description provides a clear explanation of the problem, root cause, and solution, but does not follow the template checklist structure with checkbox items.
Linked Issues check ✅ Passed The PR directly addresses the coding objectives from both linked issues #2842 and #2845: fixing timeout handling for long-running tools by using MCP-appropriate defaults instead of httpx's 5-second default.
Out of Scope Changes check ✅ Passed All changes in src/fastmcp/client/transports.py are directly scoped to fixing the HTTP transport timeout issue described in the linked issues; no out-of-scope modifications detected.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

📜 Recent review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7b940dc and 6e75eb2.

⛔ Files ignored due to path filters (1)
  • tests/integration_tests/test_timeout_fix.py is excluded by none and included by none
📒 Files selected for processing (1)
  • src/fastmcp/client/transports.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/fastmcp/client/transports.py
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Run tests: Python 3.10 on windows-latest
  • GitHub Check: Run tests: Python 3.10 on ubuntu-latest
  • GitHub Check: Run tests with lowest-direct dependencies
  • GitHub Check: Run tests: Python 3.13 on ubuntu-latest

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
src/fastmcp/client/transports.py (1)

287-293: Consider preserving MCP's granular timeout defaults when user provides read_timeout_seconds.

Using httpx.Timeout(read_timeout_seconds.total_seconds()) sets all timeout components (connect, read, write, pool) to the same value. This means a user setting read_timeout_seconds=timedelta(minutes=5) would also get a 5-minute connect timeout, losing the MCP SDK's sensible 30-second connect default.

If preserving granular control is desired:

💡 Suggested refinement
-            timeout = httpx.Timeout(read_timeout_seconds.total_seconds())
+            timeout = httpx.Timeout(
+                connect=30.0,  # Preserve MCP default connect timeout
+                read=read_timeout_seconds.total_seconds(),
+                write=read_timeout_seconds.total_seconds(),
+                pool=read_timeout_seconds.total_seconds(),
+            )

Alternatively, this may be intentional to give users full control. If so, consider documenting that read_timeout_seconds overrides all timeout components.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9e86dbc and 7b940dc.

⛔ Files ignored due to path filters (1)
  • tests/integration_tests/test_timeout_fix.py is excluded by none and included by none
📒 Files selected for processing (1)
  • src/fastmcp/client/transports.py
🧰 Additional context used
📓 Path-based instructions (1)
src/**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

src/**/*.py: Python source code must use Python ≥3.10 with full type annotations
Never use bare except - be specific with exception types
Prioritize readable, understandable code - clarity over cleverness; avoid obfuscated or confusing patterns
Follow existing patterns and maintain consistency across the codebase

Files:

  • src/fastmcp/client/transports.py
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Run tests: Python 3.10 on ubuntu-latest
  • GitHub Check: Run tests: Python 3.10 on windows-latest
  • GitHub Check: Run tests with lowest-direct dependencies
  • GitHub Check: Run tests: Python 3.13 on ubuntu-latest
🔇 Additional comments (3)
src/fastmcp/client/transports.py (3)

298-305: Factory path correctly forwards configuration with conditional timeout.

The conditional dict unpacking **({"timeout": timeout} if timeout else {}) cleanly avoids passing timeout=None to factories that may not handle it. The explicit follow_redirects=True ensures consistent behavior between factory and default paths.


28-28: Private API usage is the official pattern in the MCP SDK—no changes needed.

The import from mcp.shared._httpx_utils is the recommended approach for HTTP client creation in the MCP Python SDK (also used in official MCP client implementations like SSE and streamable-http). The code correctly uses create_mcp_http_client() to get MCP-standard timeout defaults (30s connect, 5min read) and follows redirects, as documented in the comment at lines 287-289. This is consistent with the existing McpHttpClientFactory import and represents the intended way to handle HTTP clients in the SDK. While the module path uses the private naming convention, this is the stable interface provided by MCP for this purpose.


306-311: Correct approach using MCP SDK's client factory with appropriate defaults.

This properly replaces the raw httpx.AsyncClient() with create_mcp_http_client(), which provides MCP-appropriate defaults (30s connect, 5min read timeout, and follow_redirects=True). The parameters passed (headers, timeout, auth) are correctly handled—when timeout is None, the factory's defaults apply; when provided, they override the defaults. This addresses the PR objective of fixing premature timeouts from the original 5-second default.

@jlowin jlowin merged commit e600570 into release/2.x Jan 12, 2026
8 checks passed
@jlowin jlowin deleted the fix-http-transport-timeout branch January 12, 2026 17:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working. Reports of errors, unexpected behavior, or broken functionality. client Related to the FastMCP client SDK or client-side functionality. http Related to HTTP transport, networking, or web server functionality.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant