维护中工作流模板公开推荐

MCP Server 快速部署模板

标准化 MCP Server 部署模板,包含 Docker、Systemd、Kubernetes、Vercel/Cloudflare Workers 多种部署方式,内置健康检查、日志聚合、指标监控、自动 SSL、域名配置。

更新于 2026年8月20日发布于 2026年8月20日AI资源库进阶
下载渠道
暂无
文件信息
资料包
资料数量
持续更新
访问方式
公开查看
MCP Server 快速部署模板 封面
AI 提示词 · 图片 / 视频生成
收藏

工作流信息

工作流类型
deployment-template
访问级别
免费
所需工具
DockerDocker Composekubectl (可选)Vercel CLI / Wrangler (可选)

MCP Server 快速部署模板

部署方式对比

| 方式 | 适用场景 | 优点 | 缺点 | 成本 | |------|----------|------|------|------| | Docker Compose | 单机/小规模、本地开发、内网穿透 | 简单、可移植、包含依赖 | 单点故障、手动扩容 | 低 | | Systemd + Nginx | 传统 VPS、长期运行、需开机自启 | 原生、稳定、资源占用低 | 手动运维、无滚动更新 | 低 | | Kubernetes (K8s) | 生产集群、高可用、弹性伸缩、多租户 | 企业级、自愈、GitOps、服务网格 | 复杂、资源开销大、学习曲线陡 | 中高 | | Vercel/Cloudflare Workers | Serverless、边缘计算、全球分发、零运维 | 极简部署、自动扩缩容、免费额度大 | 冷启动延迟、执行时限、无状态、不适合长连接 SSE | 低(免费额度) |

---

方式一:Docker Compose (推荐起步)

目录结构

mcp-server-deploy/
├── docker-compose.yml
├── Dockerfile
├── .env.example
├── nginx/
│   ├── nginx.conf
│   └── conf.d/
│       └── mcp.conf
├── prometheus/
│   └── prometheus.yml
├── grafana/
│   └── dashboards/
└── scripts/
    ├── backup.sh
    └── restore.sh

Dockerfile

# 多阶段构建:构建阶段 + 运行阶段
FROM python:3.11-slim AS builder

WORKDIR /app
COPY pyproject.toml .
COPY src/ ./src/
RUN pip install --no-cache-dir --user -e .

FROM python:3.11-slim AS runtime

