MCP 隧道
安全地将 Claude 连接到私有网络中运行的 MCP 服务器,无需开放入站端口或将服务暴露到公共互联网。
MCP 隧道允许您将 Claude 连接到私有网络内部运行的 Model Context Protocol(MCP)服务器。流量通过仅出站连接传输,因此您无需开放入站防火墙端口、将服务暴露到公共互联网,或在源站允许 Anthropic 的 IP 范围。
MCP 隧道目前处于测试阶段(研究预览)。申请访问权限 即可试用。它们以"按现状"方式提供,不附带任何正常运行时间、支持或连续性承诺,并且依赖于对底层传输不做可用性承诺的第三方网络提供商(Cloudflare)。Anthropic 可能随时修改或终止 MCP 隧道。
有关零数据保留和 HIPAA BAA 资格,请参阅 API 和数据保留。
工作原理
隧道部署是在您网络中运行的两个组件的小型技术栈:
- **cloudflared:**隧道代理。它发起仅出站连接到 Anthropic 运营的隧道边缘,并将 Anthropic 的加密流量传输到您的代理。
- **Proxy:**Anthropic 的路由组件。它终止内部 TLS,验证上游 IP 是否在允许范围内,并根据主机名将每个请求路由到正确的上游 MCP 服务器。
您公开的每个 MCP 服务器都会获得一个隧道域名下的主机名(例如,docs.<your-tunnel-domain>)。您可以将这些主机名附加到控制台中的 Managed Agent 会话,或通过 MCP 连接器 将其传递给 Messages API。
前提条件
在部署之前,请确保您拥有:
- 部署目标:Kubernetes 集群,或安装了 Docker 和 Docker Compose 的虚拟机。
- 在 Claude 控制台中创建的隧道。参见 创建隧道。
- 一种让您的技术栈向 Tunnels API 进行身份验证的方式。选择以下方式之一:
- **编程访问(推荐)。**在创建隧道时设置 Workload Identity Federation。您的技术栈从身份提供商获取短期 API 令牌、获取隧道令牌,并自动生成和注册 CA 证书。需要管理联邦规则的权限、已注册的 OIDC 颁发者,以及具有
org:manage_tunnels范围的联邦规则。 - **手动方式。**自行提供静态凭据:从控制台获取的隧道令牌和由您在那里注册的 CA 签名的服务器证书。参见 获取连接详情 和 添加 CA 证书。
- **编程访问(推荐)。**在创建隧道时设置 Workload Identity Federation。您的技术栈从身份提供商获取短期 API 令牌、获取隧道令牌,并自动生成和注册 CA 证书。需要管理联邦规则的权限、已注册的 OIDC 颁发者,以及具有
- 一个或多个 MCP 服务器在您的私有网络中运行。
- 如 网络要求 中所列的出站连接。
网络要求
| 组件 | 目标 | 端口 / 协议 | 何时 |
|---|---|---|---|
| Setup | api.anthropic.com | 443 TCP | 配置和令牌轮换 |
| cloudflared | 隧道边缘(198.41.192.0/19、2606:4700:a0::/44) | 7844 TCP 和 UDP | 持续 |
| Proxy | 您的上游 MCP 服务器 | 按配置 | 持续 |
安全模型
安全层
三个独立的层保护每个请求:
| 层 | 防护对象 |
|---|---|
| Anthropic 与传输提供商之间的外部 mTLS,带 IP 验证 | 未授权客户端访问隧道 |
| Anthropic 后端到代理的内部 TLS | 传输提供商或任何网络中间人对载荷的检查 |
| 每个 MCP 服务器上的 OAuth | 经过隧道身份验证的流量对 MCP 工具的未授权使用 |
隧道传输运行在 Cloudflare 的网络上。由于代理使用只有您持有的证书终止内部 TLS,Cloudflare 无法读取请求或响应载荷。Anthropic 在注册 CA 证书之前不会连接到隧道,因此不存在载荷未加密通过 Cloudflare 的配置情况。Cloudflare 确实会接收连接元数据;参见 传输提供商可以观察到的内容。
共担责任模型
| Anthropic 负责 | 您的组织负责 |
|---|---|
| 隧道访问控制 | 通过隧道传输的所有内容和流量,以及遵守适用的第三方可接受使用政策(包括 Cloudflare 的) |
| 在连接到代理之前验证您的 CA 证书 | 遵守这些页面上的部署指南 |
| 确保 Claude 只向您组织拥有的隧道发送请求 | 保护隧道令牌和 TLS 私钥 |
| 管理服务器证书并在过期前续期 | |
| 在每个 MCP 服务器上配置 OAuth | |
| 限制代理和 MCP 服务器的网络访问 | |
| 如果怀疑泄露,通知 Anthropic |
如果攻击者获取了您的隧道令牌和一个 TLS 私钥,他们可以冒充您的代理并读取 MCP 请求载荷。请将两者视为高价值密钥。有关加固指南,请参阅 MCP 隧道安全。
传输提供商可以观察到的内容
Cloudflare 提供出站传输。它无法读取 MCP 请求或响应载荷,但会接收以下连接元数据:
- 运行 cloudflared 的主机的出口 IP 地址
- cloudflared 主机指纹
- 连接时间和字节量
- 分配给您的隧道的
*.tunnel.anthropic.com子域名
Anthropic 与 Cloudflare 的协议限制了 Cloudflare 对此遥测数据的使用。Cloudflare 在此研究预览中作为子处理者。
部署隧道
如果您是 MCP 隧道的新用户,请从快速入门开始,在本地获取一个可用的隧道,然后再配置生产部署。
获取可用隧道的最短路径:使用示例 MCP 服务器的 Docker Compose。
使用 Anthropic Helm chart 在 Kubernetes 集群上安装。
使用 Docker Compose 在虚拟机上安装。
选择指南:
- 部署目标
- Helm:部署到 Kubernetes 时使用。
- Docker Compose:用于单台主机或本地测试。
- Setup 身份验证
- 编程访问(通过 Workload Identity Federation):当您有 OIDC 身份提供商(如 Kubernetes 集群、云 IAM 或 SPIFFE)时使用。
- 手动凭据:当您没有身份提供商或正在测试时使用。
使用隧道 MCP 服务器
一旦您的隧道处于活跃状态(具有活跃的 CA 证书且您的技术栈已连接),路由的 MCP 服务器即可从 Claude Managed Agents 和 Messages API 访问。
通过控制台创建的 MCP 隧道不能作为 claude.ai 中的连接器使用。
在两种情况下,隧道将加密流量传输到您的 MCP 服务器,但不对服务器进行身份验证。如果上游服务器需要自身的身份验证(OAuth、bearer 令牌),请以与任何其他 MCP 服务器相同的方式提供;它与隧道无关。
Managed Agents(控制台)
- 在 Managed Agents > Sessions 中,创建会话并选择 Create new agent,以便编辑 MCP 服务器列表。
- 点击 + MCP Server 并打开下拉菜单。会话工作区中具有至少一个活跃证书的隧道会出现在列表顶部,位于公共连接器目录之上。
- 选择隧道并提供 Subdomain(您的代理将其路由到特定 MCP 服务器)和 Path(上游服务器期望的路径)。Resolves to 行显示确切的 URL。
Messages API
在 mcp_servers 数组中传递路由的服务器 URL,方式与任何其他远程 MCP 服务器相同。主机为 <subdomain>.<your-tunnel-domain>;path 是上游 MCP 服务器提供的路径(代理原样转发)。FastMCP 的 streamable-http 传输默认为 /mcp;其他服务器可能在 / 或其他路径上提供服务。请求体和 anthropic-beta 头遵循标准 MCP 连接器 格式;只有 url 是隧道特定的。使用创建隧道的工作区的 API 密钥(控制台 Settings > API keys)。
curl https://api.anthropic.com/v1/messages \
-H "Content-Type: application/json" \
-H "X-API-Key: $ANTHROPIC_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "anthropic-beta: mcp-client-2025-11-20" \
-d '{
"model": "claude-opus-4-7",
"max_tokens": 1000,
"messages": [{"role": "user", "content": "Use the hello tool to greet tunnel."}],
"mcp_servers": [
{
"type": "url",
"url": "https://echo.YOUR_TUNNEL_DOMAIN_HERE/mcp",
"name": "echo"
}
],
"tools": [{"type": "mcp_toolset", "mcp_server_name": "echo"}]
}'
import anthropic
client = anthropic.Anthropic()
response = client.beta.messages.create(
model="claude-opus-4-7",
max_tokens=1000,
messages=[{"role": "user", "content": "Use the hello tool to greet tunnel."}],
mcp_servers=[
{
"type": "url",
"url": "https://echo.YOUR_TUNNEL_DOMAIN_HERE/mcp",
"name": "echo",
}
],
tools=[{"type": "mcp_toolset", "mcp_server_name": "echo"}],
betas=["mcp-client-2025-11-20"],
)
print(response)
import Anthropic from "@anthropic-ai/sdk";
const anthropic = new Anthropic();
const response = await anthropic.beta.messages.create({
model: "claude-opus-4-7",
max_tokens: 1000,
messages: [{ role: "user", content: "Use the hello tool to greet tunnel." }],
mcp_servers: [
{
type: "url",
url: "https://echo.YOUR_TUNNEL_DOMAIN_HERE/mcp",
name: "echo"
}
],
tools: [{ type: "mcp_toolset", mcp_server_name: "echo" }],
betas: ["mcp-client-2025-11-20"]
});
console.log(response);