Skip to content

Commit 43971c1

Browse files
felixweinbergermaxisbey
authored andcommitted
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 fb6182a commit 43971c1

File tree

7 files changed

+22
-22
lines changed

7 files changed

+22
-22
lines changed

README.md

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

2259+
import httpx
22592260
from pydantic import AnyUrl
22602261

22612262
from mcp import ClientSession
22622263
from mcp.client.auth import OAuthClientProvider, TokenStorage
22632264
from mcp.client.streamable_http import streamable_http_client
2264-
from mcp.shared._httpx_utils import create_mcp_http_client
22652265
from mcp.shared.auth import OAuthClientInformationFull, OAuthClientMetadata, OAuthToken
22662266

22672267

@@ -2315,8 +2315,8 @@ async def main():
23152315
callback_handler=handle_callback,
23162316
)
23172317

2318-
async with create_mcp_http_client(auth=oauth_auth) as custom_client:
2319-
async with streamable_http_client("http://localhost:8001/mcp", httpx_client=custom_client) as (read, write, _):
2318+
async with httpx.AsyncClient(auth=oauth_auth, follow_redirects=True) as custom_client:
2319+
async with streamable_http_client("http://localhost:8001/mcp", http_client=custom_client) as (read, write, _):
23202320
async with ClientSession(read, write) as session:
23212321
await session.initialize()
23222322

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

@@ -205,10 +205,10 @@ async def _default_redirect_handler(authorization_url: str) -> None:
205205
await self._run_session(read_stream, write_stream, None)
206206
else:
207207
print("📡 Opening StreamableHTTP transport connection with auth...")
208-
async with create_mcp_http_client(auth=oauth_auth) as custom_client:
208+
async with httpx.AsyncClient(auth=oauth_auth, follow_redirects=True) as custom_client:
209209
async with streamable_http_client(
210210
url=self.server_url,
211-
httpx_client=custom_client,
211+
http_client=custom_client,
212212
) as (read_stream, write_stream, get_session_id):
213213
await self._run_session(read_stream, write_stream, get_session_id)
214214

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
@@ -263,7 +263,7 @@ async def _establish_session(
263263

264264
client = streamable_http_client(
265265
url=server_params.url,
266-
httpx_client=httpx_client,
266+
http_client=httpx_client,
267267
terminate_on_close=server_params.terminate_on_close,
268268
)
269269
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
@@ -454,7 +454,7 @@ def get_session_id(self) -> str | None:
454454
async def streamable_http_client(
455455
url: str,
456456
*,
457-
httpx_client: httpx.AsyncClient | None = None,
457+
http_client: httpx.AsyncClient | None = None,
458458
terminate_on_close: bool = True,
459459
) -> AsyncGenerator[
460460
tuple[
@@ -469,7 +469,7 @@ async def streamable_http_client(
469469
470470
Args:
471471
url: The MCP server endpoint URL.
472-
httpx_client: Optional pre-configured httpx.AsyncClient. If None, a default
472+
http_client: Optional pre-configured httpx.AsyncClient. If None, a default
473473
client with recommended MCP timeouts will be created. To configure headers,
474474
authentication, or other HTTP settings, create an httpx.AsyncClient and pass it here.
475475
terminate_on_close: If True, send a DELETE request to terminate the session
@@ -488,8 +488,8 @@ async def streamable_http_client(
488488
write_stream, write_stream_reader = anyio.create_memory_object_stream[SessionMessage](0)
489489

490490
# Determine if we need to create and manage the client
491-
client_provided = httpx_client is not None
492-
client = httpx_client
491+
client_provided = http_client is not None
492+
client = http_client
493493

494494
if client is None:
495495
# Create default client with recommended MCP timeouts
@@ -581,7 +581,7 @@ async def streamablehttp_client(
581581
async with client:
582582
async with streamable_http_client(
583583
url,
584-
httpx_client=client,
584+
http_client=client,
585585
terminate_on_close=terminate_on_close,
586586
) as streams:
587587
yield streams

tests/client/test_session_group.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -347,13 +347,13 @@ async def test_establish_session_parameterized(
347347
elif client_type_name == "streamablehttp": # pragma: no branch
348348
assert isinstance(server_params_instance, StreamableHttpParameters)
349349
# Verify streamable_http_client was called with url, httpx_client, and terminate_on_close
350-
# The httpx_client is created by the real create_mcp_http_client
350+
# The http_client is created by the real create_mcp_http_client
351351
import httpx
352352

353353
call_args = mock_specific_client_func.call_args
354354
assert call_args.kwargs["url"] == server_params_instance.url
355355
assert call_args.kwargs["terminate_on_close"] == server_params_instance.terminate_on_close
356-
assert isinstance(call_args.kwargs["httpx_client"], httpx.AsyncClient)
356+
assert isinstance(call_args.kwargs["http_client"], httpx.AsyncClient)
357357

358358
mock_client_cm_instance.__aenter__.assert_awaited_once()
359359

tests/shared/test_streamable_http.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1024,7 +1024,7 @@ async def test_streamable_http_client_session_termination(basic_server: None, ba
10241024
headers[MCP_SESSION_ID_HEADER] = captured_session_id
10251025

10261026
async with create_mcp_http_client(headers=headers) as httpx_client:
1027-
async with streamable_http_client(f"{basic_server_url}/mcp", httpx_client=httpx_client) as (
1027+
async with streamable_http_client(f"{basic_server_url}/mcp", http_client=httpx_client) as (
10281028
read_stream,
10291029
write_stream,
10301030
_,
@@ -1091,7 +1091,7 @@ async def mock_delete(self: httpx.AsyncClient, *args: Any, **kwargs: Any) -> htt
10911091
headers[MCP_SESSION_ID_HEADER] = captured_session_id
10921092

10931093
async with create_mcp_http_client(headers=headers) as httpx_client:
1094-
async with streamable_http_client(f"{basic_server_url}/mcp", httpx_client=httpx_client) as (
1094+
async with streamable_http_client(f"{basic_server_url}/mcp", http_client=httpx_client) as (
10951095
read_stream,
10961096
write_stream,
10971097
_,
@@ -1191,7 +1191,7 @@ async def run_tool():
11911191
headers[MCP_PROTOCOL_VERSION_HEADER] = captured_protocol_version
11921192

11931193
async with create_mcp_http_client(headers=headers) as httpx_client:
1194-
async with streamable_http_client(f"{server_url}/mcp", httpx_client=httpx_client) as (
1194+
async with streamable_http_client(f"{server_url}/mcp", http_client=httpx_client) as (
11951195
read_stream,
11961196
write_stream,
11971197
_,
@@ -1403,7 +1403,7 @@ async def test_streamablehttp_request_context_propagation(context_aware_server:
14031403
}
14041404

14051405
async with create_mcp_http_client(headers=custom_headers) as httpx_client:
1406-
async with streamable_http_client(f"{basic_server_url}/mcp", httpx_client=httpx_client) as (
1406+
async with streamable_http_client(f"{basic_server_url}/mcp", http_client=httpx_client) as (
14071407
read_stream,
14081408
write_stream,
14091409
_,
@@ -1441,7 +1441,7 @@ async def test_streamablehttp_request_context_isolation(context_aware_server: No
14411441
}
14421442

14431443
async with create_mcp_http_client(headers=headers) as httpx_client:
1444-
async with streamable_http_client(f"{basic_server_url}/mcp", httpx_client=httpx_client) as (
1444+
async with streamable_http_client(f"{basic_server_url}/mcp", http_client=httpx_client) as (
14451445
read_stream,
14461446
write_stream,
14471447
_,

0 commit comments

Comments
 (0)