Les tunnels MCP sont en aperçu de recherche. Demandez l'accès pour les essayer.
Le chart Helm d'Anthropic installe la pile de tunnel sous la forme d'un unique Deployment et l'attache à votre tunnel : soit un tunnel que le hook de configuration du chart crée pour vous, soit un tunnel existant que vous avez créé dans la Console.
Vous avez besoin de :
tnl_...). Le provisionnement manuel part toujours d'un tunnel créé dans la Console ; vous aurez également besoin de son jeton de tunnel et de son domaine de tunnel.workspace:manage_tunnels.helm et kubectl. L'onglet Sans accès programmatique utilise également openssl (1.1.1 ou ultérieur).api.anthropic.com (443 TCP) et le tunnel edge (7844 TCP et UDP). Consultez les exigences réseau complètes.gateway.config.routes. Si vous n'en avez pas encore, utilisez le serveur d'exemple.Si vous n'avez pas de serveur MCP disponible pour les tests, utilisez ce serveur minimal :
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 }
EOFLes étapes d'installation qui suivent indiquent où ajouter la route correspondante.
Le composant de configuration échange le jeton de ServiceAccount projeté du cluster via votre règle de fédération, récupère le jeton de tunnel, génère une CA et un certificat serveur, et enregistre la CA auprès d'Anthropic. Un CronJob quotidien renouvelle le certificat serveur selon les besoins, de sorte que vous ne manipulez aucun secret à la main.
Configurer la Workload Identity Federation pour le cluster
Suivez Utiliser WIF avec Kubernetes pour enregistrer l'émetteur OIDC de votre cluster et créer une règle de fédération. Le composant de configuration s'exécute sous son propre ServiceAccount dans l'espace de noms de la release ; le nom exact suit la convention fullname de Helm, donc pour tout nom de release autre que mcp-tunnel, exécutez helm template <release> ... | grep -A2 'kind: ServiceAccount' pour le confirmer avant de créer la règle. Le reste de ce guide suppose le nom de release mcp-tunnel dans l'espace de noms mcp-tunnel, où le ServiceAccount est mcp-tunnel-setup.
| Champ | Valeur |
|---|---|
| Subject | system:serviceaccount:mcp-tunnel:mcp-tunnel-setup |
| Audience | api.anthropic.com (la valeur par défaut du chart ; sans schéma) |
| Scope | workspace:manage_tunnels |
L'audience par défaut du chart est api.anthropic.com sans schéma, mais le formulaire de règle de fédération de la Console suggère https://api.anthropic.com. Les deux doivent correspondre octet par octet, sinon l'authentification échoue. Définissez soit l'audience de la règle sur api.anthropic.com, soit api.wif.audience dans values.yaml sur https://api.anthropic.com.
Si le tunnel se trouve dans un espace de travail autre que celui par défaut de l'organisation, ajoutez également le compte de service de la règle en tant que membre de cet espace de travail sous Settings > Workspaces (l'API Tunnels effectue l'autorisation en fonction des appartenances du compte de service aux espaces de travail).
Notez l'ID de la règle (fdrl_...) ; vous le définirez comme api.wif.federationRuleId.
Le CronJob quotidien de renouvellement de certificat utilise un ServiceAccount distinct (également dérivé du fullname Helm) mais n'appelle pas l'API Tunnels ; il renouvelle le certificat localement et n'a besoin que du RBAC Kubernetes, que le chart accorde. La règle de fédération n'a pas besoin de le couvrir.
Récupérer les valeurs par défaut
helm show values \
oci://us-docker.pkg.dev/anthropic-public-registry/charts/mcp-tunnel \
--version 2.0.1 > values.yamlConfigurer l'attachement du tunnel et les routes
Modifiez values.yaml et définissez les clés api.wif.* avec l'ID de la règle de fédération et l'ID de l'organisation, plus une entrée routes pour chaque serveur MCP en amont :
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:8080Avec ces routes, Claude atteint les serveurs à docs.<your-tunnel-domain> et search.<your-tunnel-domain>. Certaines distributions Kubernetes managées allouent le CIDR de Service en dehors des plages privées standard ; si vos routes ciblent des Services dans le cluster, ajoutez ici gateway.config.upstream.allowed_ips conformément à Validation des IP en amont.
Si vous utilisez le serveur MCP d'exemple, définissez plutôt routes sur echo: http://hello-mcp:9000.
Examiner les manifestes générés
Générez le rendu du chart et examinez la sortie conformément aux pratiques de vérification de votre organisation :
helm template mcp-tunnel \
oci://us-docker.pkg.dev/anthropic-public-registry/charts/mcp-tunnel \
--version 2.0.1 \
-n mcp-tunnel \
-f values.yaml > rendered.yamlInstaller
helm install mcp-tunnel \
oci://us-docker.pkg.dev/anthropic-public-registry/charts/mcp-tunnel \
--version 2.0.1 \
--namespace mcp-tunnel --create-namespace \
-f values.yamlLe composant de configuration s'exécute en tant que Job de hook pre-install Helm, donc helm install se bloque jusqu'à ce qu'il se termine. En cas de succès, Helm supprime automatiquement le Job. Si helm install échoue avec une erreur de hook, consultez Échecs d'authentification du composant de configuration.
Lorsque tunnel.id est vide, le composant de configuration crée le tunnel dans l'espace de travail ciblé par votre règle de fédération (l'espace de travail par défaut de l'organisation, sauf si vous définissez api.wif.workspaceId) et stocke son ID et son domaine dans le Secret mcp-tunnel. Trouvez le domaine dont vous aurez besoin pour la vérification sur la page de détail du tunnel dans la Console sous Manage > MCP tunnels, ou lisez-le depuis le Secret :
kubectl -n mcp-tunnel get secret mcp-tunnel \
-o jsonpath='{.data.tunnel-domain}' | base64 -dLa réexécution du composant de configuration (lors des mises à niveau ou de la rotation du jeton) réutilise l'ID de tunnel stocké dans ce Secret ; elle ne crée jamais un second tunnel.
Les valeurs api.wif.* sont des identifiants, pas des secrets, donc leur stockage dans les Secrets d'historique de release Helm ne présente pas de risque. Les données sensibles au repos sont le Secret mcp-tunnel créé par le composant de configuration, qui contient le jeton de tunnel et les clés privées TLS. Appliquez les pratiques standard de votre organisation pour la protection des Secrets Kubernetes à cet espace de noms.
Vérifiez de bout en bout depuis le côté d'Anthropic : utilisez https://<route>.<your-tunnel-domain>/<path> dans une session Managed Agent ou une requête à l'API Messages, où <route> est une clé de gateway.config.routes et <path> est le chemin servi par le serveur MCP en amont. Avec le serveur MCP d'exemple, il s'agit de https://echo.<your-tunnel-domain>/mcp. Consultez Utiliser les serveurs MCP tunnelisés pour la forme des requêtes.
Si cela échoue, vérifiez les journaux du pod (kubectl -n mcp-tunnel logs deploy/mcp-tunnel -c mcp-proxy et -c cloudflared) et consultez Dépannage.
Le trafic entrant vers le pod proxy est refusé par défaut (networkPolicy.ingress.enabled: true). Pour restreindre en plus le trafic sortant du pod, définissez networkPolicy.egress.enabled: true et renseignez networkPolicy.egress.mcpServers avec des sélecteurs de labels de pods ou des plages CIDR couvrant vos serveurs MCP en amont. Le trafic sortant de cloudflared vers le tunnel edge est autorisé séparément via networkPolicy.egress.cloudflaredEgressCIDRs.
Les champs sous gateway.config.* sont transmis au fichier de configuration du proxy. Les ajustements courants incluent upstream.allowed_ips, log_level et upstream.tls. Consultez la référence de configuration du proxy pour la liste complète des champs. Le chart définit toujours listen_addr, tls.cert_file et tls.key_file ; les définir dans gateway.config n'a aucun effet.
Par défaut, le chart projette un jeton de ServiceAccount Kubernetes pour le composant de configuration. Pour utiliser un jeton provenant d'un autre fournisseur d'identité (tel que SPIFFE, Vault ou un sidecar de SDK cloud), montez-le avec setup.extraVolumes et setup.extraVolumeMounts. Ensuite, faites pointer api.wif.tokenFile vers le chemin de montage. Le chart définit ANTHROPIC_IDENTITY_TOKEN_FILE sur ce chemin, et le composant de configuration lit le jeton à partir de là.
Passez toujours --version à helm upgrade afin de ne pas récupérer un chart plus récent de manière inattendue.
Le chart 2.0.0 déplace l'ID de tunnel de api.wif.tunnelId vers tunnel.id. Avant la mise à niveau, modifiez votre values.yaml : déplacez la valeur tnl_... vers tunnel.id et supprimez api.wif.tunnelId. Laisser tunnel.id non défini est sans danger (le composant de configuration réutilise l'ID de tunnel déjà stocké dans le Secret mcp-tunnel lors de la réexécution), mais le déplacement explicite garde votre values.yaml exact. Mettez également à jour la portée de votre règle de fédération de org:manage_tunnels vers workspace:manage_tunnels dans la Console.
Pour les modifications de routine telles que les routes, le nombre de réplicas ou la NetworkPolicy :
helm upgrade mcp-tunnel \
oci://us-docker.pkg.dev/anthropic-public-registry/charts/mcp-tunnel \
--version 2.0.1 \
-n mcp-tunnel \
-f values.yamlMaintenez un values.yaml complet plutôt que de vous appuyer sur --reuse-values. Le comportement de fusion en profondeur de Helm peut échouer silencieusement à supprimer les routes supprimées.
Avec l'accès programmatique, incrémentez tunnel.tokenVersion dans values.yaml et effectuez la mise à niveau avec --set setup.force=true. Le composant de configuration ne se réexécute lors des mises à niveau que lorsqu'il y est forcé :
helm upgrade mcp-tunnel \
oci://us-docker.pkg.dev/anthropic-public-registry/charts/mcp-tunnel \
--version 2.0.1 \
-n mcp-tunnel \
-f values.yaml \
--set setup.force=trueLe composant de configuration s'authentifie avec la 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 le 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-tunnelCliquer sur Rotate token invalide immédiatement le jeton actuel. Tant que le Secret n'est pas mis à jour et que le déploiement progressif n'est pas terminé, tout pod qui redémarre avec l'ancien jeton (éviction, drainage de nœud, OOM) ne peut pas se reconnecter. Mettez à jour le Secret rapidement après la rotation ; pour des exigences de disponibilité plus strictes, utilisez l'accès programmatique afin que le chart gère la rotation de manière atomique.
Le chart fournit l'automatisation, mais vous restez responsable de la surveillance de l'expiration et de la confirmation que le renouvellement se termine.
Avec l'accès programmatique, le renouvellement de certificat est automatique. Le chart déploie un CronJob (nommé d'après le fullname Helm, avec le suffixe -cert-renew) qui exécute setup renew-cert quotidiennement (à serverCert.cronSchedule, par défaut 0 0 * * * UTC). Le job est sans effet sauf si le certificat est à moins de serverCert.renewBefore de l'expiration (30 jours par défaut). Le renouvellement est local : le job signe un nouveau certificat avec la CA déjà stockée dans le Secret, n'effectue aucun appel API et n'a besoin que du RBAC Kubernetes accordé par le chart. Le proxy recharge à chaud le certificat depuis le montage du Secret, donc aucun redémarrage du Deployment n'est nécessaire.
Sans accès programmatique, il n'y a pas de CronJob. Depuis l'intérieur du répertoire mcp-tunnel/ que vous avez conservé après l'installation, signez un nouveau certificat serveur avec la CA existante (ne régénérez pas la 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 -Le proxy recharge à chaud le certificat depuis le montage du Secret.
Attachez un serveur MCP en amont à un Managed Agent ou à l'API Messages.
Conseils de durcissement, rotation des identifiants et réponse aux compromissions.
Diagnostiquez les problèmes de connectivité, de TLS et de routage.
Was this page helpful?