Cloud Platform Deployment
Time to read: 18 minutes
Deploy your MCP server to major cloud platforms: AWS, Google Cloud, Azure, and others.
What You'll Learn
- AWS deployment
 - Google Cloud deployment
 - Azure deployment
 - Platform comparison
 - Best practices
 
AWS Deployment
AWS ECS (Elastic Container Service)
1. Create ECR Repository
aws ecr create-repository --repository-name my-mcp-server
2. Build & Push Image
# Login to ECR
aws ecr get-login-password --region us-east-1 | \
  docker login --username AWS --password-stdin \
  YOUR_ACCOUNT.dkr.ecr.us-east-1.amazonaws.com
# Build and push
docker build -t my-mcp-server .
docker tag my-mcp-server:latest \
  YOUR_ACCOUNT.dkr.ecr.us-east-1.amazonaws.com/my-mcp-server:latest
docker push YOUR_ACCOUNT.dkr.ecr.us-east-1.amazonaws.com/my-mcp-server:latest
3. Create ECS Task Definition
{
  "family": "mcp-server",
  "networkMode": "awsvpc",
  "containerDefinitions": [
    {
      "name": "mcp-server",
      "image": "YOUR_ACCOUNT.dkr.ecr.us-east-1.amazonaws.com/my-mcp-server:latest",
      "cpu": 256,
      "memory": 512,
      "essential": true,
      "portMappings": [
        {
          "containerPort": 3000,
          "protocol": "tcp"
        }
      ],
      "environment": [
        {
          "name": "NODE_ENV",
          "value": "production"
        }
      ],
      "logConfiguration": {
        "logDriver": "awslogs",
        "options": {
          "awslogs-group": "/ecs/mcp-server",
          "awslogs-region": "us-east-1",
          "awslogs-stream-prefix": "ecs"
        }
      }
    }
  ],
  "requiresCompatibilities": ["FARGATE"],
  "cpu": "256",
  "memory": "512"
}
AWS Lambda (Serverless)
For request-response workloads:
// lambda/index.js
const { Server } = require('./dist');
exports.handler = async (event) => {
  const server = new Server();
  const result = await server.handleRequest(event);
  return {
    statusCode: 200,
    body: JSON.stringify(result),
  };
};
Google Cloud Platform
Cloud Run
1. Build & Push
# Enable APIs
gcloud services enable run.googleapis.com
gcloud services enable cloudbuild.googleapis.com
# Build with Cloud Build
gcloud builds submit --tag gcr.io/PROJECT_ID/mcp-server
2. Deploy
gcloud run deploy mcp-server \
  --image gcr.io/PROJECT_ID/mcp-server \
  --platform managed \
  --region us-central1 \
  --allow-unauthenticated \
  --memory 512Mi \
  --cpu 1 \
  --port 3000
GKE (Kubernetes)
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mcp-server
spec:
  replicas: 3
  selector:
    matchLabels:
      app: mcp-server
  template:
    metadata:
      labels:
        app: mcp-server
    spec:
      containers:
      - name: mcp-server
        image: gcr.io/PROJECT_ID/mcp-server
        ports:
        - containerPort: 3000
        env:
        - name: NODE_ENV
          value: "production"
        resources:
          requests:
            memory: "512Mi"
            cpu: "250m"
          limits:
            memory: "1Gi"
            cpu: "500m"
---
apiVersion: v1
kind: Service
metadata:
  name: mcp-server
spec:
  type: LoadBalancer
  ports:
  - port: 80
    targetPort: 3000
  selector:
    app: mcp-server
Microsoft Azure
Azure Container Instances
# Create resource group
az group create --name mcp-server-rg --location eastus
# Create container
az container create \
  --resource-group mcp-server-rg \
  --name mcp-server \
  --image YOUR_REGISTRY.azurecr.io/mcp-server:latest \
  --cpu 1 --memory 1 \
  --ports 3000 \
  --environment-variables NODE_ENV=production \
  --restart-policy Always
