Déployer des tunnels MCP avec Docker Compose
Installez la pile de tunnel MCP sur une VM à l'aide de Docker Compose.
Ce guide déploie la pile de tunnel sous forme de conteneurs durcis sur un seul hôte. La même configuration peut être répliquée sur plusieurs hôtes pour la disponibilité.
Avant de commencer
Vous avez besoin de :
- Un tunnel. Avec l'accès programmatique, le composant de configuration (setup component) en crée un pour vous lorsque vous ne fournissez pas d'ID de tunnel ; pour vous rattacher à un tunnel existant à la place, créez-le dans la Console et notez l'ID du tunnel (
tnl_...). Le provisionnement manuel part toujours d'un tunnel créé dans la Console. - Un moyen pour l'hôte de s'authentifier auprès de l'API Tunnels.
- Accès programmatique (recommandé). Activez Set up programmatic access lors de la création du tunnel (ou créez la règle de fédération directement sous Settings > Workload identity si vous laissez le composant de configuration créer le tunnel) afin que le composant de configuration puisse s'authentifier via Workload Identity Federation. Notez l'ID de la règle de fédération (
fdrl_...) et l'ID de votre organisation. - Manuel. Ignorez l'accès programmatique. Vous récupérerez le jeton du tunnel depuis la Console, générerez vous-même une CA et un certificat serveur, puis enregistrerez la CA dans la Console.
- Accès programmatique (recommandé). Activez Set up programmatic access lors de la création du tunnel (ou créez la règle de fédération directement sous Settings > Workload identity si vous laissez le composant de configuration créer le tunnel) afin que le composant de configuration puisse s'authentifier via Workload Identity Federation. Notez l'ID de la règle de fédération (
- Un hôte avec Docker et Docker Compose installés. Le flux manuel nécessite également
openssl(1.1.1 ou ultérieur). - Une connectivité réseau sortante depuis l'hôte vers
api.anthropic.com(443 TCP) et la périphérie du tunnel (tunnel edge) (7844 TCP et UDP). Consultez l'ensemble des exigences réseau. - Un ou plusieurs serveurs MCP en cours d'exécution et joignables depuis l'hôte aux adresses que vous configurerez sous
routes. Si vous n'en avez pas encore, utilisez le serveur d'exemple.
Facultatif : utiliser un serveur MCP d'exemple
Si vous ne disposez pas d'un serveur MCP pour les tests, utilisez ce serveur minimal :
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")
EOFLes étapes d'installation suivantes font un cd dans mcp-tunnel/ et indiquent où ajouter le service et la route correspondants.
Installation
Ce guide fournit une approche de référence utilisant Docker Compose. Il vous incombe de l'adapter pour répondre aux exigences de sécurité de votre organisation.
Ce parcours nécessite que l'hôte dispose d'un fournisseur d'identité OIDC (tel qu'un serveur de métadonnées de VM cloud ou SPIFFE). Si ce n'est pas le cas, utilisez plutôt l'onglet Sans accès programmatique.
Le composant de configuration utilise Workload Identity Federation pour récupérer le jeton du tunnel, générer une CA et un certificat serveur, et enregistrer la CA auprès d'Anthropic.
Préparer le répertoire de déploiement
mkdir -p mcp-tunnel/{config,data} cd mcp-tunnel sudo chown 65532:65532 dataLes conteneurs s'exécutent sous l'UID non root
65532et ont besoin d'un accès en écriture àdata/.Écrire docker-compose.yaml
Le fichier compose épingle les images par empreinte SHA-256, exécute chaque conteneur en tant que non root avec un système de fichiers en lecture seule, supprime toutes les capacités Linux et désactive l'élévation de privilèges.
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 # Partage le netns du proxy pour que localhost:8080 l'atteigne. 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" EOFSi vous utilisez le serveur MCP d'exemple, ajoutez-le en tant que service :
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 EOFProvisionner le tunnel
Définissez les identifiants. Laissez
TUNNEL_IDnon défini pour que le composant de configuration crée un tunnel ; définissez-le pour vous rattacher à un tunnel existant depuis la Console :# export TUNNEL_ID=tnl_... # à définir pour se rattacher à un tunnel existant export ANTHROPIC_FEDERATION_RULE_ID=fdrl_... export ANTHROPIC_ORGANIZATION_ID=00000000-0000-0000-0000-000000000000Si votre règle de fédération est limitée à un espace de travail autre que celui par défaut de votre organisation, définissez également
ANTHROPIC_WORKSPACE_ID=wrkspc_...; sinon, le composant de configuration utilise l'espace de travail par défaut. Un tunnel créé automatiquement est créé dans cet espace de travail.Définissez
ANTHROPIC_IDENTITY_TOKENsur un JWT OIDC provenant du fournisseur d'identité de cet hôte. Suivez le guide WIF de votre fournisseur pour enregistrer l'émetteur, définir le sujet de la règle et émettre le jeton ; l'audience de la règle doit correspondre à l'audience que vous demandez lors de l'émission.Exécutez le composant de configuration :
docker compose run --rm setupsetup initest idempotent surdata/: le réexécuter réutilise l'ID de tunnel et la CA déjà stockés à cet endroit et ne crée jamais de second tunnel. Une nouvelle CA n'est générée et enregistrée que lorsquedata/est vide ou queTUNNEL_IDa changé ; dans ce cas, la limite de deux certificats actifs s'applique, donc révoquez-en d'abord un dans la Console si les deux emplacements sont occupés.Consultez Échecs d'authentification du composant de configuration en cas d'erreur.
Récupérez le domaine de votre tunnel et exportez-le pour les étapes suivantes :
export TUNNEL_DOMAIN=$(sudo cat data/tunnel-domain) echo "$TUNNEL_DOMAIN"Écrire la configuration du proxy
tunnel_domainest obligatoire : le proxy l'utilise pour retirer le suffixe de domaine des noms d'hôte entrants avant de rechercher le sous-domaine dansroutes.routesest une table plate associant un sous-domaine à une URL amont, et non une 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 EOFLa route
echo:cible le serveur MCP d'exemple ; remplacez-la par vos propres routes (ou ajoutez-les). Consultez la référence de configuration du proxy pour tous les champs disponibles.Démarrer le déploiement
export TUNNEL_TOKEN=$(sudo cat data/tunnel-token) docker compose up -d
Le fichier compose lit TUNNEL_TOKEN depuis l'environnement de l'hôte sans valeur par défaut, de sorte que l'export doit être répété dans chaque nouveau shell et après un redémarrage.
Pour un déploiement multi-VM, copiez le répertoire mcp-tunnel/ sur chaque hôte, définissez TUNNEL_TOKEN et exécutez docker compose up -d. Dans le flux programmatique, TUNNEL_TOKEN vaut $(sudo cat data/tunnel-token) ; dans le flux manuel, il s'agit de la valeur que vous avez copiée depuis la Console. Le même jeton de tunnel et les mêmes certificats fonctionnent sur toutes les répliques.
Vérifier le déploiement
Vérifiez de bout en bout en appelant un serveur MCP amont (upstream MCP server) depuis le côté d'Anthropic : consultez Utiliser les serveurs MCP tunnelisés. Avec le serveur MCP d'exemple, l'URL routée est https://echo.<your-tunnel-domain>/mcp. Si la vérification échoue, consultez Dépannage.
Mises à niveau
Exécutez les commandes de cette section depuis le répertoire de déploiement mcp-tunnel/.
Effectuer la rotation du jeton du tunnel
Avec l'accès programmatique, incrémentez --token-version dans la commande du service setup, définissez les identifiants Workload Identity Federation, émettez un nouveau JWT OIDC et réexécutez le composant de configuration :
# Modifiez docker-compose.yaml : incrémentez l'entier dans l'argument
# --token-version du service setup (par exemple, de --token-version=1 à
# --token-version=2). Le binaire setup refuse la rotation lorsque la valeur
# n'a pas changé.
# export TUNNEL_ID=tnl_... # à définir uniquement si vous l'avez défini lors de l'installation
export ANTHROPIC_FEDERATION_RULE_ID=fdrl_...
export ANTHROPIC_ORGANIZATION_ID=00000000-0000-0000-0000-000000000000
# export ANTHROPIC_WORKSPACE_ID=wrkspc_... # si votre règle est limitée à un espace de travail
# Régénérez ANTHROPIC_IDENTITY_TOKEN selon le guide du fournisseur WIF pour votre
# environnement (il aura expiré depuis l'installation).
export ANTHROPIC_IDENTITY_TOKEN=...
docker compose run --rm setup
export TUNNEL_TOKEN=$(sudo cat data/tunnel-token)
docker compose up -d cloudflaredL'argument --token-version est modifié dans docker-compose.yaml plutôt que passé en ligne de commande afin que la nouvelle valeur persiste pour les exécutions futures du composant de configuration. Le composant de configuration s'authentifie avec Workload Identity Federation ; il n'y a pas de jeton API à révoquer.
Sans accès programmatique, cliquez sur Rotate token sur la page de détail du tunnel dans la Console, puis mettez à jour la variable d'environnement TUNNEL_TOKEN sur chaque hôte et redémarrez cloudflared (docker compose up -d cloudflared).
Renouvellement des certificats
Il vous incombe de surveiller l'expiration et de renouveler le certificat serveur avant qu'il n'expire.
Avec l'accès programmatique :
docker compose run --rm setup renew-cert --output=dir:/dataLes arguments CLI remplacent la command du service setup (les arguments init) mais conservent son entrypoint, de sorte que cela exécute /setup renew-cert --output=dir:/data.
Sans accès programmatique, signez un nouveau certificat serveur avec votre CA existante (la CA enregistrée dans la Console ne change pas) et remplacez data/tls.crt. Définissez d'abord TUNNEL_DOMAIN si vous exécutez ceci depuis un nouveau shell.
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.extDans les deux flux, le proxy interroge tls.cert_file et le recharge automatiquement, de sorte qu'aucun redémarrage n'est nécessaire.
Étapes suivantes
Rattachez un serveur MCP amont à un Managed Agent ou à l'API Messages.
Conseils de durcissement, rotation des identifiants et réponse aux violations.
Diagnostiquez les problèmes de connectivité, de TLS et de routage.
Was this page helpful?