-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Open
Description
Summary
The SDK currently implements multiple server and client transports (stdio, SSE, WebSocket, Streamable HTTP). Each one has its own message loop, error handling, and resource management logic with significant duplication.
This makes it harder to:
- fix bugs consistently across transports,
- add new transports, and
- ensure feature parity between them.
A small Transport abstraction could centralize most of the shared behavior.
Problems
- Duplication: Similar read/write loops and error handling are repeated in:
src/mcp/server/stdio.pysrc/mcp/server/sse.pysrc/mcp/server/websocket.pysrc/mcp/server/streamable_http.py
- Inconsistent behavior: Features like cancellation, error mapping, and shutdown can diverge between transports.
- Maintenance cost: Adding a new transport or changing session semantics requires updating each implementation.
Proposal
-
Define a
Transportprotocol/interfaceFor example:
class Transport(Protocol): async def connect(self) -> None: ... async def send_message(self, message: JSONType) -> None: ... async def receive_message(self) -> JSONType | None: ... async def close(self) -> None: ...
- Implementations handle encoding details (JSON lines, SSE, WebSocket frames, HTTP streaming).
-
Refactor sessions to depend on
TransportBaseSession(and server/client sessions) should operate on aTransportinstance rather than transport-specific primitives.- Transport-agnostic session logic (request routing, error mapping) lives in one place.
-
Align behavior across transports
-
Standardize behavior for:
- connection setup/teardown,
- error handling,
- cancellation and shutdown semantics.
-
-
Incremental migration
- Start with one or two transports (e.g. stdio + Streamable HTTP) to validate the abstraction.
- Gradually migrate remaining transports.
Why this matters
- Consistency: Users can expect the same semantics regardless of transport choice.
- Easier maintenance: Bug fixes and feature additions happen once, in a shared layer.
- Future-proofing: Adding new transports becomes easier and less error-prone.
Acceptance criteria
- A
Transportinterface (or equivalent) is defined for server and client usage. - At least two transports are refactored to use the shared abstraction.
- Session logic no longer duplicates transport-specific read/write loops.
- Tests verify identical semantics (errors, cancellation, shutdown) across transports.
Metadata
Metadata
Assignees
Labels
No labels