Skip to content

Commit 8f874dc

Browse files
authored
Merge branch 'main' into replace-import
2 parents 82b670f + 4fc49c6 commit 8f874dc

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+269
-250
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, Any], # noqa: ARG001
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: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,6 @@ from contextlib import asynccontextmanager
229229
from dataclasses import dataclass
230230

231231
from mcp.server.mcpserver import Context, MCPServer
232-
from mcp.server.session import ServerSession
233232

234233

235234
# Mock database class for example
@@ -275,7 +274,7 @@ mcp = MCPServer("My App", lifespan=app_lifespan)
275274

276275
# Access type-safe lifespan context in tools
277276
@mcp.tool()
278-
def query_db(ctx: Context[ServerSession, AppContext]) -> str:
277+
def query_db(ctx: Context[AppContext]) -> str:
279278
"""Tool that uses initialized resources."""
280279
db = ctx.request_context.lifespan_context.db
281280
return db.query()
@@ -2122,8 +2121,8 @@ import asyncio
21222121
import os
21232122

21242123
from mcp import ClientSession, StdioServerParameters, types
2124+
from mcp.client.context import ClientRequestContext
21252125
from mcp.client.stdio import stdio_client
2126-
from mcp.shared.context import RequestContext
21272126

21282127
# Create server parameters for stdio connection
21292128
server_params = StdioServerParameters(
@@ -2135,7 +2134,7 @@ server_params = StdioServerParameters(
21352134

21362135
# Optional: create a sampling callback
21372136
async def handle_sampling_message(
2138-
context: RequestContext[ClientSession, None], params: types.CreateMessageRequestParams
2137+
context: ClientRequestContext, params: types.CreateMessageRequestParams
21392138
) -> types.CreateMessageResult:
21402139
print(f"Sampling request: {params.messages}")
21412140
return types.CreateMessageResult(

docs/migration.md

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,51 @@ async def handle_tool(name: str, arguments: dict) -> list[TextContent]:
371371
await ctx.session.send_progress_notification(ctx.meta["progress_token"], 0.5, 100)
372372
```
373373

374+
### `RequestContext` and `ProgressContext` type parameters simplified
375+
376+
The `RequestContext` class has been split to separate shared fields from server-specific fields. The shared `RequestContext` now only takes 1 type parameter (the session type) instead of 3.
377+
378+
**`RequestContext` changes:**
379+
380+
- Type parameters reduced from `RequestContext[SessionT, LifespanContextT, RequestT]` to `RequestContext[SessionT]`
381+
- Server-specific fields (`lifespan_context`, `experimental`, `request`, `close_sse_stream`, `close_standalone_sse_stream`) moved to new `ServerRequestContext` class in `mcp.server.context`
382+
383+
**`ProgressContext` changes:**
384+
385+
- Type parameters reduced from `ProgressContext[SendRequestT, SendNotificationT, SendResultT, ReceiveRequestT, ReceiveNotificationT]` to `ProgressContext[SessionT]`
386+
387+
**Before (v1):**
388+
389+
```python
390+
from mcp.client.session import ClientSession
391+
from mcp.shared.context import RequestContext, LifespanContextT, RequestT
392+
from mcp.shared.progress import ProgressContext
393+
394+
# RequestContext with 3 type parameters
395+
ctx: RequestContext[ClientSession, LifespanContextT, RequestT]
396+
397+
# ProgressContext with 5 type parameters
398+
progress_ctx: ProgressContext[SendRequestT, SendNotificationT, SendResultT, ReceiveRequestT, ReceiveNotificationT]
399+
```
400+
401+
**After (v2):**
402+
403+
```python
404+
from mcp.client.context import ClientRequestContext
405+
from mcp.client.session import ClientSession
406+
from mcp.server.context import ServerRequestContext, LifespanContextT, RequestT
407+
from mcp.shared.progress import ProgressContext
408+
409+
# For client-side context (sampling, elicitation, list_roots callbacks)
410+
ctx: ClientRequestContext
411+
412+
# For server-specific context with lifespan and request types
413+
server_ctx: ServerRequestContext[LifespanContextT, RequestT]
414+
415+
# ProgressContext with 1 type parameter
416+
progress_ctx: ProgressContext[ClientSession]
417+
```
418+
374419
### Resource URI type changed from `AnyUrl` to `str`
375420

376421
The `uri` field on resource-related types now uses `str` instead of Pydantic's `AnyUrl`. This aligns with the [MCP specification schema](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/schema/draft/schema.ts) which defines URIs as plain strings (`uri: string`) without strict URL validation. This change allows relative paths like `users/me` that were previously rejected.

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

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,11 @@
77
"""
88

99
import asyncio
10-
from typing import Any
1110

1211
import click
1312
from mcp import ClientSession
13+
from mcp.client.context import ClientRequestContext
1414
from mcp.client.streamable_http import streamable_http_client
15-
from mcp.shared.context import RequestContext
1615
from mcp.types import (
1716
CallToolResult,
1817
CreateMessageRequestParams,
@@ -24,7 +23,7 @@
2423

2524

2625
async def elicitation_callback(
27-
context: RequestContext[ClientSession, Any],
26+
context: ClientRequestContext,
2827
params: ElicitRequestParams,
2928
) -> ElicitResult:
3029
"""Handle elicitation requests from the server."""
@@ -39,7 +38,7 @@ async def elicitation_callback(
3938

4039

4140
async def sampling_callback(
42-
context: RequestContext[ClientSession, Any],
41+
context: ClientRequestContext,
4342
params: CreateMessageRequestParams,
4443
) -> CreateMessageResult:
4544
"""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, None], 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, Any],
41+
context: ClientRequestContext,
4242
params: types.ElicitRequestParams,
4343
) -> types.ElicitResult | types.ErrorData:
4444
"""Handle elicitation requests from the server.

examples/snippets/servers/lifespan_example.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
from dataclasses import dataclass
66

77
from mcp.server.mcpserver import Context, MCPServer
8-
from mcp.server.session import ServerSession
98

109

1110
# Mock database class for example
@@ -51,7 +50,7 @@ async def app_lifespan(server: MCPServer) -> AsyncIterator[AppContext]:
5150

5251
# Access type-safe lifespan context in tools
5352
@mcp.tool()
54-
def query_db(ctx: Context[ServerSession, AppContext]) -> str:
53+
def query_db(ctx: Context[AppContext]) -> str:
5554
"""Tool that uses initialized resources."""
5655
db = ctx.request_context.lifespan_context.db
5756
return db.query()

pyproject.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ authors = [{ name = "Anthropic, PBC." }]
88
maintainers = [
99
{ name = "David Soria Parra", email = "davidsp@anthropic.com" },
1010
{ name = "Justin Spahr-Summers", email = "justin@anthropic.com" },
11+
{ name = "Marcelo Trylesinski", email = "marcelotryle@gmail.com" },
12+
{ name = "Max Isbey", email = "maxisbey@anthropic.com" },
13+
{ name = "Felix Weinberger", email = "fweinberger@anthropic.com" }
1114
]
1215
keywords = ["git", "mcp", "llm", "automation"]
1316
license = { text = "MIT" }

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"]

0 commit comments

Comments
 (0)