Claude Platform Docs
メッセージMCPトンネル

Docker ComposeでMCPトンネルをデプロイする

Docker Composeを使用してVMにMCPトンネルスタックをインストールします。

このガイドでは、トンネルスタックを単一ホスト上の強化されたコンテナとしてデプロイします。可用性のために、同じ構成を複数のホストに複製することもできます。

始める前に

以下が必要です。

  • トンネル。 プログラムによるアクセスを使用する場合、トンネルIDを指定しなければセットアップコンポーネントがトンネルを作成します。代わりに既存のトンネルに接続するには、Claude Consoleでトンネルを作成し、トンネルID(tnl_...)を控えておきます。手動プロビジョニングは常にConsoleで作成したトンネルから開始します。
  • ホストがTunnels APIに対して認証する手段。
    • プログラムによるアクセス(推奨)。 トンネルの作成時に Set up programmatic access をオンにすると、セットアップコンポーネントが「Workload Identity Federation」(ワークロードアイデンティティフェデレーション)を通じて認証できるようになります。セットアップコンポーネントにトンネルを作成させる場合は、代わりにClaude ConsoleのWorkload identityページ(platform.claude.com/settings/workload-identity-federation)でフェデレーションルールを直接作成してください。フェデレーションルールID(fdrl_...)と組織IDを記録してください。
    • 手動。 プログラムによるアクセスをスキップします。Consoleからトンネルトークンを取得し、CAとサーバー証明書を自分で生成して、ConsoleにCAを登録します。
  • DockerとDocker Composeがインストールされたホスト。 手動フローでは openssl(1.1.1以降)も必要です。
  • ホストから api.anthropic.com(443 TCP)およびトンネルエッジ(7844 TCPおよびUDP)へのアウトバウンドネットワーク接続。完全なネットワーク要件を参照してください。
  • 実行中で、routes の下に設定するアドレスでホストから到達可能な1つ以上のMCPサーバー。まだない場合は、サンプルサーバーを使用してください。

オプション:サンプル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

以下のインストール手順では mcp-tunnel/ に cd し、対応するサービスとルートを追加する場所を示します。

インストール

このガイドでは、Docker Composeを使用した参考アプローチの1つを示します。組織のセキュリティ要件を満たすように調整する責任はお客様にあります。

この方法では、ホストにOIDCアイデンティティプロバイダー(クラウドVMのメタデータサーバーや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ケーパビリティを削除し、権限昇格を無効にします。

    cat > docker-compose.yaml <<'EOF'
    services:
      setup:
        image: us-docker.pkg.dev/anthropic-public-registry/images/mcp-proxy@sha256:d243d30642d39857a0579e465cb3b9bf3ae7c1141e83143bb6856777a31467a5
        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:0e56c13c7058fcef9c4f0e7d83372f82330548dbf8f8b366f3d8b506526d93b2
        command: tunnel --no-autoupdate run --url http://localhost:8080
        environment:
          - TUNNEL_TOKEN
        # localhost:8080 でプロキシに到達できるよう、プロキシの netns を共有します。
        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:d243d30642d39857a0579e465cb3b9bf3ae7c1141e83143bb6856777a31467a5
        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_...   # 既存のトンネルに接続する場合に設定します
    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ガイドに従って、発行者の登録、ルールのサブジェクトの設定、トークンの発行を行ってください。ルールのオーディエンスは、発行時に要求するオーディエンスと一致する必要があります。

    セットアップコンポーネントを実行します。

    docker compose run --rm setup

    setup init は data/ に対して冪等です。再実行すると、そこにすでに保存されているトンネルIDとCAを再利用し、2つ目のトンネルを作成することはありません。新しいCAが生成・登録されるのは、data/ が空の場合または TUNNEL_ID が変更された場合のみです。その場合はアクティブな証明書が2つまでという上限が適用されるため、両方の枠が埋まっている場合は先にConsoleで1つを失効させてください。

    エラーが発生した場合は、セットアップコンポーネントの認証失敗を参照してください。

    トンネルドメインを取得し、後の手順のためにエクスポートします。

    export TUNNEL_DOMAIN=$(sudo cat data/tunnel-domain)
    echo "$TUNNEL_DOMAIN"
  4. プロキシ設定を作成する

    tunnel_domain は必須です。プロキシはこれを使用して、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サーバーを対象としています。独自のルートに置き換える(または追加する)してください。利用可能なすべてのフィールドについては、プロキシ設定リファレンスを参照してください。

  5. デプロイを開始する

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

composeファイルはデフォルト値なしでホスト環境からTUNNEL_TOKENを読み取るため、新しいシェルを開くたび、および再起動後にエクスポートを繰り返す必要があります。

複数VMでのデプロイでは、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 を置き換えます。新しいシェルから実行する場合は、先に 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

どちらのフローでも、プロキシは tls.cert_file をポーリングして自動的に再読み込みするため、再起動は不要です。

次のステップ

Was this page helpful?