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. :::

Quiz

Module 5 Quiz: Production MCP Systems

Take Quiz