1
1
"""Utilities for creating standardized httpx AsyncClient instances."""
2
2
3
+ from __future__ import annotations
4
+
3
5
from typing import Any
4
6
5
7
import httpx
6
8
9
+ __all__ = ["create_mcp_http_client" ]
10
+
7
11
8
12
def create_mcp_http_client (
9
13
* ,
10
14
headers : dict [str , Any ] | None = None ,
11
- timeout : httpx .Timeout | float | None = None ,
15
+ timeout : httpx .Timeout | None = None ,
12
16
** kwargs : Any ,
13
17
) -> httpx .AsyncClient :
14
18
"""Create a standardized httpx AsyncClient with MCP defaults.
15
19
16
20
This function provides common defaults used throughout the MCP codebase:
17
21
- follow_redirects=True (always enabled)
18
22
- Default timeout of 30 seconds if not specified
19
- - Header will be merged
23
+ - Headers will be merged with any existing headers in kwargs
20
24
21
25
Args:
22
26
headers: Optional headers to include with all requests.
23
- timeout: Request timeout in seconds (float) or httpx.Timeout object.
27
+ timeout: Request timeout as httpx.Timeout object.
24
28
Defaults to 30 seconds if not specified.
25
29
**kwargs: Additional keyword arguments to pass to AsyncClient.
26
30
27
31
Returns:
28
32
Configured httpx.AsyncClient instance with MCP defaults.
29
33
34
+ Note:
35
+ The returned AsyncClient must be used as a context manager to ensure
36
+ proper cleanup of connections.
37
+
30
38
Examples:
31
39
# Basic usage with MCP defaults
32
40
async with create_mcp_http_client() as client:
@@ -50,16 +58,16 @@ def create_mcp_http_client(
50
58
# Handle timeout
51
59
if timeout is None :
52
60
defaults ["timeout" ] = httpx .Timeout (30.0 )
53
- elif isinstance (timeout , int | float ):
54
- defaults ["timeout" ] = httpx .Timeout (timeout )
55
61
else :
56
62
defaults ["timeout" ] = timeout
57
63
58
- # Handle headers
64
+ # Handle headers with proper merging
59
65
if headers is not None :
60
- kwargs ["headers" ] = headers
66
+ existing_headers = kwargs .get ("headers" , {})
67
+ merged_headers = {** existing_headers , ** headers }
68
+ kwargs ["headers" ] = merged_headers
61
69
62
- # Merge defaults with provided kwargs
63
- kwargs = {** defaults , ** kwargs }
70
+ # Merge kwargs with defaults (defaults take precedence)
71
+ kwargs = {** kwargs , ** defaults }
64
72
65
73
return httpx .AsyncClient (** kwargs )
0 commit comments