Azure Kubernetes Service (AKS)
# Create AKS cluster
az aks create \
  --resource-group mcp-server-rg \
  --name mcp-cluster \
  --node-count 3 \
  --enable-addons monitoring \
  --generate-ssh-keys
# Get credentials
az aks get-credentials \
  --resource-group mcp-server-rg \
  --name mcp-cluster
# Deploy
kubectl apply -f deployment.yaml
DigitalOcean
App Platform
# .do/app.yaml
name: mcp-server
services:
- name: server
  github:
    repo: your-username/mcp-server
    branch: main
    deploy_on_push: true
  build_command: npm run build
  run_command: node dist/index.js
  envs:
  - key: NODE_ENV
    value: production
  http_port: 3000
  instance_count: 1
  instance_size_slug: basic-xxs
Heroku
# Create app
heroku create my-mcp-server
# Deploy
git push heroku main
# Scale
heroku ps:scale web=1
Platform Comparison
| Platform | Best For | Cost | Scaling | 
|---|---|---|---|
| AWS ECS | Enterprise | $$$ | Excellent | 
| AWS Lambda | Event-driven | $ | Automatic | 
| Google Cloud Run | Serverless containers | $$ | Automatic | 
| GKE/AKS | Large scale | $$$ | Manual | 
| DigitalOcean | Simplicity | $$ | Manual | 
| Heroku | Quick deploy | $$ | Easy | 
Environment Configuration
Secrets Management
AWS Secrets Manager:
const AWS = require('aws-sdk');
const secretsManager = new AWS.SecretsManager();
async function getSecret(secretName) {
  const data = await secretsManager
    .getSecretValue({ SecretId: secretName })
    .promise();
  return JSON.parse(data.SecretString);
}
Google Cloud Secret Manager:
const {SecretManagerServiceClient} = require('@google-cloud/secret-manager');
const client = new SecretManagerServiceClient();
async function getSecret(name) {
  const [version] = await client.accessSecretVersion({
    name: `projects/PROJECT_ID/secrets/${name}/versions/latest`,
  });
  return version.payload.data.toString();
}
Monitoring & Logging
CloudWatch (AWS)
const winston = require('winston');
const CloudWatchTransport = require('winston-cloudwatch');
logger.add(new CloudWatchTransport({
  logGroupName: '/aws/ecs/mcp-server',
  logStreamName: 'production',
  awsRegion: 'us-east-1',
}));
Stackdriver (GCP)
const {Logging} = require('@google-cloud/logging');
const logging = new Logging();
const log = logging.log('mcp-server');
function logEntry(message, severity = 'INFO') {
  const entry = log.entry({
    severity,
    resource: {type: 'cloud_run_revision'},
  }, message);
  log.write(entry);
}
Best Practices
- Use managed services - Less operational overhead
 - Implement health checks - Monitor service health
 - Auto-scaling - Handle traffic spikes
 - Multi-region - High availability
 - Secrets management - Never hardcode credentials
 - Monitoring & alerts - Know when things break
 - CI/CD pipelines - Automate deployments
 - Cost optimization - Right-size resources
 
CI/CD Examples
GitHub Actions (AWS)
name: Deploy to AWS ECS
on:
  push:
    branches: [main]
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      
      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v1
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: us-east-1
      
      - name: Build and push
        run: |
          docker build -t mcp-server .
          docker tag mcp-server:latest $ECR_REGISTRY/mcp-server:latest
          docker push $ECR_REGISTRY/mcp-server:latest
      
      - name: Update ECS service
        run: |
          aws ecs update-service \
            --cluster mcp-cluster \
            --service mcp-server \
            --force-new-deployment
Next Steps
Master deployment:
- Docker Guide - Container basics
 - Production Checklist - Pre-flight checks
 - Logging - Production logging