Claude Platform Docs
MessagesMCP 通道

使用 Docker Compose 部署 MCP 通道

使用 Docker Compose 在虛擬機器上安裝 MCP 通道堆疊。

本指南將通道堆疊(tunnel stack)以強化過的容器形式部署在單一主機上。相同的設定可以複製到多台主機以提高可用性。

開始之前

您需要:

  • 一個通道(tunnel)。 使用程式化存取時,若您未提供通道 ID,設定元件(setup component)會為您建立一個;若要改為附加到現有通道,請在 Console 中建立它並記下通道 ID(tnl_...)。手動佈建一律從 Console 建立的通道開始。
  • 讓主機向 Tunnels API 進行身分驗證的方式。
    • 程式化存取(建議)。 建立通道時開啟 Set up programmatic access(或者,如果您要讓設定元件建立通道,請直接在 Settings > Workload identity 下建立聯合規則),讓設定元件可以透過 Workload Identity Federation(工作負載身分聯合)進行身分驗證。記下聯合規則 ID(fdrl_...)以及您的組織 ID。
    • 手動。 略過程式化存取。您將從 Console 取得通道權杖、自行產生 CA 與伺服器憑證,並在 Console 中註冊 CA
  • 一台已安裝 Docker 與 Docker Compose 的主機。 手動流程還需要 openssl(1.1.1 或更新版本)。
  • 對外網路連線,從主機連至 api.anthropic.com(443 TCP)以及通道邊緣(tunnel edge)(7844 TCP 與 UDP)。請參閱完整的網路需求
  • 一個或多個 MCP 伺服器,正在執行且可從主機透過您將在 routes 下設定的位址連線。如果您還沒有,請使用範例伺服器

選用:使用範例 MCP 伺服器

如果您沒有可供測試的 MCP 伺服器,請使用這個最精簡的版本:

mkdir -p mcp-tunnel
cat > mcp-tunnel/hello_server.py <<'EOF'
from mcp.server.fastmcp import FastMCP

mcp = FastMCP("hello-server", host="0.0.0.0", port=9000)


@mcp.tool()
def hello(name: str = "world") -> str:
    """Say hello to someone."""
    return f"Hello, {name}!"


if __name__ == "__main__":
    mcp.run(transport="streamable-http")
EOF

以下的安裝步驟會 cd 進入 mcp-tunnel/,並註明在何處加入對應的服務與路由。

安裝

本指南提供一種使用 Docker Compose 的參考做法。您有責任自行調整,以符合您組織的安全需求。

此路徑要求主機具備 OIDC 身分提供者(例如雲端虛擬機器中繼資料伺服器或 SPIFFE)。若沒有,請改用不使用程式化存取分頁。

