Production MCP Systems
Deployment Strategies
5 min read
Taking your MCP server to production requires careful planning. Let's explore deployment options.
Deployment Options
| Option | Pros | Cons |
|---|---|---|
| Docker | Portable, isolated | Container overhead |
| Serverless | Auto-scaling, pay-per-use | Cold starts, limits |
| Kubernetes | Highly scalable | Complex setup |
| VM/VPS | Full control | Manual scaling |
Docker Deployment
Create a production-ready Dockerfile:
FROM python:3.11-slim
WORKDIR /app
# Install dependencies
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# Copy application
COPY . .
# Run with production settings
ENV PYTHONUNBUFFERED=1
EXPOSE 8000
CMD ["uvicorn", "server:app", "--host", "0.0.0.0", "--port", "8000"]
Build and run:
docker build -t my-mcp-server .
docker run -p 8000:8000 -e API_KEY=secret my-mcp-server
Docker Compose for Development
version: "3.8"
services:
mcp-server:
build: .
ports:
- "8000:8000"
environment:
- DATABASE_URL=postgresql://db:5432/mcp
- API_KEY=${API_KEY}
depends_on:
- db
db:
image: postgres:15
environment:
- POSTGRES_DB=mcp
- POSTGRES_PASSWORD=secret
volumes:
- pgdata:/var/lib/postgresql/data
volumes:
pgdata:
Cloud Deployment
AWS Lambda (Serverless)
from mangum import Mangum
from server import app
# Wrap Starlette app for Lambda
handler = Mangum(app)
Railway/Fly.io
These platforms auto-detect Python apps:
# fly.toml
app = "my-mcp-server"
[http_service]
internal_port = 8000
force_https = true
[env]
PORT = "8000"
Environment Configuration
Never hardcode secrets:
import os
class Config:
SECRET_KEY = os.environ["SECRET_KEY"]
DATABASE_URL = os.environ.get("DATABASE_URL", "sqlite:///local.db")
DEBUG = os.environ.get("DEBUG", "false").lower() == "true"
LOG_LEVEL = os.environ.get("LOG_LEVEL", "INFO")
Next, we'll add monitoring and observability. :::