Skip to content

[Performance] Upstream: rmcp returns SSE-only responses, no JSON option #1919

@crivetimihai

Description

@crivetimihai

Summary

The Rust MCP SDK (rmcp) always returns text/event-stream (SSE) responses, even for simple request/response operations where application/json would be more efficient. This adds ~5ms parsing overhead per request compared to JSON responses.

Problem

The MCP Streamable HTTP specification allows servers to respond with either:

  • application/json - for simple request/response (efficient)
  • text/event-stream - for streaming/multi-message responses

However, rmcp only implements SSE responses. The StreamableHttpServerConfig struct has no option to enable JSON responses:

// crates/rmcp/src/transport/streamable_http_server/tower.rs
pub struct StreamableHttpServerConfig {
    pub sse_keep_alive: Option<Duration>,  // SSE ping interval
    pub stateful_mode: bool,               // Session persistence
    pub cancellation_token: CancellationToken,
    // NO json_response option
}

Evidence

Response format comparison:

Server Content-Type Format
Go MCP server application/json {"jsonrpc":"2.0",...}
Rust (rmcp) text/event-stream data: {"jsonrpc":"2.0",...}\nid: 0/0

Go server response:

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 94

{"jsonrpc":"2.0","id":2,"result":{...}}

Rust server response:

HTTP/1.1 200 OK
content-type: text/event-stream
transfer-encoding: chunked

data: {"jsonrpc":"2.0","id":2,"result":{...}}
id: 0/0

Parsing overhead: SSE parsing adds ~5ms per request compared to JSON due to:

  • Line-by-line async iteration
  • String operations (partition, startswith, rstrip)
  • SSE event object creation
  • Chunked transfer encoding overhead

Impact

Proposed Upstream Fix

Add json_response option to StreamableHttpServerConfig:

pub struct StreamableHttpServerConfig {
    pub sse_keep_alive: Option<Duration>,
    pub stateful_mode: bool,
    pub json_response: bool,  // NEW: Return JSON for simple responses
    pub cancellation_token: CancellationToken,
}

When json_response: true, the server should return application/json for simple request/response operations (like tools/call), and only use SSE for actual streaming scenarios.

Upstream References

Action Items

  • File upstream issue on modelcontextprotocol/rust-sdk
  • Link upstream issue here when created
  • Track progress of upstream fix
  • Update gateway when fix is available

Workaround

Until rmcp supports JSON responses, the gateway handles SSE parsing correctly via the Python MCP SDK's httpx-sse integration. The ~5ms overhead is acceptable but not ideal for high-throughput scenarios.

Related

Metadata

Metadata

Assignees

Labels

performancePerformance related items

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions