-
Notifications
You must be signed in to change notification settings - Fork 457
Description
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/0Parsing 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
- Gateway must parse SSE format for every response from rmcp-based servers
- Additional CPU overhead under load
- This is a secondary performance issue (primary is session pooling - see [Performance] Implement MCP client session pooling to reduce per-request overhead (optional) #1918)
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
- rmcp repository: https://github.com/modelcontextprotocol/rust-sdk
- MCP Streamable HTTP spec: https://modelcontextprotocol.io/specification/2025-06-18/basic/transports/streamable-http
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
- [Performance] Implement MCP client session pooling to reduce per-request overhead (optional) #1918 - MCP session pooling (primary performance fix)