Skip to content

Commit 732fa05

Browse files
refactor: Address API design improvements in StreamableHTTP client
This commit addresses two API design concerns: 1. Remove private module usage in examples: Examples no longer import from the private mcp.shared._httpx_utils module. Instead, they create httpx clients directly using the public httpx library. 2. Rename httpx_client parameter to http_client: The 'httpx_client' parameter name was redundant since the type annotation already specifies it's an httpx.AsyncClient. Renaming to 'http_client' provides a cleaner, more concise API. Changes: - Updated oauth_client.py and simple-auth-client examples to use public APIs - Renamed httpx_client to http_client in function signatures - Updated all internal callers and tests - Updated deprecated streamablehttp_client wrapper function
1 parent 2e8ecdc commit 732fa05

File tree

7 files changed

+20
-20
lines changed

7 files changed

+20
-20
lines changed

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2336,12 +2336,12 @@ cd to the `examples/snippets` directory and run:
23362336
import asyncio
23372337
from urllib.parse import parse_qs, urlparse
23382338

2339+
import httpx
23392340
from pydantic import AnyUrl
23402341

23412342
from mcp import ClientSession
23422343
from mcp.client.auth import OAuthClientProvider, TokenStorage
23432344
from mcp.client.streamable_http import streamable_http_client
2344-
from mcp.shared._httpx_utils import create_mcp_http_client
23452345
from mcp.shared.auth import OAuthClientInformationFull, OAuthClientMetadata, OAuthToken
23462346

23472347

@@ -2395,8 +2395,8 @@ async def main():
23952395
callback_handler=handle_callback,
23962396
)
23972397

2398-
async with create_mcp_http_client(auth=oauth_auth) as custom_client:
2399-
async with streamable_http_client("http://localhost:8001/mcp", httpx_client=custom_client) as (read, write, _):
2398+
async with httpx.AsyncClient(auth=oauth_auth, follow_redirects=True) as custom_client:
2399+
async with streamable_http_client("http://localhost:8001/mcp", http_client=custom_client) as (read, write, _):
24002400
async with ClientSession(read, write) as session:
24012401
await session.initialize()
24022402

examples/clients/simple-auth-client/mcp_simple_auth_client/main.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,11 @@
1515
from typing import Any
1616
from urllib.parse import parse_qs, urlparse
1717

18+
import httpx
1819
from mcp.client.auth import OAuthClientProvider, TokenStorage
1920
from mcp.client.session import ClientSession
2021
from mcp.client.sse import sse_client
2122
from mcp.client.streamable_http import streamable_http_client
22-
from mcp.shared._httpx_utils import create_mcp_http_client
2323
from mcp.shared.auth import OAuthClientInformationFull, OAuthClientMetadata, OAuthToken
2424

2525

@@ -212,10 +212,10 @@ async def _default_redirect_handler(authorization_url: str) -> None:
212212
await self._run_session(read_stream, write_stream, None)
213213
else:
214214
print("📡 Opening StreamableHTTP transport connection with auth...")
215-
async with create_mcp_http_client(auth=oauth_auth) as custom_client:
215+
async with httpx.AsyncClient(auth=oauth_auth, follow_redirects=True) as custom_client:
216216
async with streamable_http_client(
217217
url=self.server_url,
218-
httpx_client=custom_client,
218+
http_client=custom_client,
219219
) as (read_stream, write_stream, get_session_id):
220220
await self._run_session(read_stream, write_stream, get_session_id)
221221

examples/snippets/clients/oauth_client.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,12 @@
1010
import asyncio
1111
from urllib.parse import parse_qs, urlparse
1212

13+
import httpx
1314
from pydantic import AnyUrl
1415

1516
from mcp import ClientSession
1617
from mcp.client.auth import OAuthClientProvider, TokenStorage
1718
from mcp.client.streamable_http import streamable_http_client
18-
from mcp.shared._httpx_utils import create_mcp_http_client
1919
from mcp.shared.auth import OAuthClientInformationFull, OAuthClientMetadata, OAuthToken
2020

2121

@@ -69,8 +69,8 @@ async def main():
6969
callback_handler=handle_callback,
7070
)
7171

72-
async with create_mcp_http_client(auth=oauth_auth) as custom_client:
73-
async with streamable_http_client("http://localhost:8001/mcp", httpx_client=custom_client) as (read, write, _):
72+
async with httpx.AsyncClient(auth=oauth_auth, follow_redirects=True) as custom_client:
73+
async with streamable_http_client("http://localhost:8001/mcp", http_client=custom_client) as (read, write, _):
7474
async with ClientSession(read, write) as session:
7575
await session.initialize()
7676

