MCP 隧道目前处于研究预览阶段。申请访问权限以进行试用。
通过隧道的请求可能在三个层级之一失败;请按顺序进行诊断:到 tunnel edge(隧道边缘)的出站连接、从 Anthropic 到您的 proxy(代理)的 inner TLS(内部 TLS),然后是到 upstream MCP server(上游 MCP 服务器)的路由和 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 但未重启。 | 将 tunnel_domain 设置为隧道详情页面上显示的确切域名,然后重启代理(docker compose restart mcp-proxy)。 |
代理日志显示 IP validation failed: <ip> is not a private address | 上游 MCP 服务器解析到 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://<proxy>:8080 失败并显示 wrong version number | 这是预期行为;监听器是明文 WebSocket。TLS 发生在 WS 流内部。 | 请改为通过托管智能体或 Messages API 进行验证。 |
以下各节涵盖需要更详细修复方案的故障。
当您的授权服务器的源 IP 允许列表阻止 Anthropic 后端访问 /token、/register 和发现端点时,OAuth 流程会失败。如果您不想将 Anthropic 的出口 IP 范围加入允许列表,可以将后端到后端的 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 component(设置组件,即 Helm Job 或 Compose 的 setup 服务)通过您的联合规则交换 OIDC JWT 来向 Tunnels API 进行身份验证。当交换失败时,请参阅 Workload Identity Federation 参考文档中的排查交换失败问题;失败模式(subject、audience、issuer、JWKS、lifetime)是相同的。
隧道特有的原因:
api.anthropic.com(无协议前缀)。如果您的规则的 audience 是 https://api.anthropic.com,请设置 api.wif.audience 使其匹配。403,意味着规则的 scope 不包含 org:manage_tunnels,或规则的服务账号不是隧道所在工作区的成员。请设置 scope 并将服务账号添加到工作区。在 Helm 上,设置组件作为 pre-install hook Job 运行。失败时,该 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 缺失、已过期或复制错误。cloudflared 也可能记录有关 UDP 接收缓冲区大小的警告;这是 QUIC 调优提示,而非错误。
当 Anthropic 在内部 TLS 期间拒绝代理的证书时,代理会记录 tls handshake failed。请验证:
*.<tunnel-domain> 匹配。有关完整的验证规则,请参阅证书要求。
为了防止 SSRF(服务器端请求伪造),代理默认仅连接 RFC1918 私有范围内的地址(10.0.0.0/8、172.16.0.0/12、192.168.0.0/16)。代理到上游的连接仅支持 IPv4。(网络要求中的 cloudflared 到边缘的出口范围是另一个跃点。)
如果代理日志显示 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 默认值而非扩展它,因此请包含您的其他上游 MCP 服务器使用的私有范围:
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 防护。
Was this page helpful?