Why MCP traffic needs a new security model
Enterprise resource permissions were designed around human limitations. An engineer can deploy to production or query a sensitive database, but that access has traditionally been bounded by human judgment and human speed. Someone who sees an unexpected result will usually stop and reconsider. And no person can perform thousands of actions in a day.
AI agents remove both constraints. Their decisions are nondeterministic, and they can invoke the same tool indefinitely without fatigue. A plausible but incorrect decision can cascade into thousands of errors before anyone notices.

Model Context Protocol (MCP) servers give agents a standardized way to discover and call tools backed by SaaS products, internal applications, and APIs. The permissions beneath those tools are familiar; the change is in who makes each decision and how fast a bad choice can propagate. Connecting an agent to one of these tools can take a single line of configuration. An employee can point Claude Code, Codex, Cursor, OpenCode, VS Code, or any AI harness at an MCP server without approval. The traffic has no obvious shape: MCP does not require a fixed hostname or /mcp in the path, so a direct connection looks like any other HTTPS API call.
To close that gap, we're announcing new Cloudflare One capabilities to identify inspected MCP traffic, show which users and servers are generating it, and control direct connections on managed network paths. Combined with MCP Server Portals, these controls let administrators verify whether agents use an approved path or are bypassing it.
What an MCP tool call exposes
An MCP tool call takes three forms as it moves through a system. Inside the client, it is a decision to invoke a tool with arguments. On the network, it is an HTTP transaction carrying a JSON-RPC message. At the server, it becomes a call to a tool handler that may read data, change state, or perform an action.
Consider an agent querying weather in Austin. A remote MCP request looks like this:
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"
}
}
}
The request carries multiple signals. The hostname and path identify the destination; the authorization header carries the credential. The MCP-Protocol-Version header identifies the protocol version, while Mcp-Method and Mcp-Name expose the operation and tool in the stateless protocol. The JSON-RPC envelope repeats the method, supplies an id for matching responses, and carries tool arguments in params.
Arguments are the most sensitive element. They may contain a search query, source code, customer data, or instructions for state-changing actions like creating a ticket or modifying infrastructure. The tool name shows what the agent intends to call; the arguments show what data it will send and what action it wants performed. If the call succeeds, the server returns a JSON-RPC response with the same ID and the tool result — potentially containing sensitive data. Request inspection can block an unsafe action before execution; response inspection and logging reveal what the tool returned.
Three control points for an MCP request
Security teams can act at three distinct points in the request chain.
Inside the MCP client
A client hook runs after the model selects a tool but before serialization. It can see the destination server, tool name, and arguments without decrypting network traffic. This is the earliest stage for control: the client can deny servers not on an allowlist, require user confirmation for sensitive operations, or strip data from arguments before they leave the device. It can also govern local stdio MCP servers, which never generate network traffic.
The standardization challenge is significant. A security team must reproduce controls across every client employees use. Client-side policies work best when the organization manages both client and device, but telemetry from any single client gives an incomplete inventory of MCP usage.
At the device network boundary
A secure web gateway observes the HTTP request after it leaves the client. With TLS decryption, it can associate the request with a user and device, inspect the destination and protocol headers, and enforce policy independent of any particular MCP client. The network layer has the widest view of remote MCP traffic on managed paths. It can identify direct connections to servers outside an approved Portal and block them before they reach the destination. Where data loss prevention scanning is supported, a proxy can also examine JSON-RPC methods and arguments for sensitive data. Proxies cannot see local stdio calls or off-network traffic.
Before the MCP server invokes the tool
The server holds the richest execution context: it has authenticated the caller, parsed the MCP message, resolved get_weather to a handler, and validated arguments against the tool's input schema. This is the final point where a request can be denied before the tool runs. An Agents SDK handler or similar middleware can authorize the caller for the specific tool, apply rate limits, inspect arguments, and record the outcome. These checks must occur before handler invocation, especially for tools that write data or trigger external actions. Logging after execution explains what happened but cannot prevent it.
Cloudflare's WriteGuard applies this pattern across internal MCP servers. Each tool carries a risk tier and an enabled or disabled state. WriteGuard can pass reads through unchanged, add agent attribution and audit events to permitted writes, or block critical actions before their handlers run. Because control lives at the server, end users cannot bypass it by switching clients or disabling hooks.
Used together, these layers stop sensitive data before it leaves a device, detect unmanaged MCP traffic, and deny unauthorized operations before tool execution. The network control point has the broadest coverage, but it must distinguish MCP from ordinary HTTPS, require users to run a proxy, and have the MCP Server (or Portal) verify that proxy was used.
Cloudflare One provides the networking pieces. The Cloudflare One Client routes traffic from managed devices through Gateway, which classifies MCP requests at the protocol layer and distinguishes traffic initiated from an MCP Portal from connections that bypass approved controls. Administrators can report on or block non-conforming connections.
Why URLs alone cannot identify MCP
The first detection approach used the GraphQL Analytics API to search Gateway HTTP logs for hostnames containing mcp and paths like /mcp or /sse. The MCP traffic detection tutorial includes that query, plus DLP patterns for MCP JSON-RPC methods such as initialize, tools/call, and resources/read in request bodies.
Those signals remain useful for legacy clients and historical visibility, but they are crude. They miss an MCP server hosted at an ordinary URL like https://tools.example.com/api, which is not uncommon. They can also match unrelated services that happen to use mcp in a hostname or path. For conforming Streamable HTTP clients, the protocol header is more specific. The MCP 2025-11-25 specification requires clients to include MCP-Protocol-Version on every HTTP request after initialization. The MCP 2026-07-28 specification requires it on every POST request.
The header is not a complete detector, though. Initial requests from legacy clients may lack it, protocol versions before 2025-06-18 did not define it, and local stdio, custom transports, and nonconforming traffic may never carry it. Presence is a strong positive indicator; absence does not prove a request is not MCP.
Protocol evolution makes wire-level detection easier
Legacy MCP starts with an initialize request that omits the MCP-Protocol-Version header, so a network control may not classify the first request to an unknown endpoint from headers alone. The signal only appears after initialization completes. A later tool call resembles:
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"}}
The MCP 2026-07-28 specification changes the model substantially. The core protocol is stateless: it removes the initialize handshake entirely and places protocol version and operation on every request:
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"}}
The Mcp-Method and Mcp-Name headers let ordinary HTTP infrastructure identify the operation without parsing the body. Load balancers can route requests, rate limiters can distinguish tools/list from tools/call, and security products gain richer data on each request. These signals give Cloudflare Gateway concrete criteria to evaluate without relying on MCP-looking URL lists.
Two distinct threats hide inside MCP traffic
Once gateway logs can identify MCP traffic, the harder question is what a given connection means for your security posture. Cloudflare separates the problem into two categories that require different responses.
Shadow MCP is a connection to a server the organization never approved. An employee finds a server in a repository, a product guide, or a message from a colleague and adds it directly to their MCP client — the security team has no visibility into which tools that server exposes or what data employees send to it.
Portal bypass is the opposite failure mode. It starts with a server the organization did approve and placed in an MCP Portal, but an employee connects to its upstream URL directly, skipping the Portal's Access policy, curated tool catalog, data loss prevention, and tool-level audit trail.
Gateway is the primary control for shadow MCP on managed network paths: it identifies TLS-inspected MCP traffic, shows destination and user, and can apply policy. Portal bypass requires that network control plus an origin that rejects direct requests — an Access policy, source IP restriction, or an enterprise authorization mechanism initiated by the MCP server itself.
How Gateway flags MCP requests
For customers already running Cloudflare Gateway with TLS inspection, a new detection heuristic answers one question per inspected request: Is this MCP traffic?
For session-based Streamable HTTP connections, MCP clients send an MCP-Protocol-Version header after initialization. Gateway inspects that header on every TLS-inspected request and classifies traffic accordingly, using patterns observed across the millions of requests traversing the Cloudflare network daily. Classification identifies MCP negotiation and proxying to a hostname without requiring prior knowledge of the specific host or URL.
Starting today, all Cloudflare Zero Trust customers see indications of MCP traffic in Gateway HTTP logs and can explicitly block or allow that traffic with a new Gateway selector:
experimental.is_mcp == true
The selector is a boolean. If Gateway detects the MCP-Protocol-Version header on a TLS-inspected request, the value is true, and an administrator can use it in Allow or Block policies without maintaining a list of MCP-looking domains.
Direct encrypted traffic must pass through TLS decryption before Gateway can inspect these headers. Local stdio servers, off-network connections, Do Not Inspect traffic, and requests that never traverse Gateway remain outside this view entirely.
A network-wide view of MCP usage
Cloudflare is also introducing a dedicated MCP traffic dashboard showing which hosts serve MCP traffic inside your network, which users generate it, and whether requests go through your MCP Portals or bypass them.

