Claude Platform Docs
MessagesMCP-Tunnel

MCP-Tunnel mit Docker Compose bereitstellen

Installiere den MCP-Tunnel-Stack auf einer VM mit Docker Compose.

Diese Anleitung stellt den Tunnel-Stack als gehärtete Container auf einem einzelnen Host bereit. Dieselbe Konfiguration kann für Verfügbarkeit auf mehrere Hosts repliziert werden.

Bevor du beginnst

Du benötigst:

  • Einen Tunnel. Mit programmatischem Zugriff erstellt die Setup-Komponente einen für dich, wenn du keine Tunnel-ID angibst; um stattdessen einen bestehenden Tunnel anzubinden, erstelle ihn in der Console und notiere die Tunnel-ID (tnl_...). Die manuelle Bereitstellung beginnt immer mit einem in der Console erstellten Tunnel.
  • Eine Möglichkeit für den Host, sich bei der Tunnels API zu authentifizieren.
    • Programmatischer Zugriff (empfohlen). Aktiviere Set up programmatic access beim Erstellen des Tunnels (oder erstelle die Föderationsregel direkt unter Settings > Workload identity, wenn du die Setup-Komponente den Tunnel erstellen lässt), damit sich die Setup-Komponente über Workload Identity Federation authentifizieren kann. Notiere die Föderationsregel-ID (fdrl_...) und deine Organisations-ID.
    • Manuell. Überspringe den programmatischen Zugriff. Du holst das Tunnel-Token aus der Console, erzeugst selbst eine CA und ein Serverzertifikat und registrierst die CA in der Console.
  • Einen Host mit installiertem Docker und Docker Compose. Der manuelle Ablauf erfordert außerdem openssl (1.1.1 oder neuer).
  • Ausgehende Netzwerkkonnektivität vom Host 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 Host unter den Adressen erreichbar sind, die du unter routes konfigurierst. Wenn du noch keinen hast, verwende den Beispielserver.

Optional: Einen Beispiel-MCP-Server verwenden

Wenn du keinen MCP-Server zum Testen zur Verfügung hast, verwende diesen minimalen:

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

Die folgenden Installationsschritte wechseln mit cd in mcp-tunnel/ und weisen darauf hin, wo der entsprechende Service und die Route hinzuzufügen sind.

Installieren

Diese Anleitung bietet einen Referenzansatz mit Docker Compose. Du bist dafür verantwortlich, ihn an die Sicherheitsanforderungen deiner Organisation anzupassen.

Dieser Weg erfordert, dass der Host über einen OIDC-Identitätsanbieter verfügt (etwa einen Metadatenserver einer Cloud-VM oder SPIFFE). Falls nicht, verwende stattdessen den Tab Ohne programmatischen Zugriff.

Die Setup-Komponente verwendet Workload Identity Federation, um das Tunnel-Token abzurufen, eine CA und ein Serverzertifikat zu erzeugen und die CA bei Anthropic zu registrieren.

  1. Das Bereitstellungsverzeichnis vorbereiten

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

    Die Container laufen als Nicht-Root-UID 65532 und benötigen Schreibzugriff auf data/.

  2. docker-compose.yaml schreiben

    Die Compose-Datei pinnt Images per SHA-256-Digest, führt jeden Container als Nicht-Root mit schreibgeschütztem Dateisystem aus, entfernt alle Linux-Capabilities und deaktiviert die Rechteausweitung.

    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
        # Teile den netns des Proxys, damit localhost:8080 ihn erreicht.
        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

    Wenn du den Beispiel-MCP-Server verwendest, hänge ihn als Service an:

    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. Den Tunnel bereitstellen

    Setze die Kennungen. Lass TUNNEL_ID ungesetzt, damit die Setup-Komponente einen Tunnel erstellt; setze sie, um einen bestehenden Tunnel aus der Console anzubinden:

    # export TUNNEL_ID=tnl_...   # setzen, um an einen bestehenden Tunnel anzuhängen
    export ANTHROPIC_FEDERATION_RULE_ID=fdrl_...
    export ANTHROPIC_ORGANIZATION_ID=00000000-0000-0000-0000-000000000000

    Wenn deine Föderationsregel auf einen anderen Workspace als den Standard-Workspace deiner Organisation beschränkt ist, setze zusätzlich ANTHROPIC_WORKSPACE_ID=wrkspc_...; andernfalls verwendet die Setup-Komponente den Standard-Workspace. Ein automatisch erstellter Tunnel wird in diesem Workspace erstellt.

    Setze ANTHROPIC_IDENTITY_TOKEN auf ein OIDC-JWT vom Identitätsanbieter dieses Hosts. Folge der WIF-Anleitung für deinen Anbieter, um den Issuer zu registrieren, das Subject der Regel zu setzen und das Token auszustellen; die Audience der Regel muss mit der Audience übereinstimmen, die du beim Ausstellen anforderst.

    Führe die Setup-Komponente aus:

    docker compose run --rm setup

    setup init ist idempotent bezüglich data/: Ein erneutes Ausführen verwendet die dort bereits gespeicherte Tunnel-ID und CA wieder und erstellt niemals einen zweiten Tunnel. Eine neue CA wird nur erzeugt und registriert, wenn data/ leer ist oder sich TUNNEL_ID geändert hat; in diesem Fall gilt die Obergrenze von zwei aktiven Zertifikaten, widerrufe also zuerst eines in der Console, wenn beide Plätze belegt sind.

    Siehe Authentifizierungsfehler der Setup-Komponente, falls ein Fehler auftritt.

    Rufe deine Tunnel-Domain ab und exportiere sie für spätere Schritte:

    export TUNNEL_DOMAIN=$(sudo cat data/tunnel-domain)
    echo "$TUNNEL_DOMAIN"
  4. Die Proxy-Konfiguration schreiben

    tunnel_domain ist erforderlich: Der Proxy verwendet sie, um das Domain-Suffix von eingehenden Hostnamen zu entfernen, bevor er die Subdomain in routes nachschlägt. routes ist eine flache Map von Subdomain zu Upstream-URL, keine Liste.

    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

    Die Route echo: zielt auf den Beispiel-MCP-Server; ersetze sie durch deine eigenen Routen (oder füge diese hinzu). Siehe die Referenz zur Proxy-Konfiguration für alle verfügbaren Felder.

  5. Die Bereitstellung starten

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

