How to Set Up an MCP Server Proxy for Production AI Agents
MCP servers work fine over localhost during development, but production deployments need TLS termination, authentication, and connection management that a reverse proxy provides. This guide walks through proxy architectures for MCP servers, with concrete Nginx and Caddy configurations for Streamable HTTP and SSE transports.
Why MCP Servers Need a Proxy in Production
The Model Context Protocol defines how AI agents discover and call tools on remote servers. During development, you connect directly: agent talks to MCP server on localhost, everything works. But the moment you deploy that server for a team of agents or expose it to the internet, direct connections break down.
Three problems surface immediately:
- TLS termination. MCP servers built with frameworks like FastMCP typically serve plain HTTP. Agents connecting over the internet need encrypted connections, and managing certificates inside your MCP server code adds complexity you don't want.
- Authentication at the edge. You need to verify that incoming requests carry valid tokens before they reach your MCP server process. Handling auth inside the server ties your business logic to your security layer.
- Connection management. MCP's Streamable HTTP transport uses long-lived connections. Without proper timeout configuration, standard web proxies will kill sessions mid-conversation.
A reverse proxy solves all three. Nginx or Caddy sits in front of your MCP server, handles TLS and auth, and forwards clean requests to your application. The MCP server stays focused on tool execution.
What to check before scaling mcp server proxy
Both Nginx and Caddy work well as MCP server proxies, but they make different tradeoffs.
Nginx gives you granular control over every connection parameter. You can tune buffer sizes, upstream keepalive pools, and rate limits with precision. If you already run Nginx in your infrastructure, adding an MCP upstream is straightforward. The downside is certificate management. You will need certbot or another ACME client running alongside Nginx to handle TLS certificates.
Caddy handles TLS automatically. Point it at a domain, and it provisions certificates from Let's Encrypt without additional tooling. The configuration syntax is shorter and more readable. For teams deploying their first MCP proxy, Caddy gets you to production faster.
For MCP servers specifically, the critical difference is streaming support. Both handle it, but the configuration looks different. Nginx requires explicit directives to disable buffering and extend timeouts. Caddy's defaults are closer to what MCP needs out of the box.
If you need fine-grained traffic shaping or already have Nginx infrastructure, use Nginx. If you want the shortest path to a secure, working proxy, use Caddy.
Nginx Configuration for MCP Servers
MCP connections are long-lived, which means the default Nginx configuration will break them. Standard timeouts kill idle connections after 60 seconds, and response buffering interferes with Server-Sent Events streams. Here is a working Nginx configuration for proxying an MCP server:
upstream mcp_backend {
server 127.0.0.1:8000;
keepalive 32;
}
server {
listen 443 ssl;
server_name mcp.example.com;
ssl_certificate /etc/letsencrypt/live/mcp.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/mcp.example.com/privkey.pem;
location /mcp {
proxy_pass http://mcp_backend;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_buffering off;
proxy_cache off;
chunked_transfer_encoding off;
proxy_read_timeout 86400s;
proxy_send_timeout 86400s;
}
location /sse {
proxy_pass http://mcp_backend;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_buffering off;
proxy_cache off;
chunked_transfer_encoding off;
proxy_read_timeout 86400s;
proxy_send_timeout 86400s;
}
}
The key directives:
proxy_http_version 1.1with an emptyConnectionheader enables HTTP/1.1 keepalive to the upstream, which MCP's persistent connections require.proxy_buffering offandproxy_cache offensure SSE events reach the agent immediately instead of being batched by Nginx.proxy_read_timeout 86400sgives connections a 24-hour window. MCP sessions can run for hours during complex agent workflows, and you don't want Nginx closing them prematurely.keepalive 32in the upstream block maintains a pool of persistent connections to your MCP server, reducing connection overhead when multiple agents connect simultaneously.
Skip the proxy setup and connect agents directly
Fast.io's MCP server handles TLS, authentication, and multi-tenant isolation out of the box. 50GB free storage, no credit card required.
Caddy Configuration for MCP Servers
Caddy's configuration for the same setup is shorter because it handles TLS automatically and its defaults align better with streaming workloads:
mcp.example.com {
handle /mcp* {
reverse_proxy localhost:8000 {
flush_interval -1
transport http {
keepalive 30s
keepalive_idle_conns 32
}
}
}
handle /sse* {
reverse_proxy localhost:8000 {
flush_interval -1
transport http {
keepalive 30s
keepalive_idle_conns 32
}
}
}
}
The flush_interval -1 directive tells Caddy to flush response bytes immediately without buffering, which is essential for SSE transport. Caddy provisions TLS certificates from Let's Encrypt automatically when you point a domain at it, so there is no separate certbot step.
For development or internal deployments where you don't need public TLS, Caddy can also proxy on a local port:
:8443 {
reverse_proxy localhost:8000 {
flush_interval -1
}
}
This gives you a clean proxy layer without certificate management overhead.
Multi-Agent Sharing Through a Proxy
A single MCP server can serve multiple agents when you put a proxy in front of it. The proxy handles routing, rate limiting, and tenant isolation while the MCP server processes tool calls.
API key authentication at the proxy is the simplest multi-tenant pattern. Each agent gets a unique API key. The proxy validates the key before forwarding the request:
map $http_x_api_key $valid_key {
"agent-key-alpha" 1;
"agent-key-beta" 1;
default 0;
}
server {
location /mcp {
if ($valid_key = 0) {
return 401;
}
proxy_pass http://mcp_backend;
proxy_set_header X-Agent-ID $http_x_api_key;
}
}
For more sophisticated setups, MCP gateway tools like Portkey, Gravitee, and the open-source MCP Gateway Registry project provide OAuth 2.0 token validation, role-based access control, and per-agent rate limiting out of the box. These sit in the same position as Nginx or Caddy but add MCP-aware routing logic.
Connection pooling matters at scale. Without a proxy, each agent opens its own connection to the MCP server. With the keepalive pool in your proxy configuration, agents share a smaller set of persistent upstream connections. This is where the "10x more agents per server instance" improvement comes from: the MCP server handles fewer TCP handshakes and maintains less connection state.
If you need full tenant isolation rather than shared-server multi-tenancy, consider running separate MCP server processes per tenant and using the proxy for routing based on the agent's identity header.
Using Existing MCP Proxy Tools
You don't always need to configure Nginx or Caddy from scratch. Several purpose-built MCP proxy tools handle the transport bridging for you.
mcp-proxy (npm) is a TypeScript proxy that converts stdio-based MCP servers into Streamable HTTP and SSE endpoints. If your MCP server only supports stdio transport, this tool wraps it with an HTTP layer:
npx mcp-proxy --port 8080 --apiKey "your-secret" -- npx -y @anthropic/mcp-server-filesystem /data
This command starts an HTTP proxy on port 8080 with API key authentication, forwarding requests to the filesystem MCP server. The proxy exposes both /mcp (Streamable HTTP) and /sse (legacy SSE) endpoints. You can then put Nginx or Caddy in front of this for TLS termination.
mcp-proxy-server (by adamwattis on GitHub) aggregates multiple MCP servers behind a single interface. Instead of configuring each agent to connect to five different MCP servers, agents connect to one proxy that routes tool calls to the right backend. This simplifies agent configuration and gives you a single point for logging and access control.
Plugged.in MCP Proxy takes this further with a web UI for managing connected servers, enabling or disabling individual tools, and monitoring traffic across all your MCP servers from one dashboard.
For managed MCP services like Fast.io's MCP server, the proxy layer is already handled. Fast.io exposes Streamable HTTP at /mcp and legacy SSE at /sse, with built-in authentication and multi-tenant workspace isolation. Agents authenticate with API keys or OAuth, and each workspace acts as an isolated tenant with its own files, permissions, and audit trail. No reverse proxy configuration needed on your end.
Securing and Monitoring Your MCP Proxy
A proxy gives you a single point to enforce security policies. Here are the configurations that matter most for MCP deployments.
Rate limiting prevents runaway agents from overwhelming your MCP server. In Nginx:
limit_req_zone $http_x_api_key zone=mcp_limit:10m rate=30r/m;
location /mcp {
limit_req zone=mcp_limit burst=10 nodelay;
proxy_pass http://mcp_backend;
}
This limits each agent to 30 requests per minute with a burst allowance of 10, which is reasonable for most tool-calling patterns.
Access logging captures every tool call for audit purposes. Configure structured JSON logs that include the agent identity, timestamp, and response status:
log_format mcp_json escape=json
'{"time":"$time_iso8601",'
'"agent":"$http_x_api_key",'
'"method":"$request_method",'
'"path":"$uri",'
'"status":$status,'
'"duration":$request_time}';
access_log /var/log/nginx/mcp_access.json mcp_json;
Health checks catch MCP server failures before agents hit them. Add an upstream health check that verifies the MCP server is responding:
upstream mcp_backend {
server 127.0.0.1:8000;
keepalive 32;
}
Pair this with a monitoring tool that hits a health endpoint on your MCP server and alerts when it goes down.
For teams that need audit trails without building logging infrastructure, managed platforms like Fast.io provide built-in event tracking and activity summaries across all agent interactions. Every file operation, workspace change, and AI query is logged with timestamps and agent identity, exportable for compliance review.
Frequently Asked Questions
How do I proxy an MCP server?
Put a reverse proxy like Nginx or Caddy in front of your MCP server. Configure it to forward requests to your MCP server's port, disable response buffering for SSE support, and extend read timeouts to at least 24 hours. Add TLS certificates for encrypted connections. The proxy handles security while your MCP server handles tool execution.
Can multiple agents share one MCP server?
Yes. A reverse proxy enables multi-tenant access by validating API keys or OAuth tokens per agent, then forwarding authenticated requests to a shared MCP server. Connection pooling in the proxy reduces the per-agent overhead, letting a single server instance handle more concurrent agents than direct connections would allow.
How do I secure MCP server connections?
Use TLS termination at the proxy layer so agents connect over HTTPS. Add API key or OAuth token validation before requests reach the MCP server. Configure rate limiting to prevent any single agent from overwhelming the server. Enable structured access logging to create an audit trail of all tool calls.
What is the difference between an MCP proxy and an MCP gateway?
An MCP proxy forwards requests between agents and servers, handling transport concerns like TLS and buffering. An MCP gateway adds application-layer features: OAuth token exchange, role-based access control, per-agent rate limiting, tool-level permissions, and observability dashboards. Gateways are purpose-built for MCP while proxies are general-purpose reverse proxies configured for MCP traffic.
Do I need a proxy for managed MCP services?
No. Managed MCP services like Fast.io handle TLS, authentication, and multi-tenancy on the server side. Agents connect directly using API keys or OAuth tokens. The proxy layer is only necessary when you self-host MCP servers and need to add security, load balancing, or multi-tenant isolation yourself.
Which reverse proxy is better for MCP servers, Nginx or Caddy?
Caddy is faster to set up because it handles TLS certificates automatically and its defaults work well with streaming connections. Nginx gives you more granular control over connection pooling, rate limiting, and traffic shaping. Choose Caddy for simplicity, Nginx for existing infrastructure or advanced traffic management needs.
Related Resources
Skip the proxy setup and connect agents directly
Fast.io's MCP server handles TLS, authentication, and multi-tenant isolation out of the box. 50GB free storage, no credit card required.