HelmでMCPトンネルをデプロイする
Anthropic Helmチャートを使用して、Kubernetesクラスターにトンネルスタックをインストールします。
Anthropic Helmチャートは、トンネルスタックを単一のDeploymentとしてインストールし、トンネルにアタッチします。アタッチ先は、チャートのセットアップフックが作成するトンネル、またはClaude Consoleで作成した既存のトンネルのいずれかです。
始める前に
以下が必要です。
- トンネル。 プログラムによるアクセスを使用する場合、トンネルIDを指定しなければ、チャートのセットアップフックがトンネルを作成します。代わりに既存のトンネルにアタッチするには、Consoleでトンネルを作成し、トンネルID(
tnl_...)を記録してください。手動プロビジョニングは常にConsoleで作成したトンネルから始まります。その場合、トンネルトークンとトンネルドメインも必要です。 - チャートがTunnels APIに対して認証する手段。
- プログラムによるアクセス(推奨)。 セットアップコンポーネントがWorkload Identity Federationを通じて認証し、トンネルトークンを取得し、CAを生成してAnthropicに登録し、すべてをSecretに保存します。
workspace:manage_tunnelsにスコープされたフェデレーションルールが必要です。 - 手動。 プログラムによるアクセスを使用しません。Consoleからトンネルトークンを取得し、CAとサーバー証明書を自分で生成し、ConsoleでCAを登録して、認証情報をSecretとしてクラスターに提供します。
- プログラムによるアクセス(推奨)。 セットアップコンポーネントがWorkload Identity Federationを通じて認証し、トンネルトークンを取得し、CAを生成してAnthropicに登録し、すべてをSecretに保存します。
helmとkubectlでデプロイできるKubernetesクラスター。プログラムによるアクセスなしタブではopenssl(1.1.1以降)も使用します。- クラスターから
api.anthropic.com(443 TCP)およびトンネルエッジ(7844 TCPおよびUDP)へのアウトバウンドネットワーク接続。完全なネットワーク要件を参照してください。 - 実行中で、
gateway.config.routesで設定するアドレスでクラスターから到達可能な1つ以上のMCPサーバー。まだない場合は、サンプルサーバーを使用してください。
オプション:サンプルMCPサーバーを使用する
テスト用のMCPサーバーがない場合は、次の最小限のサーバーを使用してください。
kubectl create namespace mcp-tunnel --dry-run=client -o yaml | kubectl apply -f -
kubectl -n mcp-tunnel apply -f - <<'EOF'
apiVersion: v1
kind: ConfigMap
metadata:
name: hello-mcp-src
data:
hello_server.py: |
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")
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: hello-mcp
spec:
replicas: 1
selector:
matchLabels: { app: hello-mcp }
template:
metadata:
labels: { app: hello-mcp }
spec:
containers:
- name: hello-mcp
image: python:3.13-slim
command: ["sh", "-c", "pip install --quiet mcp && python /app/hello_server.py"]
volumeMounts:
- { name: src, mountPath: /app }
ports:
- { containerPort: 9000 }
volumes:
- name: src
configMap: { name: hello-mcp-src }
---
apiVersion: v1
kind: Service
metadata:
name: hello-mcp
spec:
selector: { app: hello-mcp }
ports:
- { port: 9000, targetPort: 9000 }
EOF以降のインストール手順で、対応するルートを追加する箇所を示します。
インストール
セットアップコンポーネントは、クラスターのprojected ServiceAccountトークンをフェデレーションルールを通じて交換し、トンネルトークンを取得し、CAとサーバー証明書を生成して、CAをAnthropicに登録します。毎日実行されるCronJobが必要に応じてサーバー証明書を更新するため、シークレットを手動で扱う必要はありません。
クラスター用にWorkload Identity Federationを設定する
KubernetesでWIFを使用するに従って、クラスターのOIDC発行者を登録し、フェデレーションルールを作成します。セットアップコンポーネントは、リリースnamespace内の専用のServiceAccountで実行されます。正確な名前はHelmの
fullname規則に従うため、mcp-tunnel以外のリリース名を使用する場合は、ルールを作成する前にhelm template <release> ... | grep -A2 'kind: ServiceAccount'を実行して確認してください。このガイドの残りの部分では、namespacemcp-tunnel内のリリース名mcp-tunnelを前提としており、その場合のServiceAccountはmcp-tunnel-setupです。フィールド 値 Subject system:serviceaccount:mcp-tunnel:mcp-tunnel-setupAudience api.anthropic.com(チャートのデフォルト。スキームなし)Scope workspace:manage_tunnelsトンネルが組織のデフォルト以外のワークスペースにある場合は、ルールのサービスアカウントをそのワークスペースに追加してください(Tunnels APIはサービスアカウントのワークスペースメンバーシップに基づいて認可を行います)。
ルールのID(
fdrl_...)を控えておいてください。これをapi.wif.federationRuleIdとして設定します。デフォルト値を取得する
helm show values \ oci://us-docker.pkg.dev/anthropic-public-registry/charts/mcp-tunnel \ --version 2.1.0 > values.yamlトンネルのアタッチとルートを設定する
values.yamlを編集し、api.wif.*キーにフェデレーションルールIDと組織IDを設定し、さらに各アップストリームMCPサーバーのroutesエントリを追加します。values.yamlapi: wif: federationRuleId: "fdrl_..." organizationId: "00000000-0000-0000-0000-000000000000" # Set when the tunnel is in a non-default workspace and the # rule's service account is a member of that workspace. # workspaceId: "wrkspc_..." tunnel: # Leave empty to have the setup hook create a tunnel during install. # Set to attach to an existing tunnel from the Console. id: "" # Increment to rotate the tunnel token on the next upgrade. # See the "Rotate the tunnel token" section. tokenVersion: "1" gateway: config: routes: docs: http://docs-mcp.internal:8080 search: http://search-mcp.internal:8080これらのルートにより、Claudeは
docs.<your-tunnel-domain>とsearch.<your-tunnel-domain>でサーバーに到達します。一部のマネージドKubernetesディストリビューションは、標準のプライベート範囲外にService CIDRを割り当てます。ルートがクラスター内のServiceを対象とする場合は、アップストリームIP検証の説明に従って、ここにgateway.config.upstream.allowed_ipsを追加してください。レンダリングされたマニフェストを確認する
チャートをレンダリングし、組織の審査手順に従って出力を確認します。
helm template mcp-tunnel \ oci://us-docker.pkg.dev/anthropic-public-registry/charts/mcp-tunnel \ --version 2.1.0 \ -n mcp-tunnel \ -f values.yaml > rendered.yamlインストールする
helm install mcp-tunnel \ oci://us-docker.pkg.dev/anthropic-public-registry/charts/mcp-tunnel \ --version 2.1.0 \ --namespace mcp-tunnel --create-namespace \ -f values.yamlセットアップコンポーネントはHelmのpre-installフックJobとして実行されるため、
helm installは完了するまでブロックされます。成功すると、HelmはJobを自動的に削除します。helm installがフックエラーで失敗した場合は、セットアップコンポーネントの認証失敗を参照してください。tunnel.idが空の場合、セットアップコンポーネントはフェデレーションルールが対象とするワークスペース(api.wif.workspaceIdを設定しない限り組織のデフォルトワークスペース)にトンネルを作成し、そのIDとドメインをmcp-tunnelSecretに保存します。検証に必要なドメインは、ConsoleのMCP tunnelsページ(platform.claude.com/settings/workspaces/default/mcp-tunnels)から開くトンネルの詳細ページで確認できます。サイドバーのワークスペースピッカーで、トンネルを含むワークスペースを選択してください。Secretからドメインを読み取ることもできます。kubectl -n mcp-tunnel get secret mcp-tunnel \ -o jsonpath='{.data.tunnel-domain}' | base64 -dセットアップコンポーネントを再実行する場合(アップグレード時やトークンのローテーション時)、このSecretに保存されたトンネルIDが再利用されます。2つ目のトンネルが作成されることはありません。
このモード(setup.enabled: false)では、チャートはAPI呼び出しを行いません。セットアップコンポーネントは実行されず、cert-renew CronJobもありません。Workload Identity Federationを設定したくない場合は、この方法を使用してください。
トンネルトークンとドメインを取得する
CAとサーバー証明書を生成する
プロキシはプレーンなWebSocketでリッスンし、内部TLSはここで生成する証明書を使用してそのストリーム内で伝送されます。証明書の要件で説明されているとおり、サーバー証明書のSANには
*.<tunnel-domain>を含める必要があります。export TUNNEL_DOMAIN=YOUR_TUNNEL_DOMAIN_HERE mkdir -p mcp-tunnel/data cd mcp-tunnel # 自己署名CA。ディストリビューションの openssl.cnf のデフォルトに関係なく証明書の # 要件を満たすよう、拡張を明示的に指定します。 openssl req -x509 -newkey rsa:2048 -nodes \ -keyout data/ca.key -out data/ca.crt \ -days 3650 -subj "/CN=mcp-tunnel-ca" \ -addext "basicConstraints=critical,CA:TRUE" \ -addext "keyUsage=critical,keyCertSign,cRLSign" \ -addext "subjectKeyIdentifier=hash" # サーバー証明書用の拡張ファイル。-extfile を使用することで(OpenSSL 3.0+ 専用の # -copy_extensions の代わりに)、 # OpenSSL 1.1.x でも動作します。 cat > data/tls.ext <<EOF subjectAltName = DNS:${TUNNEL_DOMAIN},DNS:*.${TUNNEL_DOMAIN} authorityKeyIdentifier = keyid,issuer extendedKeyUsage = serverAuth EOF # CA によって署名されたサーバー証明書 openssl req -newkey rsa:2048 -nodes \ -keyout 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.extConsoleで
data/ca.crtを登録します。data/ca.keyは永続的かつ安全な場所に保管してください。更新時に新しいサーバー証明書に署名するために必要になります。2つのSecretを作成する
チャートは特定のキーを読み取ります。Secret名は設定可能ですが、キーは変更できません。次のnamespace作成コマンドは、namespaceがすでに存在する場合(たとえばサンプルMCPサーバーの手順で作成済みの場合)は何も行いません。
kubectl create namespace mcp-tunnel --dry-run=client -o yaml | kubectl apply -f - kubectl -n mcp-tunnel create secret generic mcp-tunnel-token \ --from-literal=tunnel-token='eyJ...' kubectl -n mcp-tunnel create secret generic mcp-tunnel-cert \ --from-file=tls.crt=data/tls.crt \ --from-file=tls.key=data/tls.keyデフォルト値を取得する
helm show values \ oci://us-docker.pkg.dev/anthropic-public-registry/charts/mcp-tunnel \ --version 2.1.0 > values.yaml手動プロビジョニング用の値を設定する
values.yamlを編集し、次のキーを設定します。values.yamlsetup: enabled: false external: tunnelTokenSecretName: mcp-tunnel-token # must contain key: tunnel-token serverCertSecretName: mcp-tunnel-cert # must contain keys: tls.crt, tls.key gateway: config: # Required when setup.enabled is false. Replace the placeholder with # the $TUNNEL_DOMAIN value you exported earlier. When setup.enabled # is true the chart injects this from the Secret as a -tunnel-domain # flag instead. tunnel_domain: YOUR_TUNNEL_DOMAIN_HERE routes: docs: http://docs-mcp.internal:8080 search: http://search-mcp.internal:8080一部のマネージドKubernetesディストリビューションは、標準のプライベート範囲外にService CIDRを割り当てます。ルートがクラスター内のServiceを対象とする場合は、アップストリームIP検証の説明に従って、ここに
gateway.config.upstream.allowed_ipsを追加してください。レンダリングされたマニフェストを確認する
helm template mcp-tunnel \ oci://us-docker.pkg.dev/anthropic-public-registry/charts/mcp-tunnel \ --version 2.1.0 \ -n mcp-tunnel \ -f values.yaml > rendered.yamlインストールする
helm install mcp-tunnel \ oci://us-docker.pkg.dev/anthropic-public-registry/charts/mcp-tunnel \ --version 2.1.0 \ --namespace mcp-tunnel --create-namespace \ -f values.yaml
デプロイを検証する
Anthropic側からエンドツーエンドで検証します。Managed AgentセッションまたはMessages APIリクエストでhttps://<route>.<your-tunnel-domain>/<path>を使用します。ここで、<route>はgateway.config.routesのキー、<path>はアップストリームMCPサーバーが提供するパスです。サンプルMCPサーバーの場合はhttps://echo.<your-tunnel-domain>/mcpです。リクエストの形式については、トンネル経由のMCPサーバーを使用するを参照してください。
失敗した場合は、Podのログ(kubectl -n mcp-tunnel logs deploy/mcp-tunnel -c mcp-proxyおよび-c cloudflared)を確認し、トラブルシューティングを参照してください。
オプションの設定
NetworkPolicyでegressを制限する
プロキシPodへのingressはデフォルトで拒否されます(networkPolicy.ingress.enabled: true)。さらにPodのegressを制限するには、networkPolicy.egress.enabled: trueを設定し、アップストリームMCPサーバーをカバーするPodラベルセレクターまたはCIDR範囲をnetworkPolicy.egress.mcpServersに指定します。cloudflaredからトンネルエッジへのegressは、networkPolicy.egress.cloudflaredEgressCIDRsを通じて別途許可されます。
プロキシを調整する
gateway.config.*配下のフィールドは、プロキシ設定ファイルにそのまま渡されます。一般的な調整項目には、upstream.allowed_ips、log_level、upstream.tlsがあります。フィールドの完全な一覧については、プロキシ設定リファレンスを参照してください。チャートは常にlisten_addr、tls.cert_file、tls.key_fileを設定するため、これらをgateway.configで設定しても効果はありません。
独自のOIDCトークンを提供する
デフォルトでは、チャートはセットアップコンポーネント用にKubernetes ServiceAccountトークンをprojectします。別のIDプロバイダー(SPIFFE、Vault、クラウドSDKサイドカーなど)のトークンを使用するには、setup.extraVolumesとsetup.extraVolumeMountsでマウントします。次に、api.wif.tokenFileをマウントパスに向けます。チャートはANTHROPIC_IDENTITY_TOKEN_FILEをそのパスに設定し、セットアップコンポーネントはそこからトークンを読み取ります。
アップグレード
予期せず新しいチャートを取得しないように、helm upgradeには常に--versionを渡してください。
チャート1.xからのアップグレード
チャート2.0.0では、トンネルIDがapi.wif.tunnelIdからtunnel.idに移動しました。アップグレードする前にvalues.yamlを編集し、tnl_...の値をtunnel.idに移動してapi.wif.tunnelIdを削除してください。tunnel.idを未設定のままにしても安全です(セットアップコンポーネントは再実行時にmcp-tunnel Secretにすでに保存されているトンネルIDを再利用します)が、明示的に移動することでvalues.yamlを正確に保てます。また、Consoleでフェデレーションルールのスコープをorg:manage_tunnelsからworkspace:manage_tunnelsに更新してください。
設定を変更する
ルート、レプリカ数、NetworkPolicyなどの定常的な変更の場合:
helm upgrade mcp-tunnel \
oci://us-docker.pkg.dev/anthropic-public-registry/charts/mcp-tunnel \
--version 2.1.0 \
-n mcp-tunnel \
-f values.yamlトンネルトークンをローテーションする
プログラムによるアクセスを使用する場合は、values.yamlのtunnel.tokenVersionをインクリメントし、--set setup.force=trueを指定してアップグレードします。セットアップコンポーネントは、強制された場合にのみアップグレード時に再実行されます。
helm upgrade mcp-tunnel \
oci://us-docker.pkg.dev/anthropic-public-registry/charts/mcp-tunnel \
--version 2.1.0 \
-n mcp-tunnel \
-f values.yaml \
--set setup.force=trueセットアップコンポーネントはWorkload Identity Federationで認証するため、失効させるAPIトークンはありません。
プログラムによるアクセスを使用しない場合は、Consoleのトンネル詳細ページでRotate tokenをクリックし、mcp-tunnel-token Secretを更新します。
kubectl -n mcp-tunnel create secret generic mcp-tunnel-token \
--from-literal=tunnel-token='eyJ...' --dry-run=client -o yaml | kubectl apply -f -
kubectl -n mcp-tunnel rollout restart deploy/mcp-tunnel証明書の更新
チャートは自動化を提供しますが、有効期限の監視と更新の完了確認は引き続きお客様の責任です。
プログラムによるアクセスを使用する場合、証明書の更新は自動です。チャートは、setup renew-certを毎日(serverCert.cronSchedule、デフォルトはUTCの0 0 * * *)実行するCronJob(Helmのfullnameに-cert-renewを付けた名前)をデプロイします。このジョブは、証明書の有効期限がserverCert.renewBefore(デフォルト30日)以内でない限り何も行いません。更新はローカルで行われます。ジョブはSecretにすでに保存されているCAで新しい証明書に署名し、API呼び出しは行わず、チャートが付与するKubernetes RBACのみを必要とします。プロキシはSecretマウントから証明書をホットリロードするため、Deploymentの再起動は不要です。
プログラムによるアクセスを使用しない場合、CronJobはありません。インストール後に保持しているmcp-tunnel/ディレクトリ内から、既存のCAで新しいサーバー証明書に署名します(CAは再生成しないでください)。
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
kubectl -n mcp-tunnel create secret generic mcp-tunnel-cert \
--from-file=tls.crt=data/tls.crt --from-file=tls.key=data/tls.key \
--dry-run=client -o yaml | kubectl apply -f -プロキシはSecretマウントから証明書をホットリロードします。
次のステップ
アップストリームMCPサーバーをManaged AgentまたはMessages APIにアタッチします。
強化のガイダンス、認証情報のローテーション、侵害への対応。
接続、TLS、ルーティングの問題を診断します。
Was this page helpful?