src/mcp/client/session_group.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,7 @@ async def _establish_session(
322322

323323
client = streamable_http_client(
324324
url=server_params.url,
325-
httpx_client=httpx_client,
325+
http_client=httpx_client,
326326
terminate_on_close=server_params.terminate_on_close,
327327
)
328328
read, write, _ = await session_stack.enter_async_context(client)

src/mcp/client/streamable_http.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -457,7 +457,7 @@ def get_session_id(self) -> str | None:
457457
async def streamable_http_client(
458458
url: str,
459459
*,
460-
httpx_client: httpx.AsyncClient | None = None,
460+
http_client: httpx.AsyncClient | None = None,
461461
terminate_on_close: bool = True,
462462
) -> AsyncGenerator[
463463
tuple[
@@ -472,7 +472,7 @@ async def streamable_http_client(
472472
473473
Args:
474474
url: The MCP server endpoint URL.
475-
httpx_client: Optional pre-configured httpx.AsyncClient. If None, a default
475+
http_client: Optional pre-configured httpx.AsyncClient. If None, a default
476476
client with recommended MCP timeouts will be created. To configure headers,
477477
authentication, or other HTTP settings, create an httpx.AsyncClient and pass it here.
478478
terminate_on_close: If True, send a DELETE request to terminate the session
@@ -491,8 +491,8 @@ async def streamable_http_client(
491491
write_stream, write_stream_reader = anyio.create_memory_object_stream[SessionMessage](0)
492492

493493
# Determine if we need to create and manage the client
494-
client_provided = httpx_client is not None
495-
client = httpx_client
494+
client_provided = http_client is not None
495+
client = http_client
496496

497497
if client is None:
498498
# Create default client with recommended MCP timeouts
@@ -584,7 +584,7 @@ async def streamablehttp_client(
584584
async with client:
585585
async with streamable_http_client(
586586
url,
587-
httpx_client=client,
587+
http_client=client,
588588
terminate_on_close=terminate_on_close,
589589
) as streams:
590590
yield streams

tests/client/test_session_group.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -355,13 +355,13 @@ async def test_establish_session_parameterized(
355355
elif client_type_name == "streamablehttp": # pragma: no branch
356356
assert isinstance(server_params_instance, StreamableHttpParameters)
357357
# Verify streamable_http_client was called with url, httpx_client, and terminate_on_close
358-
# The httpx_client is created by the real create_mcp_http_client
358+
# The http_client is created by the real create_mcp_http_client
359359
import httpx
360360

361361
call_args = mock_specific_client_func.call_args
362362
assert call_args.kwargs["url"] == server_params_instance.url
363363
assert call_args.kwargs["terminate_on_close"] == server_params_instance.terminate_on_close
364-
assert isinstance(call_args.kwargs["httpx_client"], httpx.AsyncClient)
364+
assert isinstance(call_args.kwargs["http_client"], httpx.AsyncClient)
365365

366366
mock_client_cm_instance.__aenter__.assert_awaited_once()
367367

tests/shared/test_streamable_http.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1195,7 +1195,7 @@ async def run_tool():
11951195
headers[MCP_PROTOCOL_VERSION_HEADER] = captured_protocol_version
11961196

11971197
async with create_mcp_http_client(headers=headers) as httpx_client:
1198-
async with streamable_http_client(f"{server_url}/mcp", httpx_client=httpx_client) as (
1198+
async with streamable_http_client(f"{server_url}/mcp", http_client=httpx_client) as (
11991199
read_stream,
12001200
write_stream,
12011201
_,
@@ -1408,7 +1408,7 @@ async def test_streamablehttp_request_context_propagation(context_aware_server:
14081408
}
14091409

14101410
async with create_mcp_http_client(headers=custom_headers) as httpx_client:
1411-
async with streamable_http_client(f"{basic_server_url}/mcp", httpx_client=httpx_client) as (
1411+
async with streamable_http_client(f"{basic_server_url}/mcp", http_client=httpx_client) as (
14121412
read_stream,
14131413
write_stream,
14141414
_,
@@ -1446,7 +1446,7 @@ async def test_streamablehttp_request_context_isolation(context_aware_server: No
14461446
}
14471447

14481448
async with create_mcp_http_client(headers=headers) as httpx_client:
1449-
async with streamable_http_client(f"{basic_server_url}/mcp", httpx_client=httpx_client) as (
1449+
async with streamable_http_client(f"{basic_server_url}/mcp", http_client=httpx_client) as (
14501450
read_stream,
14511451
write_stream,
14521452
_,

0 commit comments

Comments
 (0)