# 安装运行时依赖
RUN apt-get update && apt-get install -y --no-install-recommends \
    curl ca-certificates \
    && rm -rf /var/lib/apt/lists/*

# 非 root 用户
RUN useradd -m -u 1000 mcp
WORKDIR /home/mcp/app

# 复制构建产物
COPY --from=builder /root/.local /home/mcp/.local
ENV PATH=/home/mcp/.local/bin:$PATH

# 复制应用代码
COPY --chown=mcp:mcp src/ ./src/
COPY --chown=mcp:mcp pyproject.toml .

USER mcp

# 健康检查
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
    CMD curl -f http://localhost:8000/health || exit 1

# 环境变量默认值
ENV TRANSPORT=sse
ENV HOST=0.0.0.0
ENV PORT=8000
ENV LOG_LEVEL=INFO
ENV MCP_SERVER_NAME=my-mcp-server
ENV MCP_SERVER_VERSION=1.0.0

EXPOSE 8000

CMD ["python", "-m", "mcp_server_example.server", "--transport", "sse"]

docker-compose.yml

version: '3.8'

services:
  mcp-server:
    build: .
    container_name: mcp-server
    restart: unless-stopped
    environment:
      - TRANSPORT=sse
      - HOST=0.0.0.0
      - PORT=8000
      - LOG_LEVEL=INFO
      - DATABASE_URL=postgresql://mcp:changeme@postgres:5432/mcp
      - REDIS_URL=redis://redis:6379/0
      - API_KEY=${API_KEY}
      - ENABLED_TOOLS=filesystem,web_search,database
    volumes:
      - ./data:/home/mcp/app/data
      - ./logs:/home/mcp/app/logs
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy
    networks:
      - mcp-network
    deploy:
      resources:
        limits:
          cpus: '2'
          memory: 2G
        reservations:
          cpus: '0.5'
          memory: 512M

  postgres:
    image: postgres:15-alpine
    container_name: mcp-postgres
    restart: unless-stopped
    environment:
      - POSTGRES_DB=mcp
      - POSTGRES_USER=mcp
      - POSTGRES_PASSWORD=changeme
    volumes:
      - postgres_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U mcp -d mcp"]
      interval: 10s
      timeout: 5s
      retries: 5
    networks:
      - mcp-network

  redis:
    image: redis:7-alpine
    container_name: mcp-redis
    restart: unless-stopped
    command: redis-server --appendonly yes --maxmemory 256mb --maxmemory-policy allkeys-lru
    volumes:
      - redis_data:/data
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 5s
      retries: 5
    networks:
      - mcp-network

  nginx:
    image: nginx:alpine
    container_name: mcp-nginx
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
      - ./nginx/conf.d:/etc/nginx/conf.d:ro
      - ./certbot/conf:/etc/letsencrypt:ro
      - ./certbot/www:/var/www/certbot:ro
    depends_on:
      - mcp-server
    networks:
      - mcp-network

  certbot:
    image: certbot/certbot
    container_name: mcp-certbot
    volumes:
      - ./certbot/conf:/etc/letsencrypt
      - ./certbot/www:/var/www/certbot
    entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait $${!}; done'"

  prometheus:
    image: prom/prometheus:latest
    container_name: mcp-prometheus
    restart: unless-stopped
    ports:
      - "9090:9090"
    volumes:
      - ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro
      - prometheus_data:/prometheus
    command:
      - '--config.file=/etc/prometheus/prometheus.yml'
      - '--storage.tsdb.path=/prometheus'
      - '--web.console.libraries=/usr/share/prometheus/console_libraries'
      - '--web.console.templates=/usr/share/prometheus/consoles'
    networks:
      - mcp-network

  grafana:
    image: grafana/grafana:latest
    container_name: mcp-grafana
    restart: unless-stopped
    ports:
      - "3000:3000"
    environment:
      - GF_SECURITY_ADMIN_USER=admin
      - GF_SECURITY_ADMIN_PASSWORD=changeme
      - GF_INSTALL_PLUGINS=grafana-piechart-panel
    volumes:
      - ./grafana/dashboards:/etc/grafana/provisioning/dashboards:ro
      - grafana_data:/var/lib/grafana
    networks:
      - mcp-network

volumes:
  postgres_data:
  redis_data:
  prometheus_data:
  grafana_data:

networks:
  mcp-network:
    driver: bridge

Nginx 配置 (nginx/conf.d/mcp.conf)

upstream mcp_backend {
    server mcp-server:8000;
    keepalive 32;
}

server {
    listen 80;
    server_name mcp.example.com;
    
    # ACME 挑战
    location /.well-known/acme-challenge/ {
        root /var/www/certbot;
    }
    
    # 强制 HTTPS
    location / {
        return 301 https://$server_name$request_uri;
    }
}

server {
    listen 443 ssl http2;
    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;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;
    
    # 安全头
    add_header X-Frame-Options DENY;
    add_header X-Content-Type-Options nosniff;
    add_header X-XSS-Protection "1; mode=block";
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
    
    # SSE 端点
    location /sse {
        proxy_pass http://mcp_backend;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "keep-alive";
        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;
        
        # SSE 必需配置
        proxy_cache off;
        proxy_buffering off;
        proxy_read_timeout 3600s;
        proxy_send_timeout 3600s;
    }
    
    # 消息端点
    location /messages/ {
        proxy_pass http://mcp_backend;
        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;
        proxy_read_timeout 60s;
        proxy_send_timeout 60s;
    }
    
    # 健康检查
    location /health {
        proxy_pass http://mcp_backend;
        access_log off;
    }
    
    # 指标端点 (内网访问)
    location /metrics {
        allow 10.0.0.0/8;
        allow 172.16.0.0/12;
        allow 192.168.0.0/16;
        deny all;
        proxy_pass http://mcp_backend;
    }
}

启动命令

# 1. 配置环境变量
cp .env.example .env
# 编辑 .env 填入 API_KEY、域名等

# 2. 申请 SSL 证书 (首次)
docker compose run --rm certbot certonly --webroot -w /var/www/certbot -d mcp.example.com --email admin@example.com --agree-tos --no-eff-email

# 3. 启动全栈
docker compose up -d

# 4. 查看日志
docker compose logs -f mcp-server

# 5. 验证
curl https://mcp.example.com/health
curl https://mcp.example.com/sse

---

方式二:Systemd + Nginx (传统 VPS)

系统服务 (/etc/systemd/system/mcp-server.service)

[Unit]
Description=MCP Server
After=network.target postgresql.service redis.service
Wants=postgresql.service redis.service

[Service]
Type=exec
User=mcp
Group=mcp
WorkingDirectory=/opt/mcp-server
EnvironmentFile=/opt/mcp-server/.env
ExecStart=/opt/mcp-server/.venv/bin/python -m mcp_server_example.server --transport sse
Restart=on-failure
RestartSec=5
StandardOutput=journal
StandardError=journal
SyslogIdentifier=mcp-server

# 资源限制
LimitNOFILE=65536
LimitNPROC=4096
MemoryLimit=2G
CPUQuota=200%

# 安全加固
NoNewPrivileges=yes
PrivateTmp=yes
ProtectSystem=strict
ProtectHome=yes
ReadWritePaths=/opt/mcp-server/data /opt/mcp-server/logs

[Install]
WantedBy=multi-user.target

部署脚本 (scripts/deploy_vps.sh)

#!/bin/bash
set -euo pipefail

APP_DIR="/opt/mcp-server"
REPO_URL="https://github.com/your-org/mcp-server-example.git"
BRANCH="main"

# 1. 创建用户
id -u mcp &>/dev/null || useradd -r -s /bin/false -d $APP_DIR mcp

# 2. 克隆/更新代码
if [ -d "$APP_DIR/.git" ]; then
    cd $APP_DIR && git pull origin $BRANCH
else
    git clone -b $BRANCH $REPO_URL $APP_DIR
fi

# 3. Python 环境
cd $APP_DIR
python3 -m venv .venv
source .venv/bin/activate
pip install --upgrade pip
pip install -e .

# 4. 配置文件
if [ ! -f .env ]; then
    cp .env.example .env
    echo "请编辑 $APP_DIR/.env 配置环境变量"
    exit 1
fi

# 5. 数据库迁移
alembic upgrade head

# 6. 系统服务
cp deploy/mcp-server.service /etc/systemd/system/
systemctl daemon-reload
systemctl enable mcp-server
systemctl restart mcp-server

# 7. Nginx 配置
cp deploy/nginx/mcp.conf /etc/nginx/conf.d/
nginx -t && systemctl reload nginx

# 8. SSL 证书 (Certbot)
certbot --nginx -d mcp.example.com --non-interactive --agree-tos -m admin@example.com

echo "部署完成!访问 https://mcp.example.com/health 验证"

---

方式三:Kubernetes (生产级)

命名空间与配置

# k8s/namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: mcp-system
  labels:
    name: mcp-system
---
# k8s/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: mcp-config
  namespace: mcp-system
data:
  TRANSPORT: "sse"
  HOST: "0.0.0.0"
  PORT: "8000"
  LOG_LEVEL: "INFO"
  ENABLED_TOOLS: "filesystem,web_search,database"
---
# k8s/secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: mcp-secrets
  namespace: mcp-system
type: Opaque
stringData:
  API_KEY: "your-api-key"
  DATABASE_URL: "postgresql://mcp:password@postgres:5432/mcp"
  REDIS_URL: "redis://redis:6379/0"

Deployment

# k8s/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mcp-server
  namespace: mcp-system
  labels:
    app: mcp-server
spec:
  replicas: 3
  selector:
    matchLabels:
      app: mcp-server
  template:
    metadata:
      labels:
        app: mcp-server
      annotations:
        prometheus.io/scrape: "true"
        prometheus.io/port: "8000"
        prometheus.io/path: "/metrics"
    spec:
      serviceAccountName: mcp-server
      securityContext:
        runAsUser: 1000
        runAsGroup: 1000
        fsGroup: 1000
      containers:
      - name: mcp-server
        image: your-registry/mcp-server:latest
        imagePullPolicy: Always
        ports:
        - containerPort: 8000
          name: http
        envFrom:
        - configMapRef:
            name: mcp-config
        - secretRef:
            name: mcp-secrets
        resources:
          requests:
            cpu: "500m"
            memory: "512Mi"
          limits:
            cpu: "2000m"
            memory: "2Gi"
        livenessProbe:
          httpGet:
            path: /health
            port: 8000
          initialDelaySeconds: 10
          periodSeconds: 30
          timeoutSeconds: 10
        readinessProbe:
          httpGet:
            path: /health
            port: 8000
          initialDelaySeconds: 5
          periodSeconds: 10
          timeoutSeconds: 5
        volumeMounts:
        - name: data
          mountPath: /home/mcp/app/data
        - name: logs
          mountPath: /home/mcp/app/logs
      volumes:
      - name: data
        persistentVolumeClaim:
          claimName: mcp-data-pvc
      - name: logs
        emptyDir: {}
---
# k8s/service.yaml
apiVersion: v1
kind: Service
metadata:
  name: mcp-server
  namespace: mcp-system
spec:
  selector:
    app: mcp-server
  ports:
  - port: 8000
    targetPort: 8000
    name: http
  type: ClusterIP
---
# k8s/ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: mcp-server
  namespace: mcp-system
  annotations:
    cert-manager.io/cluster-issuer: "letsencrypt-prod"
    nginx.ingress.kubernetes.io/proxy-read-timeout: "3600"
    nginx.ingress.kubernetes.io/proxy-send-timeout: "3600"
    nginx.ingress.kubernetes.io/proxy-buffering: "off"
    nginx.ingress.kubernetes.io/proxy-cache: "off"
spec:
  ingressClassName: nginx
  tls:
  - hosts:
    - mcp.example.com
    secretName: mcp-tls
  rules:
  - host: mcp.example.com
    http:
      paths:
      - path: /sse
        pathType: Prefix
        backend:
          service:
            name: mcp-server
            port:
              number: 8000
      - path: /messages
        pathType: Prefix
        backend:
          service:
            name: mcp-server
            port:
              number: 8000
      - path: /health
        pathType: Prefix
        backend:
          service:
            name: mcp-server
            port:
              number: 8000

HPA 自动扩缩容

# k8s/hpa.yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: mcp-server
  namespace: mcp-system
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: mcp-server
  minReplicas: 2
  maxReplicas: 20
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70
  - type: Resource
    resource:
      name: memory
      target:
        type: Utilization
        averageUtilization: 80
  behavior:
    scaleDown:
      stabilizationWindowSeconds: 300
      policies:
      - type: Percent
        value: 10
        periodSeconds: 60
    scaleUp:
      stabilizationWindowSeconds: 0
      policies:
      - type: Percent
        value: 100
        periodSeconds: 15
      - type: Pods
        value: 4
        periodSeconds: 15
      selectPolicy: Max

---

方式四:Vercel (Serverless SSE)

vercel.json

{
  "buildCommand": "pip install -r requirements.txt",
  "devCommand": "python -m mcp_server_example.server --transport sse",
  "installCommand": "pip install -r requirements.txt",
  "framework": null,
  "regions": ["hkg1", "sin1", "sfo1"],
  "functions": {
    "api/index.py": {
      "maxDuration": 300,
      "memory": 1024
    }
  },
  "rewrites": [
    {
      "source": "/sse",
      "destination": "/api/index.py"
    },
    {
      "source": "/messages/:path*",
      "destination": "/api/index.py"
    },
    {
      "source": "/health",
      "destination": "/api/health.py"
    }
  ],
  "env": {
    "TRANSPORT": "sse",
    "PYTHONPATH": "."
  }
}

api/index.py (Vercel Python Serverless 适配)

# Vercel Serverless 不支持长连接 SSE,需改用 HTTP 轮询或 WebSocket
# 这里演示 HTTP 轮询模式 (兼容 MCP Streamable HTTP 传输提案)

from http.server import BaseHTTPRequestHandler
import json
import asyncio
from mcp_server_example.server import MCPServer

# 全局单例 (Vercel 会复用实例)
_server = None

def get_server():
    global _server
    if _server is None:
        _server = MCPServer()
    return _server

class Handler(BaseHTTPRequestHandler):
    def do_GET(self):
        if self.path == "/health":
            self.send_response(200)
            self.send_header("Content-Type", "application/json")
            self.end_headers()
            self.wfile.write(b'{"status":"ok"}')
        elif self.path.startswith("/sse"):
            # SSE 在 Serverless 受限,建议用 Streamable HTTP
            self.send_response(501)
            self.end_headers()
            self.wfile.write(b"SSE not supported on Vercel. Use Streamable HTTP transport.")
        else:
            self.send_response(404)
            self.end_headers()
    
    def do_POST(self):
        if self.path.startswith("/messages"):
            content_length = int(self.headers.get('Content-Length', 0))
            body = self.rfile.read(content_length).decode()
            request = json.loads(body)
            
            # 处理 JSON-RPC 请求
            server = get_server()
            # 这里需要实现异步处理,Vercel 支持 async handler
            # 简化演示
            self.send_response(200)
            self.send_header("Content-Type", "application/json")
            self.end_headers()
            self.wfile.write(b'{"jsonrpc":"2.0","id":1,"result":{}}')
        else:
            self.send_response(404)
            self.end_headers()
注意: Vercel 原生不支持长连接 SSE。MCP 社区正在推进 Streamable HTTP 传输层 (基于 HTTP POST 轮询 + 长轮询),兼容 Serverless。建议:
- 简单工具类 Server → Vercel/Cloudflare Workers (HTTP 模式)
- 需要实时流式/长连接的 Server → Docker/K8s/VPS (SSE 模式)

---

方式五:Cloudflare Workers (边缘 Serverless)

wrangler.toml

name = "mcp-server"
main = "src/worker.ts"
compatibility_date = "2024-01-01"
compatibility_flags = ["nodejs_compat"]

[env.production]
vars = { ENVIRONMENT = "production" }
kv_namespaces = [{ binding = "MCP_KV", id = "your-kv-namespace-id" }]
d1_databases = [{ binding = "MCP_DB", database_name = "mcp-db", database_id = "your-db-id" }]

[observability]
enabled = true
head_sampling_rate = 0.1

src/worker.ts (TypeScript + Hono + MCP Streamable HTTP)

import { Hono } from 'hono'
import { handleMCPRequest } from './mcp-handler'

const app = new Hono()

// 健康检查
app.get('/health', (c) => c.json({ status: 'ok' }))

// MCP Streamable HTTP 端点 (POST 请求处理 JSON-RPC)
app.post('/mcp', async (c) => {
  const body = await c.req.json()
  const result = await handleMCPRequest(body, c.env)
  return c.json(result)
)

// 批量请求支持
app.post('/mcp/batch', async (c) => {
  const requests = await c.req.json()
  const results = await Promise.all(
    requests.map(req => handleMCPRequest(req, c.env))
  )
  return c.json(results)
})

// 可选:SSE 兼容端点 (通过 Durable Objects 实现长连接)
app.get('/sse', async (c) => {
  // 需要 Durable Objects 支持 WebSocket
  return c.text('SSE requires Durable Objects. Use /mcp endpoint.', 501)
})

export default app

---

监控与告警

Prometheus 规则 (prometheus/alerts.yml)

groups:
- name: mcp-server
  rules:
  - alert: MCPServerDown
    expr: up{job="mcp-server"} == 0
    for: 1m
    labels:
      severity: critical
    annotations:
      summary: "MCP Server 实例宕机"
      description: "{{ $labels.instance }} 已下线超过 1 分钟"
  
  - alert: MCPServerHighLatency
    expr: histogram_quantile(0.95, rate(mcp_tool_call_duration_seconds_bucket[5m])) > 10
    for: 5m
    labels:
      severity: warning
    annotations:
      summary: "MCP Server 工具调用 P99 延迟过高"
      description: "P99 延迟 {{ $value }}s,超过 10s 阈值"
  
  - alert: MCPServerHighErrorRate
    expr: rate(mcp_tool_call_errors_total[5m]) / rate(mcp_tool_call_total[5m]) > 0.05
    for: 2m
    labels:
      severity: critical
    annotations:
      summary: "MCP Server 错误率过高"
      description: "错误率 {{ $value | humanizePercentage }},超过 5%"
  
  - alert: MCPServerHighMemory
    expr: (container_memory_usage_bytes{pod=~"mcp-server-.*"} / container_spec_memory_limit_bytes{pod=~"mcp-server-.*"}) > 0.9
    for: 5m
    labels:
      severity: warning
    annotations:
      summary: "MCP Server 内存使用率过高"
      description: "内存使用率 {{ $value | humanizePercentage }}"

Grafana 仪表板关键指标

  • 请求吞吐: rate(mcp_tool_call_total[5m]) (按工具分组)
  • 延迟分位数: histogram_quantile(0.5/0.95/0.99, rate(mcp_tool_call_duration_seconds_bucket[5m]))
  • 错误率: rate(mcp_tool_call_errors_total[5m]) / rate(mcp_tool_call_total[5m])
  • 活跃连接: mcp_active_sse_connections (SSE 模式)
  • 资源使用: CPU、内存、磁盘、网络 I/O
  • 业务指标: 各工具调用次数、资源读取次数、提示词渲染次数

---

备份与灾难恢复

备份脚本 (scripts/backup.sh)

#!/bin/bash
set -euo pipefail

BACKUP_DIR="/backups/mcp"
DATE=$(date +%Y%m%d_%H%M%S)
RETENTION_DAYS=30

mkdir -p $BACKUP_DIR

# 1. PostgreSQL 备份
docker exec mcp-postgres pg_dump -U mcp mcp | gzip > $BACKUP_DIR/postgres_$DATE.sql.gz

# 2. Redis 备份
docker exec mcp-redis redis-cli --rdb - | gzip > $BACKUP_DIR/redis_$DATE.rdb.gz

# 3. 应用数据备份
tar -czf $BACKUP_DIR/app_data_$DATE.tar.gz -C /opt/mcp-server data/

# 4. 配置备份
tar -czf $BACKUP_DIR/config_$DATE.tar.gz -C /opt/mcp-server .env docker-compose.yml nginx/

# 5. 清理旧备份
find $BACKUP_DIR -type f -mtime +$RETENTION_DAYS -delete

# 6. 上传到远程存储 (可选)
# rclone copy $BACKUP_DIR remote:bucket/mcp-backups/

echo "备份完成: $BACKUP_DIR/*_$DATE.*"

恢复脚本 (scripts/restore.sh)

#!/bin/bash
set -euo pipefail

BACKUP_FILE=$1
if [ -z "$BACKUP_FILE" ]; then
    echo "用法: $0 <backup_date_YYYYMMDD_HHMMSS>"
    exit 1
fi

BACKUP_DIR="/backups/mcp"

# 停止服务
docker compose stop mcp-server

# 恢复 PostgreSQL
zcat $BACKUP_DIR/postgres_$BACKUP_FILE.sql.gz | docker exec -i mcp-postgres psql -U mcp mcp

# 恢复 Redis
zcat $BACKUP_DIR/redis_$BACKUP_FILE.rdb.gz | docker exec -i mcp-redis redis-cli --pipe

# 恢复应用数据
tar -xzf $BACKUP_DIR/app_data_$BACKUP_FILE.tar.gz -C /opt/mcp-server/

# 启动服务
docker compose start mcp-server

echo "恢复完成: $BACKUP_FILE"

---

安全加固清单

  • [ ] 网络隔离: 数据库/Redis 仅内网访问,不暴露公网端口
  • [ ] 最小权限: 数据库用户仅有必要权限,API Key 定期轮换
  • [ ] 传输加密: 全链路 TLS 1.3,HSTS、CSP 安全头
  • [ ] 认证授权: SSE 端点集成 OAuth 2.1 / API Key 校验
  • [ ] 输入验证: 所有工具参数 Pydantic 严格校验,防注入
  • [ ] 审计日志: 结构化 JSON 日志,包含用户、工具、参数、结果、耗时
  • [ ] 限流防刷: 令牌桶 + IP 维度限流 + 异常行为检测
  • [ ] 依赖扫描: 定期 pip-audit / snyk test / trivy image
  • [ ] 镜像签名: Cosign 签名验证,仅运行受信镜像
  • [ ] 定期演练: 季度灾难恢复演练,验证 RPO/RTO

---

相关资源

评论建议

欢迎反馈资料质量、链接状态或希望补充的内容,管理员会持续维护。

常见问题

下载链接失效怎么办?
请优先切换其他网盘渠道,并反馈失效链接。

会员能下载所有资料吗?
页面标注为会员专享的资料支持会员下载,具体以当前页面显示为准。

相关资源