MCP Session Affinity With F5 NGINX Plus
As MCP (Model Context Protocol) adoption grows, ensuring high availability and performance to support a large number of clients concurrently becomes critical.
The most direct way to address this is simply to deploy more MCP servers in the backend, sitting behind a load balancer to distribute the load. With the latest MCP specification (2025-03-26) introducing Streamable HTTP , the communications between MCP clients and servers are predominantly a series of exchanges via HTTP POST requests and responses. Such a stateless nature makes load balancing straightforward for many of the use cases where MCP is treated as a wrapper for REST API.
MCP Session Management Woe
However, there are cases where persistent client-server relationships are required, which is why the MCP specification addresses include a section on session management:
- During the initialization handshake, the MCP server issues a session identifier via the mcp-session-id header in the response.
- All subsequent requests from the client must include this session ID in the request headers.
- MCP servers validate incoming session IDs and reject requests with unknown or invalid identifiers.
This does introduce another problem: when a basic load balancer is deployed in front of the MCP servers, session continuity will be broken if POST requests after the initial setup are sent to another MCP server that has no knowledge of the session ID:
Thus, some form of session affinity, or session persistence is required.
MCP Session Affinity Options
Most load balancers support session stickiness through the following mechanisms, but there are some downsides:
- Session cookies - though simple, do not work well for programmatic access via API, or any non-browser-based client.
- Client/source IP and port - again, works well if clients are directly connecting to the server, but the reality is many clients sit behind common proxies or end up sharing NAT-ed IPs, creating uneven load distribution towards the server.
A more intelligent session tracking solution is required, which is where F5 NGINX Plus comes in.
NGINX Plus Enabling MCP Session Affinity
Leveraging sticky learn directive, NGINX Plus can monitor the session ID issued by MCP servers and dynamically maintain session-to-server mappings:
- NGINX Plus extracts the session ID from the mcp-session-id header in the Initialization response from the MCP server.
- NGINX Plus records the session ID and its corresponding upstream server in its internal session store.
- When subsequent requests arrive, NGINX Plus looks up the session ID in the request header and routes traffic to the corresponding MCP server, as mapped in the internal session store
The setup enables session affinity without requiring changes to client-side code, allowing MCP servers to be scaled out transparently.
Below is a sample F5 NGINX configuration to achieve the outcome:
http {
upstream mcp-server {
sticky learn
create=$sent_http_mcp_session_id
lookup=$http_mcp_session_id
zone=client_sessions:1m;
zone backend 64k;
server server-a:8001;
server server-b:8002;
}
server {
listen 8000;
location /mcp/ {
proxy_pass http://mcp-server/mcp/;
}
}
}
Other considerations that can be made on NGINX to further improve the architecture include:
- Improving system uptime with NGINX's health check capabilities, ensuring MCP servers that are healthy always handle client requests,
- Protecting MCP servers against attacks with F5 NGINX App Protect WAF and DoS,
to name a few.
Conclusion
NGINX Plus's configurable session tracking capability enables a large number of clients to be served concurrently by multiple MCP servers, while maintaining client-server mappings, ultimately enabling organizations to deploy scalable MCP server architecture and address use cases that require stateful sessions.