Skip to main content

Production Guide

Best practices for deploying Open MCP Gateway in production environments.

Pre-Deployment Checklist

  • API key authentication enabled
  • HTTPS/TLS configured (via reverse proxy)
  • Log level set to warn or info
  • Health checks configured
  • Resource limits set
  • Backup strategy for configuration
  • Monitoring and alerting configured
  • Runbook documented

Security

Enable Authentication

Always require API key in production:

# config.yaml
api_key: "${MCP_GATEWAY_API_KEY}"
# Set via environment
export MCP_GATEWAY_API_KEY=$(openssl rand -base64 32)

Use HTTPS

Deploy behind a reverse proxy that handles TLS:

Nginx:

server {
listen 443 ssl http2;
server_name mcp-gateway.example.com;

ssl_certificate /etc/letsencrypt/live/mcp-gateway.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/mcp-gateway.example.com/privkey.pem;

location / {
proxy_pass http://127.0.0.1:4444;
proxy_http_version 1.1;
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;
}
}

Traefik:

# docker-compose.yml
services:
traefik:
image: traefik:v2.10
command:
- "--entrypoints.websecure.address=:443"
- "--certificatesresolvers.letsencrypt.acme.email=admin@example.com"
- "--certificatesresolvers.letsencrypt.acme.storage=/acme.json"
- "--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web"
ports:
- "443:443"

mcp-gateway:
image: ghcr.io/agentic/mcp-gateway:latest
labels:
- "traefik.enable=true"
- "traefik.http.routers.mcp-gateway.rule=Host(`mcp-gateway.example.com`)"
- "traefik.http.routers.mcp-gateway.tls.certresolver=letsencrypt"

Network Security

Bind to localhost if behind a proxy:

# config.yaml
listen_addr: "127.0.0.1:4444"

Or use firewall rules:

# Allow only from load balancer
ufw allow from 10.0.0.0/8 to any port 4444
ufw deny 4444

Secret Management

HashiCorp Vault:

# Fetch secrets from Vault
export MCP_GATEWAY_API_KEY=$(vault kv get -field=api_key secret/mcp-gateway)
export DATABASE_URL=$(vault kv get -field=url secret/database)

AWS Secrets Manager:

export MCP_GATEWAY_API_KEY=$(aws secretsmanager get-secret-value \
--secret-id mcp-gateway/api-key \
--query SecretString --output text)

Performance

Resource Sizing

Small (< 100 req/min):

resources:
requests:
memory: "64Mi"
cpu: "100m"
limits:
memory: "128Mi"
cpu: "250m"

Medium (100-1000 req/min):

resources:
requests:
memory: "128Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "1000m"

Large (> 1000 req/min):

resources:
requests:
memory: "256Mi"
cpu: "500m"
limits:
memory: "1Gi"
cpu: "2000m"

Connection Tuning

# config.yaml
max_connections_per_server: 50
request_timeout_seconds: 60
idle_timeout_seconds: 600

Horizontal Scaling

Deploy multiple gateway instances behind a load balancer:

# kubernetes deployment
spec:
replicas: 3

Note: Each gateway maintains its own server connections. Consider using remote-sse runtime for stateless scaling.

Reliability

Health Checks

Configure health checks for your orchestrator:

# Kubernetes
livenessProbe:
httpGet:
path: /health
port: 4444
initialDelaySeconds: 10
periodSeconds: 30
failureThreshold: 3

readinessProbe:
httpGet:
path: /health
port: 4444
initialDelaySeconds: 5
periodSeconds: 10

Graceful Shutdown

The gateway handles SIGTERM gracefully:

  1. Stops accepting new connections
  2. Completes in-flight requests
  3. Shuts down running servers
  4. Exits

Configure shutdown timeout in orchestrator:

# Kubernetes
spec:
terminationGracePeriodSeconds: 60

Restart Policy

Always restart on failure:

# Docker Compose
restart: unless-stopped

# Kubernetes
spec:
restartPolicy: Always

Monitoring

Metrics Endpoint

The /stats endpoint provides metrics:

curl http://localhost:4444/stats | jq

Prometheus Integration

Scrape the stats endpoint:

# prometheus.yml
scrape_configs:
- job_name: 'mcp-gateway'
static_configs:
- targets: ['mcp-gateway:4444']
metrics_path: /stats

Alerting Rules

# prometheus rules
groups:
- name: mcp-gateway
rules:
- alert: GatewayDown
expr: up{job="mcp-gateway"} == 0
for: 1m
annotations:
summary: "MCP Gateway is down"

- alert: HighErrorRate
expr: rate(mcp_errors_total[5m]) > 0.1
for: 5m
annotations:
summary: "High error rate on MCP Gateway"

Logging

Set appropriate log level:

# config.yaml
log_level: "warn" # Production: warn or info

Log aggregation setup:

# Fluentd / Fluent Bit
# Logs are JSON-formatted for easy parsing

Backup & Recovery

Configuration Backup

Store configs in version control:

# Git repository structure
mcp-gateway/
├── config.yaml
├── catalog.yaml
└── environments/
├── production/
│ ├── config.yaml
│ └── catalog.yaml
└── staging/
├── config.yaml
└── catalog.yaml

Disaster Recovery

  1. Configuration: Restore from Git
  2. Secrets: Restore from secret manager
  3. State: Gateway is stateless - just redeploy

Maintenance

Rolling Updates

Update without downtime:

# Kubernetes
kubectl set image deployment/mcp-gateway \
gateway=ghcr.io/agentic/mcp-gateway:v0.2.0

# Docker Compose
docker-compose pull
docker-compose up -d

Catalog Updates

Use hot reload for catalog changes:

# Update catalog file
vim catalog.yaml

# Gateway auto-reloads, or trigger manually:
curl -X POST http://localhost:4444/admin/reload

Version Upgrades

  1. Read the changelog for breaking changes
  2. Test in staging environment
  3. Update configuration if needed
  4. Rolling deploy to production
  5. Verify with smoke tests

Troubleshooting

Common Issues

Gateway won't start:

# Check config syntax
gateway-http --config config.yaml --validate

# Check logs
RUST_LOG=debug gateway-http --config config.yaml

Servers not connecting:

# Check server status
curl http://localhost:4444/servers | jq

# Test specific server
curl -X POST http://localhost:4444/servers/postgres/start

High latency:

# Check stats
curl http://localhost:4444/stats | jq '.servers'

# Increase timeouts or connection pool

Debug Mode

Temporarily enable debug logging:

RUST_LOG=debug gateway-http --config config.yaml

Or update running instance:

# If supported by your deployment
kubectl set env deployment/mcp-gateway RUST_LOG=debug