Solucionar problemas de túneles MCP
Diagnostica problemas de conectividad, TLS, validación de IP y enrutamiento de OAuth en una pila de túnel.
Una solicitud a través del túnel puede fallar en una de tres capas; diagnostícalas en orden: la conexión saliente hacia el borde del túnel, el TLS interno desde Anthropic hacia tu proxy, y luego el enrutamiento y la validación de IP hacia el servidor MCP upstream.
Referencia rápida
| Síntoma | Causa | Solución |
|---|---|---|
| El túnel no aparece en el selector + MCP Server del agente | El selector solo lista los túneles del espacio de trabajo de la sesión que tienen al menos un certificado activo. | Registra un certificado de CA, o abre la sesión en el espacio de trabajo en el que se creó el túnel. |
El llamador ve HTTP 500; los registros de cloudflared muestran No ingress rules were defined | cloudflared no tiene un destino local. | Agrega --url http://localhost:8080 y network_mode: "service:mcp-proxy" al servicio cloudflared. |
El proxy registra no route for host | tunnel_domain no coincide con el dominio asignado, o se editó config.yaml sin reiniciar. | Establece tunnel_domain con el dominio exacto que se muestra en la página de detalles del túnel y luego reinicia el proxy (docker compose restart mcp-proxy). |
El proxy registra IP validation failed: <ip> is not a private address | El servidor MCP upstream se resuelve fuera de RFC1918. | Consulta Validación de IP upstream. |
El proxy termina con cannot unmarshal !!seq into map[string]string | routes es una lista YAML. | Usa routes: { name: http://host:port }. |
El proxy termina con open /data/tls.key: permission denied | La clave es 0600; el contenedor del proxy se ejecuta sin privilegios de root. | chmod 644 data/tls.key. |
curl https://<proxy>:8080 falla con wrong version number | Es lo esperado; el listener es WebSocket en texto plano. El TLS ocurre dentro del flujo WS. | Verifica a través de un Managed Agent o la API de Messages en su lugar. |
Las siguientes secciones cubren fallos que necesitan más que una solución de una sola línea.
OAuth falla detrás de una lista de permitidos por IP de origen
Los flujos de OAuth fallan cuando la lista de permitidos por IP de origen de tu servidor de autorización impide que el backend de Anthropic alcance /token, /register y los endpoints de descubrimiento. Si prefieres no agregar a la lista de permitidos los rangos de salida de Anthropic, puedes enrutar las llamadas OAuth de backend a backend a través del túnel mientras mantienes el endpoint /authorize orientado al navegador en tu nombre de host público existente.
Agrega una ruta del proxy para el servidor de autorización
routes: mcp: http://your-mcp-server:8080 auth: http://your-auth-server:8080Reinicia el proxy después de editar
routes(docker compose restart mcp-proxy, ohelm upgrade).Sirve metadatos de descubrimiento con endpoints divididos
La respuesta
/.well-known/oauth-authorization-serverde tu servidor de autorización debe apuntarauthorization_endpointa tu nombre de host existente incluido en la lista de permitidos y todo lo demás al túnel:{ "issuer": "https://auth.<tunnel-domain>", "authorization_endpoint": "https://<your-allowlisted-host>/authorize", "token_endpoint": "https://auth.<tunnel-domain>/token", "registration_endpoint": "https://auth.<tunnel-domain>/register", "code_challenge_methods_supported": ["S256"] }Apunta el servidor MCP al emisor del túnel
La respuesta
/.well-known/oauth-protected-resourcede tu servidor MCP debe hacer referencia al nombre de host del túnel como su servidor de autorización:{ "resource": "https://mcp.<tunnel-domain>", "authorization_servers": ["https://auth.<tunnel-domain>"] }
Con esta configuración, el navegador del usuario accede a /authorize en tu nombre de host existente (que tu lista de permitidos ya autoriza), mientras que el backend de Anthropic alcanza /token, /register y los documentos de descubrimiento a través del túnel.
Fallos de autenticación del componente de configuración
El componente de configuración (Job de Helm o servicio setup de Compose) se autentica ante la API de Tunnels intercambiando un JWT de OIDC a través de tu regla de federación. Cuando el intercambio falla, consulta Solucionar problemas de un intercambio fallido en la referencia de Workload Identity Federation; los modos de fallo (subject, audience, issuer, JWKS, lifetime) son los mismos.
Causas específicas de los túneles:
- La audiencia predeterminada del chart es
api.anthropic.com(sin esquema). Si la audiencia de tu regla eshttps://api.anthropic.com, estableceapi.wif.audiencepara que coincida. - Un
403de la API de Tunnels después de un intercambio exitoso significa que el alcance de la regla no incluyeworkspace:manage_tunnels, o que la cuenta de servicio de la regla no es miembro del espacio de trabajo del túnel. Establece el alcance y agrega la cuenta de servicio al espacio de trabajo.
En Helm, el componente de configuración se ejecuta como un Job de hook pre-install. En caso de fallo, el Job se conserva para su inspección (kubectl logs job/mcp-tunnel-setup -n mcp-tunnel). Helm no administra los recursos de hooks, así que elimínalo antes de reintentar:
helm uninstall mcp-tunnel -n mcp-tunnel
kubectl -n mcp-tunnel delete job mcp-tunnel-setupEl túnel no se conecta
Revisa primero los registros de cloudflared. Causas comunes:
- El
TUNNEL_TOKENfalta, expiró o se copió incorrectamente. - Un firewall está bloqueando el tráfico TCP/UDP saliente en el puerto 7844 hacia el borde del túnel.
cloudflared también puede registrar advertencias sobre los tamaños del búfer de recepción UDP; esto es una sugerencia de ajuste de QUIC, no un error.
Errores de certificado
Cuando Anthropic rechaza el certificado del proxy durante el TLS interno, el proxy registra tls handshake failed. Verifica que:
- El certificado del servidor no haya expirado.
- El Subject Alternative Name del certificado coincida con
*.<tunnel-domain>. - La CA firmante esté registrada con Anthropic para este túnel.
Consulta los requisitos de certificados para ver las reglas de validación completas.
Validación de IP upstream
Para la protección contra SSRF, el proxy solo se conecta de forma predeterminada a direcciones en los rangos privados RFC1918 (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16). Solo se admite IPv4 para la conexión del proxy al upstream. (El rango de salida de cloudflared al borde en Requisitos de red es un salto diferente.)
Si el proxy registra IP validation failed: <ip> is not a private address, el nombre de host upstream se resolvió fuera de ese conjunto. En Kubernetes, algunas distribuciones administradas asignan el CIDR de Service fuera de RFC1918; si kubectl get svc kubernetes -n default -o jsonpath='{.spec.clusterIP}' devuelve una dirección fuera de los rangos privados, busca el CIDR de Service de tu clúster y agrégalo.
Si la dirección es legítima, agrega el CIDR más estrecho que la cubra a upstream.allowed_ips. Establecer allowed_ips reemplaza el valor predeterminado RFC1918 en lugar de extenderlo, así que incluye los rangos privados que usan tus otros servidores MCP upstream:
upstream:
allowed_ips:
- 10.0.0.0/8
- 172.16.0.0/12
- 192.168.0.0/16
- 127.0.0.0/8 # loopback, for local testing onlyWas this page helpful?