Claude Platform Docs
MessagesMCP-Tunnel

MCP-Tunnel mit Helm bereitstellen

Installiere den Tunnel-Stack mit dem Anthropic-Helm-Chart auf einem Kubernetes-Cluster.

Das Anthropic Helm-Chart installiert den Tunnel-Stack als einzelnes Deployment und verbindet ihn mit deinem Tunnel: entweder mit einem, den der Setup-Hook des Charts für dich erstellt, oder mit einem bestehenden Tunnel, den du in der Claude Console erstellt hast.

Bevor du beginnst

Du benötigst:

  • Einen Tunnel. Mit programmatischem Zugriff erstellt der Setup-Hook des Charts einen für dich, wenn du keine Tunnel-ID angibst; um stattdessen einen bestehenden Tunnel zu verwenden, erstelle ihn in der Console und notiere die Tunnel-ID (tnl_...). Die manuelle Bereitstellung beginnt immer mit einem in der Console erstellten Tunnel; du benötigst außerdem dessen Tunnel-Token und Tunnel-Domain.
  • Eine Möglichkeit für das Chart, sich bei der Tunnels API zu authentifizieren.
  • Einen Kubernetes-Cluster, auf dem du mit helm und kubectl bereitstellen kannst. Der Tab Ohne programmatischen Zugriff verwendet außerdem openssl (1.1.1 oder neuer).
  • Ausgehende Netzwerkverbindung vom Cluster zu api.anthropic.com (443 TCP) und zum Tunnel-Edge (7844 TCP und UDP). Siehe die vollständigen Netzwerkanforderungen.
  • Einen oder mehrere MCP-Server, die laufen und vom Cluster aus unter den Adressen erreichbar sind, die du unter gateway.config.routes konfigurierst. Falls du noch keinen hast, verwende den Beispielserver.

Optional: Einen Beispiel-MCP-Server verwenden

Wenn dir kein MCP-Server zum Testen zur Verfügung steht, verwende diesen minimalen:

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

Die folgenden Installationsschritte weisen darauf hin, wo du die entsprechende Route hinzufügst.

Installieren

