# =============================================================================
# Operation Ollama-First v5.0 / Phase 10 — MCP 自建 Stack
# =============================================================================
# 部署位置：188 主機，與既有 momo-pro 容器共存
# 啟動方式：docker compose -f docker-compose.mcp.yml up -d
# 啟用前置：
#   1. .env 加 TAVILY_API_KEY（Tavily 1000 free credits/月）
#   2. .env 加 EXA_API_KEY（Exa 備援）
#   3. 確認 188 防火牆 allow 172.x docker bridge 對外（firecrawl 抓網頁）
#
# 4 個 MCP server 對應 ADR-031 (Phase 10) 規格：
#   - postgres-mcp:    Claude 直連 momo_pro DB（read-only RBAC）
#   - mcp-omnisearch:  取代 Gemini Grounding，Tavily 主 + Exa 備
#   - firecrawl-self:  自建爬蟲（含 Owen v5.0 護欄 #2 mem_limit:2g + chrome-reaper）
#   - filesystem-mcp:  跨主機檔案操作
#
# 護欄一覽（ADR-033）：
#   #2 Firecrawl mem_limit:2g + chrome-reaper sidecar + 1.8GB 告警
#
# 部署後驗收（給統帥）：
#   curl http://localhost:3001/health    # postgres-mcp
#   curl http://localhost:3002/health    # firecrawl
#   curl http://localhost:3003/health    # omnisearch
#   curl http://localhost:3004/health    # filesystem
# =============================================================================

services:

  # ─────────────────────────────────────────────────────────────────────────
  # postgres-mcp: Claude 直連 momo_pro DB（read-only）
  # ─────────────────────────────────────────────────────────────────────────
  postgres-mcp:
    image: mcp/postgres:latest
    container_name: momo-mcp-postgres
    restart: unless-stopped
    init: true
    ports:
      - "127.0.0.1:3001:3000"  # 僅 localhost 暴露（避免外網直連 DB）
    environment:
      - POSTGRES_HOST=momo-db
      - POSTGRES_PORT=5432
      - POSTGRES_USER=mcp_readonly  # 須在 momo-db 預先建 read-only role
      - POSTGRES_PASSWORD=${MCP_POSTGRES_PASSWORD}
      - POSTGRES_DB=momo_pro
      # RBAC：限制 SELECT 到熱表
      - ALLOWED_TABLES=ai_insights,ai_calls,mcp_calls,daily_sales_snapshot,competitor_prices,products
    networks:
      - momo-shared
    deploy:
      resources:
        limits:
          memory: 256m
    healthcheck:
      test: ["CMD", "wget", "-qO-", "http://localhost:3000/health"]
      interval: 30s
      timeout: 5s
      retries: 3

  # ─────────────────────────────────────────────────────────────────────────
  # mcp-omnisearch: 統一搜尋（Tavily 主 + Exa 備）
  # ─────────────────────────────────────────────────────────────────────────
  mcp-omnisearch:
    image: ghcr.io/spences10/mcp-omnisearch:latest
    container_name: momo-mcp-omnisearch
    restart: unless-stopped
    init: true
    ports:
      - "127.0.0.1:3003:3000"
    environment:
      # 排除 Brave（2026-02 已取消免費 tier）
      - TAVILY_API_KEY=${TAVILY_API_KEY}      # 1000 free credits/月（主）
      - EXA_API_KEY=${EXA_API_KEY}            # 1000 free credits/月（備援）
      - SEARCH_PROVIDER_ORDER=tavily,exa      # fallback 順序
    deploy:
      resources:
        limits:
          memory: 512m
    healthcheck:
      test: ["CMD", "wget", "-qO-", "http://localhost:3000/health"]
      interval: 30s
      timeout: 5s
      retries: 3

  # ─────────────────────────────────────────────────────────────────────────
  # firecrawl-self: 自建爬蟲（含 Owen v5.0 護欄 #2）
  # ─────────────────────────────────────────────────────────────────────────
  firecrawl-self:
    image: firecrawl/firecrawl:latest
    container_name: momo-mcp-firecrawl
    restart: unless-stopped
    init: true
    ports:
      - "127.0.0.1:3002:3002"
    environment:
      - REDIS_URL=redis://firecrawl-redis:6379
      - PLAYWRIGHT_MICROSERVICE_URL=http://firecrawl-playwright:3000
      - PLAYWRIGHT_BROWSER_POOL_MAX=3       # ⭐ 護欄 #2：瀏覽器池上限
      - SCRAPE_TIMEOUT_MS=30000
      - BULL_AUTH_KEY=${FIRECRAWL_AUTH_KEY:-momo-internal-only}
    depends_on:
      - firecrawl-redis
      - firecrawl-playwright
    deploy:
      resources:
        limits:
          memory: 2g                        # ⭐ Owen v5.0 護欄 #2 硬上限
          cpus: '1.5'
    healthcheck:
      test: ["CMD", "wget", "-qO-", "http://localhost:3002/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 60s

  firecrawl-redis:
    image: redis:7-alpine
    container_name: momo-mcp-firecrawl-redis
    restart: unless-stopped
    deploy:
      resources:
        limits:
          memory: 128m

  firecrawl-playwright:
    image: firecrawl/playwright:latest
    container_name: momo-mcp-firecrawl-playwright
    restart: unless-stopped
    deploy:
      resources:
        limits:
          memory: 1.5g
          cpus: '1.0'

  # ─────────────────────────────────────────────────────────────────────────
  # chrome-reaper: 護欄 #2 — 每小時清 Chrome 殘留
  # ─────────────────────────────────────────────────────────────────────────
  chrome-reaper:
    image: alpine:3
    container_name: momo-mcp-chrome-reaper
    restart: unless-stopped
    command: |
      sh -c '
        apk add --no-cache docker-cli;
        while true; do
          echo "[reaper] $(date) cleaning Chrome zombies...";
          docker exec momo-mcp-firecrawl-playwright \
            sh -c "pkill -f \"chrome.*--type=zygote\" 2>/dev/null || true;
                   pkill -f \"chrome.*--type=renderer\" 2>/dev/null || true" \
            2>/dev/null || true;
          sleep 3600;
        done
      '
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro

  # ─────────────────────────────────────────────────────────────────────────
  # filesystem-mcp: 跨主機檔案操作（限本地）
  # ─────────────────────────────────────────────────────────────────────────
  filesystem-mcp:
    image: mcp/filesystem:latest
    container_name: momo-mcp-filesystem
    restart: unless-stopped
    init: true
    ports:
      - "127.0.0.1:3004:3000"
    environment:
      - ALLOWED_PATHS=/data,/logs           # 限制存取範圍
    volumes:
      - ./data:/data:ro                     # ⚠️ ro 唯讀，避免 LLM 改檔
      - ./logs:/logs:ro
    deploy:
      resources:
        limits:
          memory: 128m

# ─────────────────────────────────────────────────────────────────────────────
# 與既有 momo-pro 共用 network（讓 postgres-mcp 連 momo-db）
# ─────────────────────────────────────────────────────────────────────────────
networks:
  momo-shared:
    external: true
    name: momo-pro_default      # 既有 docker-compose.yml 的 default network
