Cloudflare Gateway 通过协议级特征识别 MCP 流量,安全团队可据此发现影子 MCP 流量、强制门户访问白名单、阻断直连。
大多数公司在设计资源权限时都以人类用户为中心。一位高级工程师可能有能力部署到生产环境、查询敏感数据库或撤销其他用户的访问权限。这些特权伴随着风险,但这种风险传统上受到两个假设的限制:工程师会运用人类判断力,而且工程师只能以人类的速度行事。
工程师在看到意外结果时通常会停下来重新考虑自己的行为。任何人在一天之内能够点击、输入和审查的内容都是有限的。AI 智能体的引入改变了这两个阈值。它们的行为是不确定的,而且可以无限次地重复同一操作(或调用同一工具),不会疲劳也不会停下来休息。一个看似合理但错误的决策可以在人类注意到之前变成数千次错误操作。
今天,我们宣布了新的 Cloudflare One 功能,可以识别和检查 MCP 流量,显示哪些用户和服务器正在生成流量,并控制管理网络路径上的直接连接。结合 MCP Server Portals,这些控制措施帮助管理员了解智能体是否使用了批准的路径,或者以某种方式绕过了它。
Model Context Protocol(MCP)服务器为智能体提供了一种通用方式来发现和调用由第三方 SaaS 产品、内部应用程序和 API 支持的工具。底层权限可能是熟悉的;改变的是谁做出每个决策,以及错误决策传播的速度有多快。
将智能体连接到这些工具只需要一行配置。员工可以将 Claude Code、Codex、Cursor、OpenCode、VS Code 或任何 AI 开发工具指向 MCP 服务器,而无需检查它是否已获得批准。生成的流量没有明显的特征。Model Context Protocol 不使用确定的主机名,也不要求路径中包含 /mcp,因此直接连接看起来可能与任何其他 HTTPS API 调用无异。
为了解释这些控制措施如何协同工作,我们先从工具调用的结构及其暴露的信息开始。然后,我们将比较安全团队可以采取行动的三个位置:客户端内部、网络层面和 MCP 服务器端。接下来,我们将展示 Cloudflare Gateway 如何利用协议信号来发现影子 MCP 流量,并强制对可信 MCP 服务器只能通过 MCP Portal 进行访问。
同一个 MCP 工具调用在系统中经历三个阶段。在客户端内部,它是对一组参数调用工具的决策。在网络上,它是一个携带 JSON-RPC 消息的 HTTP 事务。在服务器端,它变成对工具处理程序的调用,该处理程序可能读取数据、更改状态或完成其他操作。
考虑一个想知道奥斯汀天气的智能体。远程 MCP 请求可能如下所示:
POST /mcp HTTP/1.1
Host: tools.example.com
Authorization: Bearer <access-token>
Content-Type: application/json
MCP-Protocol-Version: 2026-07-28
Mcp-Method: tools/call
Mcp-Name: get_weather
{
"jsonrpc": "2.0",
"id": 42,
"method": "tools/call",
"params": {
"name": "get_weather",
"arguments": {
"city": "Austin"
}
}
}
这个请求中包含多个有用的信号。主机名和路径标识目标。授权头携带凭据,用于在服务器需要时对调用者进行身份验证。头信息 MCP-Protocol-Version 标识协议版本,而 Mcp-Method 和 Mcp-Name 在新的无状态协议中公开操作和工具。JSON-RPC 信封重复了方法,给予请求一个 ID,客户端可以用它来匹配响应,并在 params 中携带工具参数。
参数是最敏感的部分。它们可能包含搜索查询、源代码、客户数据,或用于创建工单或更改基础设施等操作的指令。工具名称说明智能体打算调用什么;参数说明它将发送什么数据以及希望服务器执行什么操作。
如果调用成功,服务器返回一个带有相同 ID 和工具结果的 JSON-RPC 响应。该响应也可能包含敏感数据。请求检查可以在执行之前阻止不安全的操作,而响应检查和日志记录则显示工具返回给智能体的内容。
该请求为安全团队提供了三个观察或控制调用的位置。
客户端钩子可以在模型选择工具之后、客户端序列化请求之前运行。从那里,它可以看到目标服务器、工具名称和参数,而无需解密网络流量。
这是请求链中行使控制权的最早阶段。客户端可以拒绝不在允许列表中的服务器,要求用户确认敏感操作,或在数据离开设备之前从参数中移除数据。它还可以覆盖本地 stdio(又称本地)MCP 服务器,这些服务器从不产生网络流量。
这带来了标准化挑战。为了使安全团队从中受益,他们需要在员工使用的每个客户端中重现其控制措施。客户端控制措施在组织同时管理客户端和设备时效果最佳,但一个客户端的遥测数据永远不会是 MCP 使用情况的完整清单。
安全 Web 网关可以在请求离开客户端后观察 HTTP 请求。通过 TLS 解密,它可以将请求与用户和设备关联,检查目标和协议头,并应用策略,而不依赖于特定的 MCP 客户端。
网络层具有最广泛的视角来检测管理路径上的远程 MCP 流量。它可以识别对批准 Portal 外部服务器的直接连接,并在请求到达目标之前阻止它们。在支持数据丢失防护扫描的地方,代理还可以检查 JSON-RPC 方法和参数中是否有敏感数据。但是,代理无法看到本地 stdio 调用或网络外流量。
服务器具有最丰富的执行上下文。它已对调用者进行了身份验证,解析了 MCP 消息,将 get_weather 解析为处理程序,并根据工具的输入模式验证了提供的参数。这是请求在工具运行之前可以被拒绝的最后一点。
Agents SDK 处理程序或类似的服务器中间件可以授权调用者使用特定工具,应用速率限制,检查参数,并记录结果。服务器应在调用处理程序之前执行这些检查,特别是对于写入数据或触发外部操作的工具。仅在执行后记录可以解释发生了什么,但它无法阻止发生。
Cloudflare 的 WriteGuard 在我们的内部 MCP 服务器上使用此模式。每个工具都有一个风险层级和一个启用或禁用状态。WriteGuard 可以让读取请求保持不变,向允许的写入添加智能体属性和审计事件,或在处理程序运行之前阻止关键操作。因为控制存在于服务器端,最终用户无法通过切换客户端或禁用本地钩子来绕过它。
虽然服务器端控制仅保护实现它们的服务器,但客户端和服务器具有最佳的请求深度。网络可以看到最广泛的远程连接集。将这些控制措施一起使用,可以在敏感数据离开设备之前阻止它,发现未管理的 MCP 流量,并在工具执行之前拒绝未经授权的操作。
网络控制点具有最广泛的覆盖范围,但首先必须将 MCP 与普通 HTTPS 流量区分开来,用户必须运行代理,并且 MCP Server(或 Portal)必须验证连接中使用了代理。
Cloudflare One 提供了该链条的网络部分。Cloudflare One Client 将来自管理设备的流量通过 Gateway 发送。Gateway 可以在协议层对 MCP 请求进行分类,并区分流量是从 MCP Portal 发起的,还是在批准的控制之外进行的。管理员可以报告或阻止不遵循批准路径的连接。这个过程首先从可靠地识别请求开始。
我们第一种查找 MCP 流量的方法使用 GraphQL Analytics API 在 Gateway HTTP 日志中搜索包含 mcp 的主机名和常见路径(如 /mcp 或 /sse)。我们的 MCP 流量检测教程包含该查询。它还解释了如何为 MCP JSON-RPC 方法创建数据丢失防护模式,如请求体中的 initialize、tools/call 和 resources/read。
这些信号对于查找来自旧客户端的流量和提供历史可见性仍然有用,但它们非常基础。它们会漏掉位于普通 URL(如 https://tools.example.com/api)的 MCP 服务器,这并不罕见。
而且它们可能匹配到某个恰好在主机名或路径中使用了 mcp 的无关服务(虽然不太可能,但我们确实见过这种情况)。对于符合规范的 Streamable HTTP 客户端,协议头是一个更精确的信号。MCP 2025-11-25 规范要求客户端在初始化后的每个 HTTP 请求中包含 MCP-Protocol-Version。MCP 2026-07-28 规范更进一步,要求在每个 POST 请求中都包含它。
但这并不意味着这个头信息是一个完整的检测器。旧版客户端的初始请求可能不包含它,早于 2025-06-18 的协议版本没有定义它,而本地的 stdio、自定义传输或不符合规范的流量可能永远不会携带它。它的存在是 MCP 的强烈正向指标;它的缺失并不能证明某个请求不是 MCP。
协议在网络层面的识别难度正在降低
旧版 MCP 流程以一个不包含 MCP-Protocol-Version HTTP 头的 initialize 请求开始,因此网络控制可能无法仅凭头信息对先前未知端点的第一个请求进行分类。信号在客户端和服务器完成初始化后才出现。
后续的工具调用看起来像这样:
POST /api HTTP/1.1
Host: tools.example.com
Content-Type: application/json
MCP-Protocol-Version: 2025-11-25
{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"get_weather"}}
MCP 2026-07-28 规范大幅改变了这个模型。核心协议是无状态的;它完全移除了初始化握手,将协议版本和操作信息放到每个请求中:
POST /mcp HTTP/1.1
Host: tools.example.com
Content-Type: application/json
MCP-Protocol-Version: 2026-07-28
Mcp-Method: tools/call
Mcp-Name: get_weather
{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"get_weather"}}
Mcp-Method 和 Mcp-Name 头信息让普通的 HTTP 基础设施无需解析请求体就能识别操作。负载均衡器可以路由请求,限流器可以区分 tools/list 和 tools/call,安全产品可以在每个请求上获得更多信息。
这些协议信号让 Cloudflare Gateway 有了一些具体的东西可以评估,而不依赖于 MCP 外观的 URL 列表。
Shadow MCP 和 approved-path bypass 是两个不同的问题
一旦 Gateway 能够识别 MCP 流量,你就可以评估给定连接对你的安全态势意味着什么。
Shadow MCP 是指向组织尚未批准的服务器的连接。员工在代码仓库、产品指南或同事消息中找到该服务器,并直接将其添加到 MCP 客户端。安保团队不知道它暴露了哪些工具,也不知道员工向它发送了什么数据。
Portal bypass 则不同:它始于一个已批准的服务器——组织已将其放入 MCP Portal——但员工直接连接到这个服务器的上游 URL,跳过 Portal 的 Access 策略、精选工具目录、数据丢失防护和工具级审计追踪。
Gateway 是在托管网络路径上控制 shadow MCP 的主要手段;它识别经过 TLS 解密的 MCP 流量,显示目标地址和用户,并可以应用策略。Portal bypass 需要这种网络控制,加上一个能够拒绝直接请求的上游来源,无论是 Access 策略、源 IP 限制,还是由 MCP 服务器本身发起的企业授权机制。
在 Gateway 中检测 MCP 流量
对于已经采用带有 TLS 检查的 Cloudflare Gateway 的客户,我们正在添加一个检测启发式方法,为每个被检查的请求回答一个简单的问题:这是 MCP 流量吗?
对于基于会话的 Streamable HTTP 连接,MCP 客户端在初始化后发送 MCP-Protocol-Version 头。Gateway 在每个 TLS 解密的请求上检查该头,并根据我们每天在穿越 Cloudflare 网络的数百万请求中观察到的模式对流量进行分类。该分类识别 MCP 协商和代理到某个主机名,而不依赖于预先知道特定的主机或 URL。
从今天开始,所有 Cloudflare Zero Trust 客户都可以在其 Gateway HTTP 日志中看到 MCP 流量的指示,并可以使用一个新的 Gateway 选择器明确地阻止或允许该流量:
experimental.is_mcp == true
该选择器是一个布尔值。如果 Gateway 在 TLS 解密的请求上检测到 MCP-Protocol-Version 头,该值为 true,管理员可以在 Allow 或 Block 策略中使用它,而无需维护自己的 MCP 外观域名列表。
加密的直连流量必须先经过 TLS 解密,Gateway 才能检查这些头信息,而本地的 stdio 服务器、离网连接、"不解密"流量以及从不穿越 Gateway 的请求仍然不在此范围内。
在整个网络中可视化 MCP 流量
今天,我们引入了一个专用的 MCP 流量仪表板,显示哪些主机在你的网络内提供 MCP 流量、哪些用户生成了该流量,以及请求是通过 Cloudflare MCP Portal 还是完全绕过它们。