Die Setup-Komponente tauscht das projizierte ServiceAccount-Token des Clusters über deine Federation-Regel aus, ruft das Tunnel-Token ab, generiert eine CA und ein Serverzertifikat und registriert die CA bei Anthropic. Ein täglicher CronJob erneuert das Serverzertifikat bei Bedarf, sodass du keine Secrets manuell handhaben musst.

  1. Workload Identity Federation für den Cluster einrichten

    Folge WIF mit Kubernetes verwenden, um den OIDC-Issuer deines Clusters zu registrieren und eine Federation-Regel zu erstellen. Die Setup-Komponente läuft unter einem eigenen ServiceAccount im Release-Namespace; der genaue Name folgt Helms fullname-Konvention. Führe daher bei jedem anderen Release-Namen als mcp-tunnel den Befehl helm template <release> ... | grep -A2 'kind: ServiceAccount' aus, um ihn zu bestätigen, bevor du die Regel erstellst. Der Rest dieser Anleitung geht vom Release-Namen mcp-tunnel im Namespace mcp-tunnel aus, wobei der ServiceAccount mcp-tunnel-setup ist.

    FeldWert
    Subjectsystem:serviceaccount:mcp-tunnel:mcp-tunnel-setup
    Audienceapi.anthropic.com (Standard des Charts; ohne Schema)
    Scopeworkspace:manage_tunnels

    Wenn sich der Tunnel in einem anderen Workspace als dem Standard-Workspace der Organisation befindet, füge außerdem den Service-Account der Regel zu diesem Workspace hinzu (die Tunnels API autorisiert anhand der Workspace-Mitgliedschaften des Service-Accounts).

    Notiere die ID der Regel (fdrl_...); du setzt sie als api.wif.federationRuleId.

  2. Standardwerte abrufen

    helm show values \
      oci://us-docker.pkg.dev/anthropic-public-registry/charts/mcp-tunnel \
      --version 2.1.0 > values.yaml
  3. Tunnel-Anbindung und Routen konfigurieren

    Bearbeite values.yaml und setze die api.wif.*-Schlüssel mit der Federation-Regel-ID und der Organisations-ID sowie einen routes-Eintrag für jeden Upstream-MCP-Server:

    values.yaml
    api:
      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

    Mit diesen Routen erreicht Claude die Server unter docs.<your-tunnel-domain> und search.<your-tunnel-domain>. Einige verwaltete Kubernetes-Distributionen weisen den Service-CIDR außerhalb der standardmäßigen privaten Bereiche zu; wenn deine Routen auf clusterinterne Services zielen, füge hier gateway.config.upstream.allowed_ips hinzu, wie in Upstream-IP-Validierung beschrieben.

  4. Gerenderte Manifeste prüfen

    Rendere das Chart und prüfe die Ausgabe gemäß den Prüfverfahren deiner Organisation:

    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
  5. Installieren

    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

    Die Setup-Komponente läuft als Helm-Pre-Install-Hook-Job, daher blockiert helm install, bis sie abgeschlossen ist. Bei Erfolg löscht Helm den Job automatisch. Wenn helm install mit einem Hook-Fehler fehlschlägt, siehe Authentifizierungsfehler der Setup-Komponente.

    Wenn tunnel.id leer ist, erstellt die Setup-Komponente den Tunnel in dem Workspace, auf den deine Federation-Regel zielt (dem Standard-Workspace der Organisation, sofern du nicht api.wif.workspaceId setzt), und speichert dessen ID und Domain im Secret mcp-tunnel. Die Domain, die du für die Verifizierung benötigst, findest du auf der Detailseite des Tunnels, die du über die Seite MCP tunnels (platform.claude.com/settings/workspaces/default/mcp-tunnels) in der Console öffnest. Wähle in der Workspace-Auswahl in der Seitenleiste den Workspace aus, der den Tunnel enthält. Du kannst die Domain auch aus dem Secret auslesen:

    kubectl -n mcp-tunnel get secret mcp-tunnel \
      -o jsonpath='{.data.tunnel-domain}' | base64 -d

    Ein erneutes Ausführen der Setup-Komponente (bei Upgrades oder der Token-Rotation) verwendet die in diesem Secret gespeicherte Tunnel-ID wieder; es wird nie ein zweiter Tunnel erstellt.

Das Deployment verifizieren

Verifiziere Ende-zu-Ende von Anthropics Seite aus: Verwende https://<route>.<your-tunnel-domain>/<path> in einer Managed-Agent-Sitzung oder einer Messages-API-Anfrage, wobei <route> ein Schlüssel aus gateway.config.routes ist und <path> der Pfad, unter dem der Upstream-MCP-Server bereitstellt. Mit dem Beispiel-MCP-Server ist das https://echo.<your-tunnel-domain>/mcp. Siehe Die getunnelten MCP-Server verwenden für die Anfrageformate.

Wenn das fehlschlägt, prüfe die Pod-Logs (kubectl -n mcp-tunnel logs deploy/mcp-tunnel -c mcp-proxy und -c cloudflared) und konsultiere die Fehlerbehebung.

Optionale Konfiguration

Egress mit NetworkPolicy einschränken

Ingress zum Proxy-Pod ist standardmäßig verweigert (networkPolicy.ingress.enabled: true). Um zusätzlich den Pod-Egress einzuschränken, setze networkPolicy.egress.enabled: true und befülle networkPolicy.egress.mcpServers mit Pod-Label-Selektoren oder CIDR-Bereichen, die deine Upstream-MCP-Server abdecken. Egress von cloudflared zum Tunnel-Edge wird separat über networkPolicy.egress.cloudflaredEgressCIDRs erlaubt.

Den Proxy anpassen

