Skip to content

Transports

TransportClientServerDescription
StdioYesYesstdin/stdout pipes, subprocess communication
Streamable HTTPYesYesHTTP POST with streaming server-sent events
SSEYesYes¹Server-Sent Events for push notifications
WebSocketYesNoTCP-based bidirectional (libhv WebSocketClient)
InMemoryYesYesIn-process for testing

Streamable HTTP

The Streamable HTTP transport implements the MCP Streamable HTTP specification. Each session uses an internal StreamableHttpSessionTransport (wrapping ITransport) with its own message channel and background thread.

Request flow: Client sends a JSON-RPC message via HTTP POST. The server validates Mcp-Method and Mcp-Name headers against the body (SEP-2243), echoes them back on the response, and extracts Mcp-Param-* headers into _meta.x-mcp-headers. If the response is JSON, the server responds synchronously in stateless mode (with pending-response correlation via std::promise) or returns 202 Accepted in session mode. If the response is SSE (text/event-stream), the server keeps the connection open and streams events.

SSE read loop: On the client side, when the POST response has Content-Type: text/event-stream, a background thread (SseReadLoop) reads chunks, splits on \n\n delimiters, parses data: lines, and enqueues JsonRpcMessage into the MessageChannel.

Headers (StreamableHttpClientTransport):

  • MCP-Protocol-Version: 2026-07-28 — always sent
  • Mcp-Method — dynamic, derived from JSON-RPC body method field
  • Mcp-Param-* — primitive params extracted for middleware routing (strings, integers, booleans only)
  • Accept: application/json, text/event-stream — allows server to pick response mode

Transport Interfaces

ITransport (session connection)
  └── TransportBase (3-state: Initial → Connected → Disconnected)
      ├── StdioServerTransport
      ├── StdioClientSessionTransport (internal)
      ├── InMemoryTransportImpl
      ├── SseClientSessionTransport (internal)
      ├── WebSocketSessionTransport (wraps hv::WebSocketClient)
      ├── StreamableHttpServerTransport
      └── StreamableHttpSessionTransport (internal)

IClientTransport (connection factory)
  ├── StdioClientTransport (PlatformIO)
  ├── SseClientTransport (libhv HttpClient + requests::post)
  ├── StreamableHttpClientTransport (libhv requests::post / WinHTTP)
  └── WebSocketClientTransport (libhv WebSocketClient)

Key Types

HttpTransportMode

Controls how the HTTP client transport connects:

ValueDescription
AutoDetectProbe server/discover first; fall back to SSE POST
StreamableHttpUse Streamable HTTP directly (requires 2026-07-28+)
SseUse legacy SSE POST only

StdioClientTransportOptions

FieldTypeDefaultDescription
commandstd::stringrequiredSubprocess command
argumentsstd::vector<std::string>{}Command-line arguments
namestd::string"stdio"Transport name
working_directorystd::string""Subprocess working directory
inherit_environment_variablesbooltrueInherit parent environment
environment_variablesstd::map<std::string, std::string>{}Additional env vars

HttpClientTransportOptions

FieldTypeDefaultDescription
endpointstd::stringrequiredServer endpoint URL
transport_modeHttpTransportModeAutoDetectConnection mode
namestd::string""Transport name
known_session_idstd::string""Session ID for resumption
additional_headersstd::map<std::string, std::string>{}Extra HTTP headers

StreamableHttpServerOptions

FieldTypeDefaultDescription
portuint16_t3001HTTP server port
endpointstd::string"/mcp"HTTP endpoint path
statelessboolfalseEnable 2026-07-28 stateless mode
enable_legacy_ssebooltrueServe SSE stream on GET
event_storestd::shared_ptr<EventStore>nullptrEvent store for resumption
server_namestd::string"mcp-server"Server name for discovery
server_versionstd::string"0.1.0"Server version for discovery

InMemoryTransport::Pair

cpp
struct Pair {
    std::shared_ptr<ITransport> client;
    std::shared_ptr<ITransport> server;
};

¹ SSE server-side is provided through StreamableHttpServerTransport when enable_legacy_sse is true (default), which serves an SSE stream on the same endpoint via HTTP GET.

Stateless Mode

StreamableHttpServerTransport supports stateless mode controlled by StreamableHttpServerOptions::stateless (default false). When true, IsStateless() returns true and:

  • No sessions: Each request is independent; the response is correlated synchronously via std::promise with a 30-second timeout.
  • No SSE: Server-initiated notifications are delivered inline via JSON response; EventStore append is skipped.
  • MRTR disabled: The server disables InputRequiredResult — requests must carry full context via _meta and requestState (opaque token for cross-request state recovery).