Skip to content

Commit 609585a

Browse files
committed
feat: add ClientRequestContext type alias for client-side handlers
Introduce a dedicated `ClientRequestContext` type alias in `mcp.client.context` to provide a cleaner API for client-side callback handlers (sampling, elicitation, list_roots). This improves the developer experience by: - Providing a concrete type instead of requiring `RequestContext[ClientSession]` - Making the internal `RequestContext` private by moving it to `_context.py` - Exporting `ClientRequestContext` from `mcp.client` for easy access All examples and conformance tests have been updated to use `ClientRequestContext` instead of the internal `RequestContext` type. The migration guide has been updated to reflect these changes.
1 parent b1f7eec commit 609585a

File tree

25 files changed

+55
-37
lines changed

25 files changed

+55
-37
lines changed

.github/actions/conformance/client.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,9 @@
3838
PrivateKeyJWTOAuthProvider,
3939
SignedJWTParameters,
4040
)
41+
from mcp.client.context import ClientRequestContext
4142
from mcp.client.streamable_http import streamable_http_client
4243
from mcp.shared.auth import OAuthClientInformationFull, OAuthClientMetadata, OAuthToken
43-
from mcp.shared.context import RequestContext
4444

4545
# Set up logging to stderr (stdout is for conformance test output)
4646
logging.basicConfig(
@@ -187,7 +187,7 @@ async def run_sse_retry(server_url: str) -> None:
187187

188188

189189
async def default_elicitation_callback(
190-
context: RequestContext[ClientSession],
190+
context: ClientRequestContext,
191191
params: types.ElicitRequestParams,
192192
) -> types.ElicitResult | types.ErrorData:
193193
"""Accept elicitation and apply defaults from the schema (SEP-1034)."""

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2120,8 +2120,8 @@ import asyncio
21202120
import os
21212121

21222122
from mcp import ClientSession, StdioServerParameters, types
2123+
from mcp.client.context import ClientRequestContext
21232124
from mcp.client.stdio import stdio_client
2124-
from mcp.shared.context import RequestContext
21252125

21262126
# Create server parameters for stdio connection
21272127
server_params = StdioServerParameters(
@@ -2133,7 +2133,7 @@ server_params = StdioServerParameters(
21332133

21342134
# Optional: create a sampling callback
21352135
async def handle_sampling_message(
2136-
context: RequestContext[ClientSession, None], params: types.CreateMessageRequestParams
2136+
context: ClientRequestContext, params: types.CreateMessageRequestParams
21372137
) -> types.CreateMessageResult:
21382138
print(f"Sampling request: {params.messages}")
21392139
return types.CreateMessageResult(

README.v2.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2121,8 +2121,8 @@ import asyncio
21212121
import os
21222122

21232123
from mcp import ClientSession, StdioServerParameters, types
2124+
from mcp.client.context import ClientRequestContext
21242125
from mcp.client.stdio import stdio_client
2125-
from mcp.shared.context import RequestContext
21262126

21272127
# Create server parameters for stdio connection
21282128
server_params = StdioServerParameters(
@@ -2134,7 +2134,7 @@ server_params = StdioServerParameters(
21342134

21352135
# Optional: create a sampling callback
21362136
async def handle_sampling_message(
2137-
context: RequestContext[ClientSession], params: types.CreateMessageRequestParams
2137+
context: ClientRequestContext, params: types.CreateMessageRequestParams
21382138
) -> types.CreateMessageResult:
21392139
print(f"Sampling request: {params.messages}")
21402140
return types.CreateMessageResult(

docs/migration.md

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,7 @@ The `RequestContext` class has been split to separate shared fields from server-
387387
**Before (v1):**
388388

389389
```python
390+
from mcp.client.session import ClientSession
390391
from mcp.shared.context import RequestContext, LifespanContextT, RequestT
391392
from mcp.shared.progress import ProgressContext
392393

@@ -400,19 +401,19 @@ progress_ctx: ProgressContext[SendRequestT, SendNotificationT, SendResultT, Rece
400401
**After (v2):**
401402

402403
```python
403-
from mcp.shared.context import RequestContext
404+
from mcp.client.context import ClientRequestContext
405+
from mcp.client.session import ClientSession
406+
from mcp.server.context import ServerRequestContext, LifespanContextT, RequestT
404407
from mcp.shared.progress import ProgressContext
405408

406-
# RequestContext with 1 type parameter
407-
ctx: RequestContext[ClientSession]
408-
409-
# ProgressContext with 1 type parameter
410-
progress_ctx: ProgressContext[ClientSession]
409+
# For client-side context (sampling, elicitation, list_roots callbacks)
410+
ctx: ClientRequestContext
411411

412412
# For server-specific context with lifespan and request types
413-
from mcp.server.context import ServerRequestContext, LifespanContextT, RequestT
414-
415413
server_ctx: ServerRequestContext[LifespanContextT, RequestT]
414+
415+
# ProgressContext with 1 type parameter
416+
progress_ctx: ProgressContext[ClientSession]
416417
```
417418

418419
### Resource URI type changed from `AnyUrl` to `str`

examples/clients/simple-task-interactive-client/mcp_simple_task_interactive_client/main.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@
1010

1111
import click
1212
from mcp import ClientSession
13+
from mcp.client.context import ClientRequestContext
1314
from mcp.client.streamable_http import streamable_http_client
14-
from mcp.shared.context import RequestContext
1515
from mcp.types import (
1616
CallToolResult,
1717
CreateMessageRequestParams,
@@ -23,7 +23,7 @@
2323

2424

2525
async def elicitation_callback(
26-
context: RequestContext[ClientSession],
26+
context: ClientRequestContext,
2727
params: ElicitRequestParams,
2828
) -> ElicitResult:
2929
"""Handle elicitation requests from the server."""
@@ -38,7 +38,7 @@ async def elicitation_callback(
3838

3939

4040
async def sampling_callback(
41-
context: RequestContext[ClientSession],
41+
context: ClientRequestContext,
4242
params: CreateMessageRequestParams,
4343
) -> CreateMessageResult:
4444
"""Handle sampling requests from the server."""

examples/snippets/clients/stdio_client.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
import os
77

88
from mcp import ClientSession, StdioServerParameters, types
9+
from mcp.client.context import ClientRequestContext
910
from mcp.client.stdio import stdio_client
10-
from mcp.shared.context import RequestContext
1111

1212
# Create server parameters for stdio connection
1313
server_params = StdioServerParameters(
@@ -19,7 +19,7 @@
1919

2020
# Optional: create a sampling callback
2121
async def handle_sampling_message(
22-
context: RequestContext[ClientSession], params: types.CreateMessageRequestParams
22+
context: ClientRequestContext, params: types.CreateMessageRequestParams
2323
) -> types.CreateMessageResult:
2424
print(f"Sampling request: {params.messages}")
2525
return types.CreateMessageResult(

examples/snippets/clients/url_elicitation_client.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,14 @@
3131
from urllib.parse import urlparse
3232

3333
from mcp import ClientSession, types
34+
from mcp.client.context import ClientRequestContext
3435
from mcp.client.sse import sse_client
35-
from mcp.shared.context import RequestContext
3636
from mcp.shared.exceptions import MCPError, UrlElicitationRequiredError
3737
from mcp.types import URL_ELICITATION_REQUIRED
3838

3939

4040
async def handle_elicitation(
41-
context: RequestContext[ClientSession],
41+
context: ClientRequestContext,
4242
params: types.ElicitRequestParams,
4343
) -> types.ElicitResult | types.ErrorData:
4444
"""Handle elicitation requests from the server.

src/mcp/client/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
from mcp.client._transport import Transport
44
from mcp.client.client import Client
5+
from mcp.client.context import ClientRequestContext
56
from mcp.client.session import ClientSession
67

7-
__all__ = ["Client", "ClientSession", "Transport"]
8+
__all__ = ["Client", "ClientRequestContext", "ClientSession", "Transport"]

src/mcp/client/context.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
"""Request context for MCP client handlers."""
2+
3+
from mcp.client.session import ClientSession
4+
from mcp.shared._context import RequestContext
5+
6+
ClientRequestContext = RequestContext[ClientSession]
7+
"""Context for handling incoming requests in a client session.
8+
9+
This context is passed to client-side callbacks (sampling, elicitation, list_roots) when the server sends requests
10+
to the client.
11+
12+
Attributes:
13+
request_id: The unique identifier for this request.
14+
meta: Optional metadata associated with the request.
15+
session: The client session handling this request.
16+
"""

src/mcp/client/experimental/task_handlers.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
from pydantic import TypeAdapter
2020

2121
import mcp.types as types
22-
from mcp.shared.context import RequestContext
22+
from mcp.shared._context import RequestContext
2323
from mcp.shared.session import RequestResponder
2424

2525
if TYPE_CHECKING:

0 commit comments

Comments
 (0)