Felder unter gateway.config.* werden an die Proxy-Konfigurationsdatei durchgereicht. Häufige Anpassungen umfassen upstream.allowed_ips, log_level und upstream.tls. Siehe die Referenz zur Proxy-Konfiguration für die vollständige Feldliste. Das Chart setzt immer listen_addr, tls.cert_file und tls.key_file; sie in gateway.config zu setzen, hat keine Wirkung.

Eigenes OIDC-Token bereitstellen

Standardmäßig projiziert das Chart ein Kubernetes-ServiceAccount-Token für die Setup-Komponente. Um ein Token von einem anderen Identitätsanbieter zu verwenden (etwa SPIFFE, Vault oder ein Cloud-SDK-Sidecar), binde es mit setup.extraVolumes und setup.extraVolumeMounts ein. Richte dann api.wif.tokenFile auf den Mount-Pfad. Das Chart setzt ANTHROPIC_IDENTITY_TOKEN_FILE auf diesen Pfad, und die Setup-Komponente liest das Token von dort.

Upgrades

Übergib helm upgrade immer --version, damit du nicht unerwartet ein neueres Chart abrufst.

Upgrade von Chart 1.x

Chart 2.0.0 verschiebt die Tunnel-ID von api.wif.tunnelId nach tunnel.id. Bearbeite vor dem Upgrade deine values.yaml: Verschiebe den tnl_...-Wert nach tunnel.id und entferne api.wif.tunnelId. tunnel.id nicht zu setzen ist unbedenklich (die Setup-Komponente verwendet beim erneuten Ausführen die bereits im Secret mcp-tunnel gespeicherte Tunnel-ID wieder), aber das explizite Verschieben hält deine values.yaml korrekt. Aktualisiere außerdem in der Console den Scope deiner Federation-Regel von org:manage_tunnels auf workspace:manage_tunnels.

Konfiguration ändern

Für routinemäßige Änderungen wie Routen, Replikatanzahl oder 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

Das Tunnel-Token rotieren

Mit programmatischem Zugriff erhöhst du tunnel.tokenVersion in values.yaml und führst das Upgrade mit --set setup.force=true durch. Die Setup-Komponente läuft bei Upgrades nur erneut, wenn dies erzwungen wird:

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

Die Setup-Komponente authentifiziert sich mit Workload Identity Federation; es gibt kein API-Token, das widerrufen werden müsste.

Ohne programmatischen Zugriff klickst du auf der Tunnel-Detailseite in der Console auf Rotate token und aktualisierst dann das Secret mcp-tunnel-token:

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

Zertifikatserneuerung

Das Chart bietet Automatisierung, aber du bleibst dafür verantwortlich, den Ablauf zu überwachen und zu bestätigen, dass die Erneuerung abgeschlossen wird.

Mit programmatischem Zugriff erfolgt die Zertifikatserneuerung automatisch. Das Chart stellt einen CronJob bereit (benannt nach dem Helm-fullname mit dem Suffix -cert-renew), der täglich setup renew-cert ausführt (zu serverCert.cronSchedule, standardmäßig 0 0 * * * UTC). Der Job tut nichts, es sei denn, das Zertifikat läuft innerhalb von serverCert.renewBefore ab (standardmäßig 30 Tage). Die Erneuerung erfolgt lokal: Der Job signiert ein neues Zertifikat mit der bereits im Secret gespeicherten CA, führt keine API-Aufrufe durch und benötigt nur das Kubernetes-RBAC, das das Chart gewährt. Der Proxy lädt das Zertifikat im laufenden Betrieb aus dem Secret-Mount neu, sodass kein Neustart des Deployments erforderlich ist.

Ohne programmatischen Zugriff gibt es keinen CronJob. Signiere aus dem Verzeichnis mcp-tunnel/, das du nach der Installation aufbewahrt hast, ein neues Serverzertifikat mit der bestehenden CA (generiere die CA nicht neu):

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 -

Der Proxy lädt das Zertifikat im laufenden Betrieb aus dem Secret-Mount neu.

Nächste Schritte

Was this page helpful?