可配置时间窗口内的 MCP 请求总数、独立用户数和独立服务器数
随时间变化的 MCP 服务器及其各自的请求计数
按入口类型划分的流量明细,将 MCP Portal 流量与直接设备客户端连接分开
你的 Portal 外部发现的最多的 MCP 服务器,这是最重要的 shadow MCP 流量
按 MCP 请求量排名的顶级用户

管理员可以按特定服务器、用户或入口类型进行过滤,并直接导航到按相关主机或用户过滤的 Gateway HTTP 日志进行深入调查。

将发现的服务器纳入 MCP Portal
MCP 发现功能将未知流量转化为可供管理员调查的列表。当组织批准其中一个服务器后,可以将其置于 Cloudflare MCP server portal 之后。Portal 为员工提供一个托管端点,并向上游服务器前置 Access 身份、精选工具目录和日志记录。管理员可以通过 Portal 或针对单个服务器,路由兼容的上游调用通过 Gateway 以应用 HTTP 策略、可预测的出口和数据丢失防护。工具活动也可以通过 Logpush 导出。发现仪表板可以区分使用 Portal 的请求和直接连接到同一服务器的请求。
这创建了一条从发现到治理的路径:找到服务器、决定是否批准它、将批准的使用移到 Portal 之后,并调查继续绕过它的流量。最后一步很重要,因为未批准的服务器和绕过已批准服务器是两个不同的问题。
强制执行仅 Portal 访问
我们正在向 Gateway Network 和 HTTP 策略添加流量源选择器,让管理员能够根据流量是否来自 MCP Portal 来编写规则控制 MCP 流量。
当 MCP Portal 流量通过 Gateway 时,它携带一个 mcp_portal 流量源,这让策略能够区分 Portal 代理的请求和员工的直接连接。基线执行规则如下:
experimental.is_mcp == true and not traffic.onramp in ("mcp_portal")
Action: Block

