Files
kefu/wechat_rpa/.venv/Lib/site-packages/mcp/shared/context.py
T
2026-09-21 10:34:06 +08:00

86 lines
3.0 KiB
Python

"""`BaseContext` - the user-facing per-request context.
Composition over a `DispatchContext`: forwards the transport metadata, the
back-channel (`send_raw_request`/`notify`), progress reporting, and the cancel
event. Adds `meta` (the inbound request's `_meta` field).
Satisfies `Outbound`, so `ClientPeer` can wrap it. Shared between client and
server: the server's `Context` extends this with `lifespan`/`connection`;
`ClientContext` is just an alias.
"""
from collections.abc import Mapping
from typing import Any, Generic
import anyio
from mcp_types import RequestParamsMeta
from typing_extensions import TypeVar
from mcp.shared.dispatcher import CallOptions, DispatchContext
from mcp.shared.transport_context import TransportContext
__all__ = ["BaseContext"]
TransportT = TypeVar("TransportT", bound=TransportContext, default=TransportContext, covariant=True)
class BaseContext(Generic[TransportT]):
"""Per-request context wrapping a `DispatchContext`.
`ServerRunner` constructs one per inbound request and passes it to the
user's handler.
"""
def __init__(self, dctx: DispatchContext[TransportT], meta: RequestParamsMeta | None = None) -> None:
self._dctx = dctx
self._meta = meta
@property
def transport(self) -> TransportT:
"""Transport-specific metadata for this inbound request."""
return self._dctx.transport
@property
def cancel_requested(self) -> anyio.Event:
"""Set when the peer sends `notifications/cancelled` for this request."""
return self._dctx.cancel_requested
@property
def can_send_request(self) -> bool:
"""Whether the back-channel can currently deliver server-initiated requests.
`False` when the transport has no back-channel, or when the underlying
dispatch context has been closed because the inbound request finished.
"""
return self._dctx.can_send_request
@property
def meta(self) -> RequestParamsMeta | None:
"""The inbound request's `_meta` field, if present."""
return self._meta
async def send_raw_request(
self,
method: str,
params: Mapping[str, Any] | None,
opts: CallOptions | None = None,
) -> dict[str, Any]:
"""Send a request to the peer on the back-channel.
Raises:
MCPError: The peer responded with an error.
NoBackChannelError: `can_send_request` is `False`.
"""
return await self._dctx.send_raw_request(method, params, opts)
async def notify(self, method: str, params: Mapping[str, Any] | None, opts: CallOptions | None = None) -> None:
"""Send a notification to the peer on the back-channel."""
await self._dctx.notify(method, params, opts)
async def report_progress(self, progress: float, total: float | None = None, message: str | None = None) -> None:
"""Report progress for this request, if the peer supplied a progress token.
A no-op when no token was supplied.
"""
await self._dctx.progress(progress, total, message)