設定元件使用 Workload Identity Federation 來擷取通道權杖、產生 CA 與伺服器憑證,並向 Anthropic 註冊該 CA。

  1. 準備部署目錄

    mkdir -p mcp-tunnel/{config,data}
    cd mcp-tunnel
    sudo chown 65532:65532 data

    容器以非 root 的 UID 65532 執行,且需要對 data/ 的寫入權限。

  2. 撰寫 docker-compose.yaml

    此 compose 檔案以 SHA-256 摘要固定映像檔版本、以非 root 身分搭配唯讀檔案系統執行每個容器、移除所有 Linux capabilities,並停用權限提升。

    cat > docker-compose.yaml <<'EOF'
    services:
      setup:
        image: us-docker.pkg.dev/anthropic-public-registry/images/mcp-proxy@sha256:efb27b299d627e4134815663cb8896641eeaee025d734c0f695582b4df38f013
        entrypoint: ["/setup"]
        command:
          - init
          - --api-url=https://api.anthropic.com
          - --output=dir:/data
          - --token-version=1
        environment:
          - TUNNEL_ID
          - ANTHROPIC_FEDERATION_RULE_ID
          - ANTHROPIC_ORGANIZATION_ID
          - ANTHROPIC_WORKSPACE_ID
          - ANTHROPIC_IDENTITY_TOKEN
        volumes:
          - ./data:/data
        user: "65532:65532"
        read_only: true
        security_opt:
          - no-new-privileges:true
        cap_drop:
          - ALL
        profiles: ["setup"]
    
      cloudflared:
        image: cloudflare/cloudflared@sha256:6b599ca3e974349ead3286d178da61d291961182ec3fe9c505e1dd02c8ac31b0
        command: tunnel --no-autoupdate run --url http://localhost:8080
        environment:
          - TUNNEL_TOKEN
        # 共用 proxy 的 netns,讓 localhost:8080 能連到它。
        network_mode: "service:mcp-proxy"
        restart: unless-stopped
        user: "65532:65532"
        read_only: true
        security_opt:
          - no-new-privileges:true
        cap_drop:
          - ALL
        stop_grace_period: 30s
        logging:
          options:
            max-size: "10m"
            max-file: "3"
    
      mcp-proxy:
        image: us-docker.pkg.dev/anthropic-public-registry/images/mcp-proxy@sha256:efb27b299d627e4134815663cb8896641eeaee025d734c0f695582b4df38f013
        volumes:
          - ./config/mcp-proxy.yaml:/etc/mcp-gateway/config.yaml:ro
          - ./data:/data:ro
        restart: unless-stopped
        user: "65532:65532"
        read_only: true
        security_opt:
          - no-new-privileges:true
        cap_drop:
          - ALL
        stop_grace_period: 30s
        logging:
          options:
            max-size: "10m"
            max-file: "3"
    EOF

    如果您使用範例 MCP 伺服器,請將其附加為一個服務:

    cat >> docker-compose.yaml <<'EOF'
    
      hello-mcp:
        image: python:3.13-slim
        working_dir: /app
        volumes:
          - ./hello_server.py:/app/hello_server.py:ro
        command: sh -c "pip install --quiet mcp && python hello_server.py"
        restart: unless-stopped
    EOF
  3. 佈建通道

    設定識別碼。將 TUNNEL_ID 保持未設定,讓設定元件建立通道;若要附加到 Console 中的現有通道,請設定它:

    # export TUNNEL_ID=tnl_...   # 設定此值以連接至現有的 tunnel
    export ANTHROPIC_FEDERATION_RULE_ID=fdrl_...
    export ANTHROPIC_ORGANIZATION_ID=00000000-0000-0000-0000-000000000000

    如果您的聯合規則範圍限定於組織預設工作區以外的工作區,請同時設定 ANTHROPIC_WORKSPACE_ID=wrkspc_...;否則設定元件會使用預設工作區。自動建立的通道會建立在該工作區中。

    ANTHROPIC_IDENTITY_TOKEN 設定為來自此主機身分提供者的 OIDC JWT。請依照適用於您提供者的 WIF 指南註冊簽發者、設定規則的 subject,並鑄造權杖;規則的 audience 必須與您鑄造時所請求的 audience 相符。

    執行設定元件:

    docker compose run --rm setup

    setup initdata/ 具有冪等性:重新執行時會重複使用已儲存於其中的通道 ID 與 CA,絕不會建立第二個通道。只有在 data/ 為空或 TUNNEL_ID 已變更時,才會產生並註冊新的 CA;在這種情況下,兩張有效憑證的上限會適用,因此若兩個位置都已佔滿,請先在 Console 中撤銷其中一張。

    若發生錯誤,請參閱設定元件身分驗證失敗

    取得您的通道網域並匯出,供後續步驟使用:

    export TUNNEL_DOMAIN=$(sudo cat data/tunnel-domain)
    echo "$TUNNEL_DOMAIN"
  4. 撰寫 proxy 設定

    tunnel_domain必填proxy 會使用它從傳入的主機名稱中去除網域後綴,然後再於 routes 中查詢子網域。routes 是從子網域對應到上游 URL 的扁平映射,而非清單。

    cat > config/mcp-proxy.yaml <<EOF
    listen_addr: ":8080"
    log_level: info
    shutdown_timeout: 30s
    tunnel_domain: ${TUNNEL_DOMAIN}
    tls:
      cert_file: /data/tls.crt
      key_file: /data/tls.key
    routes:
      echo: http://hello-mcp:9000
    EOF

    echo: 路由指向範例 MCP 伺服器;請以您自己的路由取代(或新增)。所有可用欄位請參閱 proxy 設定參考文件。

  5. 啟動部署

    export TUNNEL_TOKEN=$(sudo cat data/tunnel-token)
    docker compose up -d

