Skip to content

Commit 4a81199

Browse files
committed
Expose server-assigned session_id on ClientSession
Read session_id from InitializeResult._meta after initialize and expose as session.session_id property. Enables client-side construction of session-scoped event topics for the {session_id} authorization convention.
1 parent 85cc652 commit 4a81199

2 files changed

Lines changed: 37 additions & 0 deletions

File tree

docs/events.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ Topics are `/`-separated strings with a maximum depth of 8 segments. Clients sub
2727
- `+` matches exactly one segment
2828
- `#` matches zero or more trailing segments (must be the last segment)
2929

30+
### Session-Scoped Topics
31+
32+
Servers may use a `{session_id}` placeholder in topic patterns to scope topics to individual sessions (e.g., `app/sessions/{session_id}/messages`). When a topic contains `{session_id}`, the server enforces that subscribers can only substitute their own session UUID -- wildcards and other session IDs are rejected. This convention is not part of the core MCP spec but is a common server-side pattern (used by FastMCP, among others).
33+
3034
## Server-Side
3135

3236
### Declaring Event Topics
@@ -195,6 +199,17 @@ server.request_handlers[EventListRequest] = handle_list
195199

196200
## Client-Side
197201

202+
### Session ID
203+
204+
After initialization, `session.session_id` returns the server-assigned session ID (`str | None`), sourced from `InitializeResult._meta["session_id"]`. This is useful for constructing session-scoped topic patterns:
205+
206+
```python
207+
topic = f"app/sessions/{session.session_id}/messages"
208+
await session.subscribe_events([topic])
209+
```
210+
211+
Returns `None` if the server does not provide a session ID in `_meta`.
212+
198213
### Subscribing to Events
199214

200215
Use `subscribe_events()` to register interest in one or more topic patterns:

src/mcp/client/session.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ def __init__(
146146
self._message_handler = message_handler or _default_message_handler
147147
self._tool_output_schemas: dict[str, dict[str, Any] | None] = {}
148148
self._server_capabilities: types.ServerCapabilities | None = None
149+
self._session_id: str | None = None
149150
self._experimental_features: ExperimentalClientFeatures | None = None
150151
self._event_handler: EventHandlerFnT | None = None
151152
self._event_topic_filter: str | None = None
@@ -205,6 +206,16 @@ async def initialize(self) -> types.InitializeResult:
205206

206207
self._server_capabilities = result.capabilities
207208

209+
# FastMCP servers inject a server-assigned session_id into
210+
# InitializeResult._meta so clients can synchronously read it after
211+
# connect (e.g. to subscribe to session-scoped event topics like
212+
# ``sessions/{session_id}/messages``). Non-FastMCP servers typically
213+
# omit this, in which case ``self._session_id`` stays ``None``.
214+
if result.meta is not None:
215+
meta_session_id = result.meta.get("session_id")
216+
if isinstance(meta_session_id, str):
217+
self._session_id = meta_session_id
218+
208219
await self.send_notification(types.ClientNotification(types.InitializedNotification()))
209220

210221
return result
@@ -216,6 +227,17 @@ def get_server_capabilities(self) -> types.ServerCapabilities | None:
216227
"""
217228
return self._server_capabilities
218229

230+
@property
231+
def session_id(self) -> str | None:
232+
"""The server-assigned session ID from InitializeResult._meta, if present.
233+
234+
This is set by FastMCP servers to enable client-side subscription to
235+
session-scoped event topics like ``sessions/{session_id}/messages``.
236+
Returns None if the server did not provide a session_id (e.g.,
237+
non-FastMCP server).
238+
"""
239+
return self._session_id
240+
219241
@property
220242
def experimental(self) -> ExperimentalClientFeatures:
221243
"""Experimental APIs for tasks and other features.

0 commit comments

Comments
 (0)