MCP 隧道故障排除
诊断 MCP 隧道部署中的连接、TLS、IP 验证和 OAuth 路由问题。
MCP 隧道是一项研究预览功能。申请访问权限 即可试用。
无法接受流量的隧道可能在三个层面失败;请按顺序诊断:到隧道边缘的出站连接、Anthropic 到代理的内部 TLS 握手,然后是上游路由和 IP 验证。
快速参考
| 症状 | 原因 | 修复方法 |
|---|---|---|
| 隧道不出现在智能体 + MCP Server 选择器中 | 选择器只列出会话工作区中具有至少一个活跃证书的隧道。 | 注册 CA 证书,或在创建隧道的工作区中打开会话。 |
调用者看到 HTTP 500;cloudflared 日志显示 No ingress rules were defined | cloudflared 没有本地目标。 | 向 cloudflared 服务添加 --url http://localhost:8080 和 network_mode: "service:mcp-proxy"。 |
代理日志显示 no route for host | tunnel_domain 与分配的域名不匹配,或编辑了 config.yaml 但未重启(docker compose restart mcp-proxy)。 | 将 tunnel_domain 设置为隧道详情页上显示的确切域名。 |
代理日志显示 IP validation failed: <ip> is not a private address | 上游解析到 RFC1918 之外。 | 参见 上游 IP 验证。 |
代理退出并显示 cannot unmarshal !!seq into map[string]string | routes 是 YAML 列表。 | 使用 routes: { name: http://host:port }。 |
代理退出并显示 open /data/tls.key: permission denied | 密钥权限为 0600;代理容器以非 root 用户运行。 | chmod 644 data/tls.key。 |
curl https://:8080 失败并显示 wrong version number | 预期行为;监听器是纯文本 WebSocket。TLS 在 WS 流内部进行。 | 改为通过 Managed Agent 或 Messages API 验证。 |
OAuth 在源 IP 允许列表后失败
当您的授权服务器的源 IP 允许列表阻止 Anthropic 后端访问 /token、/register 和发现端点时,OAuth 流程会失败。如果您不想将 Anthropic 的出口范围加入允许列表,可以通过隧道路由后端到后端的 OAuth 调用,同时将面向浏览器的 /authorize 端点保留在现有的公共主机名上。
为授权服务器添加代理路由
routes: mcp: http://your-mcp-server:8080 auth: http://your-auth-server:8080编辑
routes后重启代理(docker compose restart mcp-proxy,或helm upgrade)。提供分离端点的发现元数据
您的授权服务器的
/.well-known/oauth-authorization-server响应应将authorization_endpoint指向您现有的已允许主机名,其他所有内容指向隧道:{ "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"] }将 MCP 服务器指向隧道颁发者
您的 MCP 服务器的
/.well-known/oauth-protected-resource响应应将隧道主机名引用为其授权服务器:{ "resource": "https://mcp.<tunnel-domain>", "authorization_servers": ["https://auth.<tunnel-domain>"] }
使用此配置,用户的浏览器访问您现有主机名上的 /authorize(您的允许列表已允许),而 Anthropic 后端通过隧道访问 /token、/register 和发现文档。
Setup Job 身份验证失败
Helm setup Job 和 Compose setup 服务通过您的联邦规则交换 OIDC JWT 来向 Tunnels API 进行身份验证。当交换失败时,请参阅 Workload Identity Federation 参考中的 排查交换失败;失败模式(主题、受众、颁发者、JWKS、生命周期)是相同的。
Tunnels 特定原因:
- Chart 的默认受众为
api.anthropic.com(无协议前缀)。如果您的规则的受众为https://api.anthropic.com,请将api.wif.audience设置为匹配。 - 成功交换后 Tunnels API 返回
403意味着规则的范围不包含org:manage_tunnels,或规则的服务账户不是隧道工作区的成员。请设置范围并将服务账户添加到工作区。
Helm setup Job 作为 pre-install hook 运行。失败时,Job 会保留以供检查(kubectl logs job/mcp-tunnel-setup -n mcp-tunnel)。Helm 不管理 hook 资源,因此重试前请先删除:
helm uninstall mcp-tunnel -n mcp-tunnel
kubectl -n mcp-tunnel delete job mcp-tunnel-setup
隧道无法连接
首先检查 cloudflared 日志。常见原因:
TUNNEL_TOKEN缺失、过期或复制错误。- 防火墙阻止了到隧道边缘的 7844 端口出站 TCP/UDP。
cloudflared 也可能记录关于 UDP 接收缓冲区大小的警告;这是 QUIC 调优提示,不是错误。
证书错误
当 Anthropic 在内部 TLS 握手期间拒绝代理的证书时,代理会记录 tls handshake failed。请验证:
- 服务器证书未过期。
- 证书的 Subject Alternative Name 匹配
*.<tunnel-domain>。 - 签名 CA 已为此隧道在 Anthropic 注册。
有关完整的验证规则,请参阅 证书要求。
上游 IP 验证
为了 SSRF 防护,代理默认只拨号 RFC1918 私有范围内的地址(10.0.0.0/8、172.16.0.0/12、192.168.0.0/16)。仅支持 IPv4。
如果代理记录 IP validation failed: <ip> is not a private address,则上游主机名解析到了该范围之外。在 Kubernetes 上,某些托管发行版将 Service CIDR 分配在 RFC1918 之外;如果 kubectl get svc kubernetes -n default -o jsonpath='{.spec.clusterIP}' 返回的地址在私有范围之外,请查找集群的 Service CIDR 并添加。
如果地址是合法的,请将最小覆盖 CIDR 添加到 upstream.allowed_ips。设置 allowed_ips 会替换 RFC1918 默认值而非扩展它,因此请包含其他上游使用的私有范围:
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 only
避免在本地测试之外使用 0.0.0.0/0;它会完全禁用 SSRF 防护。