feat: add ClientRequestContext type alias for client-side handlers (#1989)
This commit is contained in:
parent
74f41ff1ae
commit
4fc49c62bd
25 changed files with 55 additions and 37 deletions
4
.github/actions/conformance/client.py
vendored
4
.github/actions/conformance/client.py
vendored
|
|
@ -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)."""
|
||||||
|
|
|
||||||
|
|
@ -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(
|
||||||
|
|
|
||||||
|
|
@ -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(
|
||||||
|
|
|
||||||
|
|
@ -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`
|
||||||
|
|
|
||||||
|
|
@ -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."""
|
||||||
|
|
|
||||||
|
|
@ -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(
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
|
||||||
|
|
@ -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
16
src/mcp/client/context.py
Normal 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.
|
||||||
|
"""
|
||||||
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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")
|
||||||
|
|
|
||||||
20
src/mcp/shared/_context.py
Normal file
20
src/mcp/shared/_context.py
Normal 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
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
Loading…
Reference in a new issue