Die Compose-Datei liest TUNNEL_TOKEN ohne Standardwert aus der Host-Umgebung, daher muss der Export in jeder neuen Shell und nach einem Neustart wiederholt werden.

Für eine Bereitstellung auf mehreren VMs kopiere das Verzeichnis mcp-tunnel/ auf jeden Host, setze TUNNEL_TOKEN und führe docker compose up -d aus. Im programmatischen Ablauf ist TUNNEL_TOKEN gleich $(sudo cat data/tunnel-token); im manuellen Ablauf ist es der Wert, den du aus der Console kopiert hast. Dasselbe Tunnel-Token und dieselben Zertifikate funktionieren über alle Replikate hinweg.

Die Bereitstellung verifizieren

Verifiziere Ende-zu-Ende, indem du einen Upstream-MCP-Server von Anthropics Seite aus aufrufst: siehe Die getunnelten MCP-Server verwenden. Mit dem Beispiel-MCP-Server lautet die geroutete URL https://echo.<your-tunnel-domain>/mcp. Wenn die Verifizierung fehlschlägt, siehe Fehlerbehebung.

Upgrades

Führe die Befehle in diesem Abschnitt innerhalb des Bereitstellungsverzeichnisses mcp-tunnel/ aus.

Das Tunnel-Token rotieren

Mit programmatischem Zugriff erhöhe --token-version im Befehl des setup-Services, setze die Workload-Identity-Federation-Kennungen, stelle ein frisches OIDC-JWT aus und führe die Setup-Komponente erneut aus:

# Bearbeite docker-compose.yaml: Erhöhe die Ganzzahl im Argument
# --token-version des setup-Dienstes (zum Beispiel --token-version=1 auf
# --token-version=2). Das setup-Binary verweigert die Rotation, wenn sich der Wert
# nicht geändert hat.

# export TUNNEL_ID=tnl_...   # nur setzen, wenn du es bei der Installation gesetzt hast
export ANTHROPIC_FEDERATION_RULE_ID=fdrl_...
export ANTHROPIC_ORGANIZATION_ID=00000000-0000-0000-0000-000000000000
# export ANTHROPIC_WORKSPACE_ID=wrkspc_...   # falls deine Regel Workspace-bezogen ist
# Erstelle ANTHROPIC_IDENTITY_TOKEN neu gemäß dem WIF-Provider-Leitfaden für deine
# Umgebung (es ist seit der Installation abgelaufen).
export ANTHROPIC_IDENTITY_TOKEN=...

docker compose run --rm setup

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

Das Argument --token-version wird in docker-compose.yaml bearbeitet statt auf der Kommandozeile übergeben, damit der neue Wert für zukünftige Ausführungen der Setup-Komponente erhalten bleibt. Die Setup-Komponente authentifiziert sich mit Workload Identity Federation; es gibt kein API-Token zu widerrufen.

Ohne programmatischen Zugriff klicke auf der Tunnel-Detailseite in der Console auf Rotate token, aktualisiere dann die Umgebungsvariable TUNNEL_TOKEN auf jedem Host und starte cloudflared neu (docker compose up -d cloudflared).

Zertifikatserneuerung

Du bist dafür verantwortlich, den Ablauf zu überwachen und das Serverzertifikat zu erneuern, bevor es abläuft.

Mit programmatischem Zugriff:

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

Die CLI-Argumente ersetzen den command des setup-Services (die init-Argumente), behalten aber dessen entrypoint bei, sodass dies /setup renew-cert --output=dir:/data ausführt.

Ohne programmatischen Zugriff signiere ein neues Serverzertifikat mit deiner bestehenden CA (die in der Console registrierte CA ändert sich nicht) und ersetze data/tls.crt. Setze zuerst TUNNEL_DOMAIN, wenn du dies aus einer neuen Shell ausführst.

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

In beiden Abläufen fragt der Proxy tls.cert_file regelmäßig ab und lädt sie automatisch neu, sodass kein Neustart erforderlich ist.

Nächste Schritte

Binde einen Upstream-MCP-Server an einen Managed Agent oder die Messages API an.

Hinweise zur Härtung, Rotation von Zugangsdaten und Reaktion auf Sicherheitsvorfälle.

Diagnostiziere Konnektivitäts-, TLS- und Routing-Probleme.

Was this page helpful?