compose 檔案從主機環境讀取 TUNNEL_TOKEN 且沒有預設值,因此在每個新的 shell 中以及重新開機後都必須重新執行 export。

若要進行多虛擬機器部署,請將 mcp-tunnel/ 目錄複製到每台主機、設定 TUNNEL_TOKEN,然後執行 docker compose up -d。在程式化流程中,TUNNEL_TOKEN$(sudo cat data/tunnel-token);在手動流程中,則是您從 Console 複製的值。相同的通道權杖與憑證可在所有副本上使用。

驗證部署

從 Anthropic 端呼叫上游 MCP 伺服器以進行端對端驗證:請參閱使用通道化的 MCP 伺服器。使用範例 MCP 伺服器時,路由後的 URL 為 https://echo.<your-tunnel-domain>/mcp。若驗證失敗,請參閱疑難排解

升級

請在 mcp-tunnel/ 部署目錄內執行本節中的指令。

輪替通道權杖

使用程式化存取時,請遞增 setup 服務指令中的 --token-version、設定 Workload Identity Federation 識別碼、鑄造新的 OIDC JWT,然後重新執行設定元件:

# 編輯 docker-compose.yaml:將 setup 服務的
# --token-version 引數中的整數遞增(例如從 --token-version=1 改為
# --token-version=2)。若該值未變更,setup 二進位檔
# 會拒絕輪替。

# export TUNNEL_ID=tnl_...   # 僅在安裝時曾設定此值時才需設定
export ANTHROPIC_FEDERATION_RULE_ID=fdrl_...
export ANTHROPIC_ORGANIZATION_ID=00000000-0000-0000-0000-000000000000
# export ANTHROPIC_WORKSPACE_ID=wrkspc_...   # 若您的規則以工作區為範圍
# 依照您環境適用的 WIF 提供者指南重新產生 ANTHROPIC_IDENTITY_TOKEN
# (自安裝以來它應已過期)。
export ANTHROPIC_IDENTITY_TOKEN=...

docker compose run --rm setup

export TUNNEL_TOKEN=$(sudo cat data/tunnel-token)
docker compose up -d cloudflared

--token-version 引數是在 docker-compose.yaml 中編輯,而非在命令列上傳遞,如此新值才能在設定元件未來的執行中持續保留。設定元件透過 Workload Identity Federation 進行身分驗證;沒有需要撤銷的 API 權杖。

不使用程式化存取時,請在 Console 的通道詳細資訊頁面上點擊 Rotate token,然後更新每台主機上的 TUNNEL_TOKEN 環境變數並重新啟動 cloudflared(docker compose up -d cloudflared)。

憑證更新

您有責任監控到期時間,並在伺服器憑證到期前進行更新。

使用程式化存取時:

docker compose run --rm setup renew-cert --output=dir:/data

CLI 引數會取代 setup 服務的 command(即 init 引數),但保留其 entrypoint,因此這會執行 /setup renew-cert --output=dir:/data

不使用程式化存取時,請使用您現有的 CA 簽署新的伺服器憑證(在 Console 中註冊的 CA 不會變更),並取代 data/tls.crt。如果您是在新的 shell 中執行,請先設定 TUNNEL_DOMAIN

export TUNNEL_DOMAIN=YOUR_TUNNEL_DOMAIN_HERE
openssl req -new -key data/tls.key -out /tmp/server.csr \
  -subj "/CN=${TUNNEL_DOMAIN}"
openssl x509 -req -in /tmp/server.csr \
  -CA data/ca.crt -CAkey data/ca.key -CAcreateserial \
  -out data/tls.crt -days 90 \
  -extfile data/tls.ext

在任一流程中,proxy 都會輪詢 tls.cert_file 並自動重新載入,因此不需要重新啟動。

後續步驟

將上游 MCP 伺服器附加到 Managed Agent 或 Messages API。

強化指引、憑證輪替與入侵應變。

診斷連線、TLS 與路由問題。

Was this page helpful?