The dashboard presents:
- Total MCP requests, unique users, and unique servers over a configurable time window
- MCP servers over time with per-server request counts
- Traffic breakdown by on-ramp, separating MCP Portal traffic from direct device client connections
- Top MCP servers seen outside your Portals — the shadow MCP traffic that matters most
- Top users by MCP request volume

Administrators can filter by server, user, or on-ramp type, and jump directly to Gateway HTTP logs filtered by host or user for deeper investigation.

From discovery to governance
The discovery dashboard turns unknown traffic into an investigable list. Once an organization approves a discovered server, it can place that server behind a Cloudflare MCP Portal. The Portal gives employees one managed endpoint and fronts the upstream server with Access identity, a curated tool catalog, and logging. Administrators can route compatible upstream calls through Gateway for HTTP policy, predictable egress, and data loss prevention — either across the whole Portal or for an individual server — and tool activity can be exported via Logpush.
The dashboard then distinguishes requests that use the Portal from direct connections to the same server. That creates a clear path: find the server, decide whether to approve it, move approved use behind the Portal, and investigate traffic that keeps going around it.
Enforcing Portal-only access
New Traffic Source selectors for Gateway Network and HTTP policies give administrators the fidelity to write rules based on whether traffic originated from an MCP Portal. When Portal traffic routes through Gateway, it carries an mcp_portal Traffic Source, so policy can distinguish Portal-proxied requests from direct employee connections. A baseline enforcement rule looks like this:
experimental.is_mcp == true and not traffic.onramp in ("mcp_portal")
Action: Block
Any detected MCP traffic that didn't arrive through a Portal gets blocked; Portal traffic is unaffected. Organizations that prefer observation over enforcement can use Traffic Source and MCP detection in HTTP logs for decrypted traffic without needing a policy at all.
OAuth clients join the governed path
An approved path is only useful when it connects to servers employees actually use. Earlier MCP specifications recommended Dynamic Client Registration, where a client registers itself without an OAuth application — but many common OAuth providers require an administrator-registered application with fixed client ID, client secret, callback URL, and scopes. MCP 2026-07-28 also recently deprecated dynamic registration.
MCP Portals now support pre-registered OAuth clients to cover this model. An administrator can configure manual OAuth credentials, register the callback URL shown in the dashboard with the upstream provider, and enter client credentials. The Portal discovers standard OAuth metadata when present; otherwise the administrator supplies authorization, token, revocation, and issuer endpoints manually.
Each user still authorizes access to their own upstream data sources, and the stored client secret is used only to fetch updated tool and prompt lists.
Some providers still require custom headers, personal access tokens, or explicit client allowlists — those remain separate compatibility problems. Cloudflare says OAuth support in MCP Portals will continue expanding in coming months.
Private upstreams get a path into Portals
Public SaaS tools are only part of an enterprise MCP catalog. Most secure information lives in public or private cloud infrastructure, or on-premise, reachable only through private network connectivity. Until now, an MCP Portal had to resolve and reach an upstream server over the public Internet, leaving private-DNS or private-IP servers out of reach.
Cloudflare is working to let MCP Portals connect to private servers through Gateway routing and the same Cloudflare One network used for other private applications. The private server keeps its private hostname; the Portal reaches it through Cloudflare's private routing and presents its tools beside public upstream servers; Access policy, Portal logging, and tool controls apply at the same front door.
Routing Portal traffic through Gateway also stamps it with the mcp_portal Traffic Source. Private connectivity for MCP servers is in active development; Cloudflare points to its Changelog for updates.
Agents SDK handles both protocol generations
The MCP project's 2026-07-28 specification replaces connection-scoped initialization with a stateless, per-request model. Cloudflare Agents SDK v0.20.0 supports that version as both client and server. For each connection, the client first probes for the new stateless protocol with server/discover; if the server doesn't support it, the client falls back to the legacy initialize handshake on the same connection. Existing addMcpServer calls work without separate protocol settings or separate clients.
On the server side, createMcpHandler can serve stateless tools, prompts, resources, and elicitation from a Worker without creating a transport session or 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;
That fallback matters because protocol migrations rarely happen at once. A new client still needs to reach an existing server, and a new server still needs to handle clients that haven't moved yet. The SDK supports both paths during the transition.
Visibility first, enforcement second
A workable MCP security program starts with understanding user traffic profiles and MCP usage, then aligning on an approved set of tools. Concretely: inspect MCP traffic traversing Gateway, compare destinations against your approved server list, and move approved servers behind MCP Portals.
Then enforce the boundary you can control. Compose Gateway policies using MCP detection conditions together with Traffic Source and Destination selectors to block direct MCP connections from managed devices and sites. Restrict self-hosted upstream servers to Portal traffic where possible.
Cloudflare will soon add more granular MCP visibility and control, including per-tool policy and new reporting on tool usage across all MCP servers in your environment — whether known or unknown to your security team. The MCP traffic detection tutorial covers the hostname, path, and JSON-RPC heuristics available in Gateway logs today; documentation will be updated with protocol selector details as the new signal reaches general availability.



