Skip to content

Commit 77d0af0

Browse files
committed
Add migration note
1 parent 309439f commit 77d0af0

File tree

2 files changed

+52
-14
lines changed

2 files changed

+52
-14
lines changed

docs/migration.md

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,58 @@ async with http_client:
4444
async with streamable_http_client(
4545
url="http://localhost:8000/mcp",
4646
http_client=http_client,
47-
) as (read_stream, write_stream, get_session_id):
47+
) as (read_stream, write_stream):
4848
...
4949
```
5050

51+
### `get_session_id` callback removed from `streamable_http_client`
52+
53+
The `get_session_id` callback (third element of the returned tuple) has been removed from `streamable_http_client`. The function now returns a 2-tuple `(read_stream, write_stream)` instead of a 3-tuple.
54+
55+
If you need to capture the session ID (e.g., for session resumption testing), you can use httpx event hooks to capture it from the response headers:
56+
57+
**Before (v1):**
58+
59+
```python
60+
from mcp.client.streamable_http import streamable_http_client
61+
62+
async with streamable_http_client(url) as (read_stream, write_stream, get_session_id):
63+
async with ClientSession(read_stream, write_stream) as session:
64+
await session.initialize()
65+
session_id = get_session_id() # Get session ID via callback
66+
```
67+
68+
**After (v2):**
69+
70+
```python
71+
import httpx
72+
from mcp.client.streamable_http import streamable_http_client
73+
74+
# Option 1: Simply ignore if you don't need the session ID
75+
async with streamable_http_client(url) as (read_stream, write_stream):
76+
async with ClientSession(read_stream, write_stream) as session:
77+
await session.initialize()
78+
79+
# Option 2: Capture session ID via httpx event hooks if needed
80+
captured_session_ids: list[str] = []
81+
82+
async def capture_session_id(response: httpx.Response) -> None:
83+
session_id = response.headers.get("mcp-session-id")
84+
if session_id:
85+
captured_session_ids.append(session_id)
86+
87+
http_client = httpx.AsyncClient(
88+
event_hooks={"response": [capture_session_id]},
89+
follow_redirects=True,
90+
)
91+
92+
async with http_client:
93+
async with streamable_http_client(url, http_client=http_client) as (read_stream, write_stream):
94+
async with ClientSession(read_stream, write_stream) as session:
95+
await session.initialize()
96+
session_id = captured_session_ids[0] if captured_session_ids else None
97+
```
98+
5199
### `StreamableHTTPTransport` parameters removed
52100

53101
The `headers`, `timeout`, `sse_read_timeout`, and `auth` parameters have been removed from `StreamableHTTPTransport`. Configure these on the `httpx.AsyncClient` instead (see example above).

tests/client/test_session_group.py

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,7 @@ async def test_client_session_group_disconnect_non_existent_server():
278278
await group.disconnect_from_server(session)
279279

280280

281+
# TODO(Marcelo): This is horrible. We should drop this test.
281282
@pytest.mark.anyio
282283
@pytest.mark.parametrize(
283284
"server_params_instance, client_type_name, patch_target_for_client_func",
@@ -310,19 +311,8 @@ async def test_client_session_group_establish_session_parameterized(
310311
mock_read_stream = mock.AsyncMock(name=f"{client_type_name}Read")
311312
mock_write_stream = mock.AsyncMock(name=f"{client_type_name}Write")
312313

313-
# streamable_http_client's __aenter__ returns three values
314-
if client_type_name == "streamablehttp":
315-
mock_extra_stream_val = mock.AsyncMock(name="StreamableExtra")
316-
mock_client_cm_instance.__aenter__.return_value = (
317-
mock_read_stream,
318-
mock_write_stream,
319-
mock_extra_stream_val,
320-
)
321-
else:
322-
mock_client_cm_instance.__aenter__.return_value = (
323-
mock_read_stream,
324-
mock_write_stream,
325-
)
314+
# All client context managers return (read_stream, write_stream)
315+
mock_client_cm_instance.__aenter__.return_value = (mock_read_stream, mock_write_stream)
326316

327317
mock_client_cm_instance.__aexit__ = mock.AsyncMock(return_value=None)
328318
mock_specific_client_func.return_value = mock_client_cm_instance

0 commit comments

Comments
 (0)