Heuristic:OpenHands OpenHands Streamable HTTP Over SSE
| Knowledge Sources | |
|---|---|
| Domains | Distributed_Systems, SaaS_Infrastructure |
| Last Updated | 2026-02-11 21:00 GMT |
Overview
Use Streamable HTTP instead of SSE for MCP connections in distributed environments to avoid stateful connection problems with pod restarts and replica routing.
Description
For the Model Context Protocol (MCP) client connections to the main app server, OpenHands explicitly chooses Streamable HTTP over Server-Sent Events (SSE). This is a deliberate architectural decision documented in the codebase. SSE connections are long-lived and stateful, which creates two major problems in distributed Kubernetes environments: (1) subsequent requests from the same client may hit different replicas, breaking the connection state, and (2) pod restarts kill the SSE connection with no recovery mechanism. Streamable HTTP is stateless and can be routed to any replica, making it naturally compatible with horizontal scaling and pod restarts.
Usage
Apply this pattern when choosing between SSE and HTTP for any long-lived client-server communication in the OpenHands SaaS environment. This is particularly relevant for the MCP protocol integration but applies to any service-to-service communication that must work across multiple server replicas behind a load balancer.
The Insight (Rule of Thumb)
- Action: Use Streamable HTTP (`MCPSHTTPServerConfig`) instead of SSE for MCP connections.
- Value: Eliminates the need for sticky sessions or bespoke replica-routing logic.
- Trade-off: Slightly higher per-request overhead compared to SSE (new HTTP connection per request vs persistent connection), but the operational simplicity is worth the cost.
Reasoning
The architectural decision is justified by three factors:
- Performance: Streamable HTTP offers better performance than SSE for the MCP request-response pattern (no keep-alive overhead).
- Statelessness: Stateless connections are essential for distributed server environments. Any replica can handle any request without session affinity.
- Resilience to pod restarts: Long-lived SSE connections are killed when a pod restarts during a rolling deployment, and there is no automatic reconnection mechanism in the MCP protocol. HTTP requests naturally retry on failure.
Code evidence from `enterprise/server/mcp/mcp_config.py:14-22`:
# We opt for Streamable HTTP over SSE connection to the main app server's MCP
# Reasoning:
# 1. Better performance over SSE
# 2. Allows stateless MCP client connections, essential for distributed server environments
#
# The second point is very important - any long lived stateful connections (like SSE) will
# require bespoke implementation to make sure all subsequent requests hit the same replica. It is
# also not resistant to replica pod restarts (it will kill the connection and there's no recovering from it)
# NOTE: these details are specific to the MCP protocol
MCP config creation from `enterprise/server/mcp/mcp_config.py:52-54`:
return MCPSHTTPServerConfig(
url=f'https://{host}/mcp/mcp', api_key=api_key
), []