Skip to content

transport_context

Transport-specific metadata attached to each inbound message.

TransportContext is the base; each transport defines its own subclass with whatever fields make sense (HTTP request id, ASGI scope, stdio process handle, etc.). The dispatcher passes it through opaquely; only the layers above the dispatcher (ServerRunner, Context, user handlers) read its concrete fields.

TransportContext dataclass

Base transport metadata for an inbound message.

Subclass per transport and add fields as needed. Instances are immutable.

Source code in src/mcp/shared/transport_context.py
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
@dataclass(kw_only=True, frozen=True)
class TransportContext:
    """Base transport metadata for an inbound message.

    Subclass per transport and add fields as needed. Instances are immutable.
    """

    kind: str
    """Short identifier for the transport (e.g. `"stdio"`, `"streamable-http"`)."""

    can_send_request: bool
    """Whether this message's request-scoped channel can deliver a server-initiated request.

    `False` for any of three reasons: the response has no room (streamable
    HTTP in JSON-response mode and the 2026-07-28 single-exchange entry answer
    with one JSON-RPC reply), the client's reply has nowhere to land (stateless
    HTTP, no session), or the protocol forbids server-initiated requests (any
    2026-07-28 connection, whose dispatch masks the flag off). `True` for a
    plain duplex pipe (stdio, SSE) and stateful streamable HTTP with SSE
    responses, all pre-2026-07-28. When `False`,
    `DispatchContext.send_raw_request` raises `NoBackChannelError` instead of
    parking a waiter no reply can reach. Says nothing about the connection's
    standalone channel, which refuses separately.
    """

    headers: Mapping[str, str] | None = None
    """Request headers carried by this message, when the transport has them.

    Populated by HTTP-based transports; `None` on stdio. Handlers should
    None-check before use.
    """

kind instance-attribute

kind: str

Short identifier for the transport (e.g. "stdio", "streamable-http").

can_send_request instance-attribute

can_send_request: bool

Whether this message's request-scoped channel can deliver a server-initiated request.

False for any of three reasons: the response has no room (streamable HTTP in JSON-response mode and the 2026-07-28 single-exchange entry answer with one JSON-RPC reply), the client's reply has nowhere to land (stateless HTTP, no session), or the protocol forbids server-initiated requests (any 2026-07-28 connection, whose dispatch masks the flag off). True for a plain duplex pipe (stdio, SSE) and stateful streamable HTTP with SSE responses, all pre-2026-07-28. When False, DispatchContext.send_raw_request raises NoBackChannelError instead of parking a waiter no reply can reach. Says nothing about the connection's standalone channel, which refuses separately.

headers class-attribute instance-attribute

headers: Mapping[str, str] | None = None

Request headers carried by this message, when the transport has them.

Populated by HTTP-based transports; None on stdio. Handlers should None-check before use.