feat: add ClientRequestContext type alias for client-side handlers (#1989)

This commit is contained in:
Marcelo Trylesinski 2026-02-03 17:37:38 +01:00 • committed by GitHub
commit 4fc49c62bd
25 changed files with 55 additions and 37 deletions

View file

@ -38,9 +38,9 @@ from mcp.client.auth.extensions.client_credentials import (
PrivateKeyJWTOAuthProvider, PrivateKeyJWTOAuthProvider,
SignedJWTParameters, SignedJWTParameters,
) )
from mcp.client.context import ClientRequestContext
from mcp.client.streamable_http import streamable_http_client from mcp.client.streamable_http import streamable_http_client
from mcp.shared.auth import OAuthClientInformationFull, OAuthClientMetadata, OAuthToken from mcp.shared.auth import OAuthClientInformationFull, OAuthClientMetadata, OAuthToken
from mcp.shared.context import RequestContext
# Set up logging to stderr (stdout is for conformance test output) # Set up logging to stderr (stdout is for conformance test output)
logging.basicConfig( logging.basicConfig(
@ -187,7 +187,7 @@ async def run_sse_retry(server_url: str) -> None:
async def default_elicitation_callback( async def default_elicitation_callback(
context: RequestContext[ClientSession], context: ClientRequestContext,
params: types.ElicitRequestParams, params: types.ElicitRequestParams,
) -> types.ElicitResult | types.ErrorData: ) -> types.ElicitResult | types.ErrorData:
"""Accept elicitation and apply defaults from the schema (SEP-1034).""" """Accept elicitation and apply defaults from the schema (SEP-1034)."""

View file

@ -2120,8 +2120,8 @@ import asyncio
import os import os
from mcp import ClientSession, StdioServerParameters, types from mcp import ClientSession, StdioServerParameters, types
from mcp.client.context import ClientRequestContext
from mcp.client.stdio import stdio_client from mcp.client.stdio import stdio_client
from mcp.shared.context import RequestContext
# Create server parameters for stdio connection # Create server parameters for stdio connection
server_params = StdioServerParameters( server_params = StdioServerParameters(
@ -2133,7 +2133,7 @@ server_params = StdioServerParameters(
# Optional: create a sampling callback # Optional: create a sampling callback
async def handle_sampling_message( async def handle_sampling_message(
context: RequestContext[ClientSession, None], params: types.CreateMessageRequestParams context: ClientRequestContext, params: types.CreateMessageRequestParams
) -> types.CreateMessageResult: ) -> types.CreateMessageResult:
print(f"Sampling request: {params.messages}") print(f"Sampling request: {params.messages}")
return types.CreateMessageResult( return types.CreateMessageResult(

View file

@ -2121,8 +2121,8 @@ import asyncio
import os import os
from mcp import ClientSession, StdioServerParameters, types from mcp import ClientSession, StdioServerParameters, types
from mcp.client.context import ClientRequestContext
from mcp.client.stdio import stdio_client from mcp.client.stdio import stdio_client
from mcp.shared.context import RequestContext
# Create server parameters for stdio connection # Create server parameters for stdio connection
server_params = StdioServerParameters( server_params = StdioServerParameters(
@ -2134,7 +2134,7 @@ server_params = StdioServerParameters(
# Optional: create a sampling callback # Optional: create a sampling callback
async def handle_sampling_message( async def handle_sampling_message(
context: RequestContext[ClientSession], params: types.CreateMessageRequestParams context: ClientRequestContext, params: types.CreateMessageRequestParams
) -> types.CreateMessageResult: ) -> types.CreateMessageResult:
print(f"Sampling request: {params.messages}") print(f"Sampling request: {params.messages}")
return types.CreateMessageResult( return types.CreateMessageResult(

View file

@ -387,6 +387,7 @@ The `RequestContext` class has been split to separate shared fields from server-
**Before (v1):** **Before (v1):**
```python ```python
from mcp.client.session import ClientSession
from mcp.shared.context import RequestContext, LifespanContextT, RequestT from mcp.shared.context import RequestContext, LifespanContextT, RequestT
from mcp.shared.progress import ProgressContext from mcp.shared.progress import ProgressContext
@ -400,19 +401,19 @@ progress_ctx: ProgressContext[SendRequestT, SendNotificationT, SendResultT, Rece
**After (v2):** **After (v2):**
```python ```python
from mcp.shared.context import RequestContext from mcp.client.context import ClientRequestContext
from mcp.client.session import ClientSession
from mcp.server.context import ServerRequestContext, LifespanContextT, RequestT
from mcp.shared.progress import ProgressContext from mcp.shared.progress import ProgressContext
# RequestContext with 1 type parameter # For client-side context (sampling, elicitation, list_roots callbacks)
ctx: RequestContext[ClientSession] ctx: ClientRequestContext
# For server-specific context with lifespan and request types
server_ctx: ServerRequestContext[LifespanContextT, RequestT]
# ProgressContext with 1 type parameter # ProgressContext with 1 type parameter
progress_ctx: ProgressContext[ClientSession] progress_ctx: ProgressContext[ClientSession]
# For server-specific context with lifespan and request types
from mcp.server.context import ServerRequestContext, LifespanContextT, RequestT
server_ctx: ServerRequestContext[LifespanContextT, RequestT]
``` ```
### Resource URI type changed from `AnyUrl` to `str` ### Resource URI type changed from `AnyUrl` to `str`

View file

@ -10,8 +10,8 @@ import asyncio
import click import click
from mcp import ClientSession from mcp import ClientSession
from mcp.client.context import ClientRequestContext
from mcp.client.streamable_http import streamable_http_client from mcp.client.streamable_http import streamable_http_client
from mcp.shared.context import RequestContext
from mcp.types import ( from mcp.types import (
CallToolResult, CallToolResult,
CreateMessageRequestParams, CreateMessageRequestParams,
@ -23,7 +23,7 @@ from mcp.types import (
async def elicitation_callback( async def elicitation_callback(
context: RequestContext[ClientSession], context: ClientRequestContext,
params: ElicitRequestParams, params: ElicitRequestParams,
) -> ElicitResult: ) -> ElicitResult:
"""Handle elicitation requests from the server.""" """Handle elicitation requests from the server."""
@ -38,7 +38,7 @@ async def elicitation_callback(
async def sampling_callback( async def sampling_callback(
context: RequestContext[ClientSession], context: ClientRequestContext,
params: CreateMessageRequestParams, params: CreateMessageRequestParams,
) -> CreateMessageResult: ) -> CreateMessageResult:
"""Handle sampling requests from the server.""" """Handle sampling requests from the server."""

View file

@ -6,8 +6,8 @@ import asyncio
import os import os
from mcp import ClientSession, StdioServerParameters, types from mcp import ClientSession, StdioServerParameters, types
from mcp.client.context import ClientRequestContext
from mcp.client.stdio import stdio_client from mcp.client.stdio import stdio_client
from mcp.shared.context import RequestContext
# Create server parameters for stdio connection # Create server parameters for stdio connection
server_params = StdioServerParameters( server_params = StdioServerParameters(
@ -19,7 +19,7 @@ server_params = StdioServerParameters(
# Optional: create a sampling callback # Optional: create a sampling callback
async def handle_sampling_message( async def handle_sampling_message(
context: RequestContext[ClientSession], params: types.CreateMessageRequestParams context: ClientRequestContext, params: types.CreateMessageRequestParams
) -> types.CreateMessageResult: ) -> types.CreateMessageResult:
print(f"Sampling request: {params.messages}") print(f"Sampling request: {params.messages}")
return types.CreateMessageResult( return types.CreateMessageResult(

View file

@ -31,14 +31,14 @@ from typing import Any
from urllib.parse import urlparse from urllib.parse import urlparse
from mcp import ClientSession, types from mcp import ClientSession, types
from mcp.client.context import ClientRequestContext
from mcp.client.sse import sse_client from mcp.client.sse import sse_client
from mcp.shared.context import RequestContext
from mcp.shared.exceptions import MCPError, UrlElicitationRequiredError from mcp.shared.exceptions import MCPError, UrlElicitationRequiredError
from mcp.types import URL_ELICITATION_REQUIRED from mcp.types import URL_ELICITATION_REQUIRED
async def handle_elicitation( async def handle_elicitation(
context: RequestContext[ClientSession], context: ClientRequestContext,
params: types.ElicitRequestParams, params: types.ElicitRequestParams,
) -> types.ElicitResult | types.ErrorData: ) -> types.ElicitResult | types.ErrorData:
"""Handle elicitation requests from the server. """Handle elicitation requests from the server.

View file

@ -2,6 +2,7 @@
from mcp.client._transport import Transport from mcp.client._transport import Transport
from mcp.client.client import Client from mcp.client.client import Client
from mcp.client.context import ClientRequestContext
from mcp.client.session import ClientSession from mcp.client.session import ClientSession
__all__ = ["Client", "ClientSession", "Transport"] __all__ = ["Client", "ClientRequestContext", "ClientSession", "Transport"]

16
src/mcp/client/context.py Normal file
View file

@ -0,0 +1,16 @@
"""Request context for MCP client handlers."""
from mcp.client.session import ClientSession
from mcp.shared._context import RequestContext
ClientRequestContext = RequestContext[ClientSession]
"""Context for handling incoming requests in a client session.
This context is passed to client-side callbacks (sampling, elicitation, list_roots) when the server sends requests
to the client.
Attributes:
request_id: The unique identifier for this request.
meta: Optional metadata associated with the request.
session: The client session handling this request.
"""

View file

@ -19,7 +19,7 @@ from typing import TYPE_CHECKING, Protocol
from pydantic import TypeAdapter from pydantic import TypeAdapter
import mcp.types as types import mcp.types as types
from mcp.shared.context import RequestContext from mcp.shared._context import RequestContext
from mcp.shared.session import RequestResponder from mcp.shared.session import RequestResponder
if TYPE_CHECKING: if TYPE_CHECKING:

View file

@ -10,7 +10,7 @@ from pydantic import TypeAdapter
import mcp.types as types import mcp.types as types
from mcp.client.experimental import ExperimentalClientFeatures from mcp.client.experimental import ExperimentalClientFeatures
from mcp.client.experimental.task_handlers import ExperimentalTaskHandlers from mcp.client.experimental.task_handlers import ExperimentalTaskHandlers
from mcp.shared.context import RequestContext from mcp.shared._context import RequestContext
from mcp.shared.message import SessionMessage from mcp.shared.message import SessionMessage
from mcp.shared.session import BaseSession, ProgressFnT, RequestResponder from mcp.shared.session import BaseSession, ProgressFnT, RequestResponder
from mcp.shared.version import SUPPORTED_PROTOCOL_VERSIONS from mcp.shared.version import SUPPORTED_PROTOCOL_VERSIONS

View file

@ -7,7 +7,7 @@ from typing_extensions import TypeVar
from mcp.server.experimental.request_context import Experimental from mcp.server.experimental.request_context import Experimental
from mcp.server.session import ServerSession from mcp.server.session import ServerSession
from mcp.shared.context import RequestContext from mcp.shared._context import RequestContext
from mcp.shared.message import CloseSSEStreamCallback from mcp.shared.message import CloseSSEStreamCallback
LifespanContextT = TypeVar("LifespanContextT") LifespanContextT = TypeVar("LifespanContextT")

View file

@ -0,0 +1,20 @@
"""Request context for MCP handlers."""
from dataclasses import dataclass
from typing import Any, Generic
from typing_extensions import TypeVar
from mcp.shared.session import BaseSession
from mcp.types import RequestId, RequestParamsMeta
SessionT = TypeVar("SessionT", bound=BaseSession[Any, Any, Any, Any, Any])
@dataclass(kw_only=True)
class RequestContext(Generic[SessionT]):
"""Common context for handling incoming requests."""
request_id: RequestId
meta: RequestParamsMeta | None
session: SessionT

View file

@ -5,7 +5,7 @@ from typing import Generic
from pydantic import BaseModel from pydantic import BaseModel
from mcp.shared.context import RequestContext, SessionT from mcp.shared._context import RequestContext, SessionT
from mcp.types import ProgressToken from mcp.types import ProgressToken

View file

@ -5,7 +5,7 @@ from mcp import Client
from mcp.client.session import ClientSession from mcp.client.session import ClientSession
from mcp.server.mcpserver import MCPServer from mcp.server.mcpserver import MCPServer
from mcp.server.mcpserver.server import Context from mcp.server.mcpserver.server import Context
from mcp.shared.context import RequestContext from mcp.shared._context import RequestContext
from mcp.types import ListRootsResult, Root, TextContent from mcp.types import ListRootsResult, Root, TextContent

View file

@ -3,7 +3,7 @@ import pytest
from mcp import Client from mcp import Client
from mcp.client.session import ClientSession from mcp.client.session import ClientSession
from mcp.server.mcpserver import MCPServer from mcp.server.mcpserver import MCPServer
from mcp.shared.context import RequestContext from mcp.shared._context import RequestContext
from mcp.types import ( from mcp.types import (
CreateMessageRequestParams, CreateMessageRequestParams,
CreateMessageResult, CreateMessageResult,

View file

@ -5,7 +5,7 @@ import pytest
import mcp.types as types import mcp.types as types
from mcp.client.session import DEFAULT_CLIENT_INFO, ClientSession from mcp.client.session import DEFAULT_CLIENT_INFO, ClientSession
from mcp.shared.context import RequestContext from mcp.shared._context import RequestContext
from mcp.shared.message import SessionMessage from mcp.shared.message import SessionMessage
from mcp.shared.session import RequestResponder from mcp.shared.session import RequestResponder
from mcp.shared.version import SUPPORTED_PROTOCOL_VERSIONS from mcp.shared.version import SUPPORTED_PROTOCOL_VERSIONS

View file

@ -7,7 +7,7 @@ import mcp.types as types
from mcp import ClientCapabilities from mcp import ClientCapabilities
from mcp.client.experimental.task_handlers import ExperimentalTaskHandlers from mcp.client.experimental.task_handlers import ExperimentalTaskHandlers
from mcp.client.session import ClientSession from mcp.client.session import ClientSession
from mcp.shared.context import RequestContext from mcp.shared._context import RequestContext
from mcp.shared.message import SessionMessage from mcp.shared.message import SessionMessage
from mcp.types import ( from mcp.types import (
LATEST_PROTOCOL_VERSION, LATEST_PROTOCOL_VERSION,

View file

@ -22,7 +22,7 @@ from anyio.streams.memory import MemoryObjectReceiveStream, MemoryObjectSendStre
import mcp.types as types import mcp.types as types
from mcp.client.experimental.task_handlers import ExperimentalTaskHandlers from mcp.client.experimental.task_handlers import ExperimentalTaskHandlers
from mcp.client.session import ClientSession from mcp.client.session import ClientSession
from mcp.shared.context import RequestContext from mcp.shared._context import RequestContext
from mcp.shared.experimental.tasks.in_memory_task_store import InMemoryTaskStore from mcp.shared.experimental.tasks.in_memory_task_store import InMemoryTaskStore
from mcp.shared.message import SessionMessage from mcp.shared.message import SessionMessage
from mcp.shared.session import RequestResponder from mcp.shared.session import RequestResponder

View file

@ -20,7 +20,7 @@ from mcp.client.session import ClientSession
from mcp.server import Server from mcp.server import Server
from mcp.server.experimental.task_context import ServerTaskContext from mcp.server.experimental.task_context import ServerTaskContext
from mcp.server.lowlevel import NotificationOptions from mcp.server.lowlevel import NotificationOptions
from mcp.shared.context import RequestContext from mcp.shared._context import RequestContext
from mcp.shared.experimental.tasks.helpers import is_terminal from mcp.shared.experimental.tasks.helpers import is_terminal
from mcp.shared.experimental.tasks.in_memory_task_store import InMemoryTaskStore from mcp.shared.experimental.tasks.in_memory_task_store import InMemoryTaskStore
from mcp.shared.message import SessionMessage from mcp.shared.message import SessionMessage

Some files were not shown because too many files have changed in this diff Show more