任何未通过 Portal 到达的检测到的 MCP 流量都会被阻止;通过 Portal 的流量不受影响。对于希望先观察后执行的组织,流量源和 MCP 检测现已存在于解密流量的 HTTP 日志中,因此你可以监控代理流量的行为,而无需制定策略。
更多 MCP 服务器现在可以使用受治理的路径
只有当批准路径能够连接到员工实际需要的大量服务器时,它才有价值。
早期的 MCP 规范推荐动态客户端注册,即客户端在没有 OAuth 应用程序的情况下向授权服务器注册自己。许多常见的 OAuth 提供商使用不同的模型:它们要求管理员使用固定的客户端 ID、客户端密钥、回调 URL 和一组作用域注册一个应用程序。MCP 2026-07-28 也最近弃用了动态注册。
为了帮助缓解这个问题,MCP Portal 现在支持预注册的 OAuth 客户端。管理员可以配置手动 OAuth 凭据,向提供商注册仪表板中显示的回调 URL,并输入客户端凭据。Portal 在可用时发现标准 OAuth 元数据,当发现不可能时,管理员可以提供授权、令牌、撤销和颁发者端点。
每个用户仍然需要自行授权访问其上游数据源,而存储的客户端密钥仅用于获取更新后的工具列表和提示词列表。
手动 OAuth 支持现已覆盖 OAuth 实现的诸多变体。部分提供商要求自定义请求头、个人访问令牌或明确的客户端白名单,这些都属于不同的兼容性问题。我们将在未来几个月继续扩展 MCP Portal 的 OAuth 支持。
将私有 MCP 服务器纳入同一 Portal
公共 SaaS 工具只是企业 MCP 目录的一部分。企业所依赖的大部分敏感信息并非来自公共互联网,而是存在于公共或私有云基础设施中,或托管在本地,只有通过私有网络连接才能访问。
目前,MCP Portal 必须能够通过公共互联网解析并访问上游服务器。这意味着那些仅通过私有 DNS 或私有 IP 段可达的服务器,无法被 Portal 访问到。我们正在努力让 MCP Portal 通过 Cloudflare Gateway 路由连接私有服务器,并复用与其他私有应用相同的 Cloudflare One 网络。
私有服务器保持其私有主机名不变;Portal 通过 Cloudflare 的私有路由访问它,并将其工具与公共上游服务器并列展示;Access 策略、Portal 日志记录和工具控制继续在同一个入口处生效。
通过 Gateway 路由 Portal 流量还会为其打上 mcp_portal 流量来源标签,使 Gateway 策略能够区分 Portal 请求与员工直接连接。MCP 服务器的私有连接功能正在积极开发中,敬请关注更新日志。
Agents SDK 支持新的无状态模型
几周前,MCP 项目发布了 2026-07-28 规范,这是一次重大修订,用无状态的按请求模型取代了连接作用域的初始化。我们在《MCP 的下一代架构》中详细介绍了协议变更和迁移路径。
Cloudflare Agents SDK v0.20.0 支持 MCP 2026-07-28,既可作为客户端也可作为服务器。对于每个连接,客户端首先通过 server/discover 探测新的无状态协议;如果服务器不支持,客户端会在同一连接上继续执行传统的 initialize 握手。已有的 addMcpServer 调用无需单独的协议设置或单独的客户端。
在服务器端,createMcpHandler 可以从 Worker 中提供无状态工具、提示词、资源和引导功能,无需创建传输会话或 Durable Object:
import { McpServer } from "@modelcontextprotocol/server";
import { createMcpHandler } from "agents/mcp/server";
function createServer() {
return new McpServer({ name: "example", version: "1.0.0" });
}
export default {
fetch(request, env, ctx) {
return createMcpHandler(createServer)(request, env, ctx);
},
} satisfies ExportedHandler;
这种回退机制至关重要,因为协议迁移很少能一次性完成。新客户端仍需访问现有服务器,新服务器也仍需处理尚未迁移的客户端。在生态系统过渡期间,Agents SDK 同时支持两条路径。
从可见性入手,再封堵不该存在的通道
一个可行的 MCP 安全方案始于了解用户的流量特征、MCP 使用情况,并就批准的工具体系和访问方法达成共识。
首先,检查流经 Gateway 的 MCP 流量,将其目标地址与企业已批准的服务器进行比对。将更多已批准的服务器迁移到 MCP Portal 之后。
然后,强制执行你所能控制的边界。组合使用 MCP 检测条件与流量来源和目标条件来编写 Gateway 策略,阻止托管设备和站点发出的直接 MCP 连接,并尽可能将自托管的上游服务器限制为仅限 Portal 流量。
我们即将为 MCP 流量的可见性和控制添加更细粒度的功能,包括对特定工具使用的控制,以及对环境内所有 MCP 服务器(新出现的 MCP 服务器同样适用)的工具使用情况的新报告。
我们的 MCP 流量检测教程涵盖了当前 Gateway 日志中可用的主机名、路径和 JSON-RPC 启发式检测方法。随着新检测信号达到普遍可用,我们将更新文档并补充协议选择器的详细信息。