mcp · ai-governance · claude-code · revops
Cloudflare MCP Server Portals: Access, Not Intent
Cloudflare shipped a real MCP gateway: one endpoint, per-tool policy, per-user OAuth. It answers who may reach a tool. It does not answer why an agent called it.
On this page
Cloudflare MCP Server Portals put many MCP servers behind one authenticated endpoint, with identity from your corporate IdP, per-tool allow and deny policy, and per-user OAuth to the upstream servers. It is a real gateway, it shipped in Open Beta in August 2025, and it runs on Cloudflare One's free plan, which covers up to 50 users. If you are running MCP servers across a team without an access layer, you should look at it.
It answers one question completely: who is allowed to reach this tool.
It does not answer the other one: why is this agent calling it right now. Those are different questions, and the second one is the one that is still open.
What Cloudflare actually shipped
Credit where it is due. The portal is not a thin wrapper.
- One endpoint, many servers. Register your MCP servers, hand users a single portal URL to configure in their client. Tools are auto-namespaced as
{server_id}_{tool_name}so two servers cannot collide. - Per-tool policy, not just per-server. Individual tools and prompts can be toggled per portal. There is an allowlist pattern too: set
default_disabled: trueon the server-to-portal mapping and enable only what you want. - Per-user upstream OAuth. This is the part most people underestimate. A Require user auth toggle decides whether each user authenticates separately to each OAuth-protected upstream server, or whether everyone shares one admin credential. Where a server supports dynamic client registration, Cloudflare handles it. Where it does not, you register a redirect URI and supply a client ID and secret.
- Zero Trust policy on the front door. MFA, device posture, geography, all the Cloudflare One controls, applied to an AI client the same way they are applied to a human.
- Aggregated logs, exportable to a SIEM via Logpush on enterprise plans.
That last set is the thing to take seriously. Multi-operator OAuth is genuinely unpleasant to build, and most teams running agents on shared infrastructure have not built it. Cloudflare did, and put it behind a switch.
The line: access versus behavior
Here is the whole distinction in one table.
| Question | Answered by |
|---|---|
| Is this a real user from our directory? | Access |
| Is their device healthy, are they in an allowed country? | Access |
| Are they allowed to reach the Attio server? | Portal policy |
Are they allowed to call attio__delete_record specifically? |
Portal policy |
| What is this agent trying to accomplish? | Nothing in the stack |
| Was this call in service of that goal? | Nothing in the stack |
| What context and constraints should this call receive? | Nothing in the stack |
Cloudflare's own enterprise MCP reference architecture spans infrastructure and authentication, discovery and governance, and LLM mediation for cost and provider flexibility. There is no agent-intent verification in it. No task attribution. No tracing a call back to a stated goal.
Their shadow-MCP detection blocks unauthorized servers. It does not detect unauthorized operations by an authorized agent, because from the perimeter those two things look identical. A correctly authenticated agent making a call it had no business making is, at the network layer, a completely normal request.
This is perimeter security applied to agents. It is necessary. It is not sufficient.
The sharpest finding: purpose justification does not apply
Cloudflare Access already has a feature called purpose justification. It prompts a user for why they need access, framed in GDPR purpose-limitation language, so you can audit not just who reached a resource but why they said they needed it.
That sounds like an intent gate. It is not, for three independent reasons.
- It fires once per Access session, at login — with Cloudflare's example eight-hour session length, once every eight hours. Not per tool call.
- It is audit-only. It records the stated reason. Nothing consumes it, nothing gates on it, and it does not change what the user can subsequently do.
- It does not apply to MCP portals at all. The portal documentation lists it explicitly under access policy features that are not enforced for server authorization through portals, alongside independent MFA and temporary authentication.
So the concept exists inside Cloudflare One, and it does not reach the MCP layer. A stated purpose that is collected once per session, never validated, and never consulted at call time is a compliance artifact. It is not governance.
Why this is structural, not a roadmap gap
The tempting read is that Cloudflare will add intent tracking next quarter. We do not think so, and the reason is architectural rather than a guess about their roadmap.
A neutral pipe cannot demand a behavior change from its clients. Cloudflare's entire value proposition for portals is that any MCP client works unchanged: point it at one URL, authenticate, done. That is the product.
Intent governance requires exactly the opposite. The client has to declare what it is doing before it touches a tool, and the gateway has to refuse the call if it does not. That is an opinionated contract imposed on the caller. It breaks "works unchanged" by design, and it is only worth accepting if the thing you get back is worth the friction: the right context, the right procedure, and the right constraints injected for that specific declared intent.
You cannot be a transparent proxy and a forcing function at the same time. Cloudflare picked transparent proxy, which is the right call for what they are selling.
There is a second tell. Their reference architecture frames excessive token consumption as a cost problem, to be solved with caching and provider flexibility. We frame the same number as a governance problem: tokens burned before the first task-advancing call are a measurable tax that a compiled procedure removes permanently. Same metric, entirely different theory of what it means.
What the logs do and do not carry
Portal logs record timestamp, HTTP status, MCP server name, tool name, and processing duration.
That is a good access log. It is not a decision record. What is absent:
- No task or goal attribution. You can see that
attio__update_recordwas called. You cannot see what the operator was trying to accomplish, or reconstruct which calls belonged to the same piece of work. - No semantic success. HTTP status is the only outcome signal. A tool that returns
200 OKwith an error payload in the body reads as a success. We hit exactly this and had to fix it in our own telemetry: error-shaped results now count as failures, because otherwise your error rate is a fiction. - No response shape or size. The most expensive failure mode we see is a tool that returns correct data at the wrong shape, burning the context window before the agent can act. That never appears in an access log.
If your question is "who touched what," portal logs answer it. If your question is "is this AI deployment producing anything," they cannot.
Practical limits worth knowing before you plan around it
From Cloudflare's own documentation, as of early August 2026:
- No stdio transport. Servers must expose an HTTP endpoint. Anything you run as a local subprocess needs an HTTP wrapper first. In our own deployment that rules out several integrations we run as stdio children today, including both Google Analytics and Search Console.
- Maximum 40 MCP servers per portal.
- Some servers return 403 to proxy clients and simply will not work behind a portal.
- Admin tokens can expire silently, with no automatic notification. This is the same shape of failure as a credential that looks configured and is not, which is the single most expensive class of integration bug we have logged.
- Manual-OAuth tools are captured only at first user authentication. The roughly two-hourly background sync does not refresh them.
Our verdict
We are not putting our deployments behind a portal, and the reason is not competitive.
Entity isolation is a structural claim in our architecture: the agent operating for one business cannot see another's context, because the deployments are separate, not because a policy says so. For a portfolio operator, "structurally cannot" is a materially stronger sentence than "a vendor's policy engine says it cannot." We are not trading the first for the second.
But we are also not pretending this is competition. It is validation, and it is useful. Cloudflare has now made the access layer a commodity, at a scale and a price nobody should try to match. That is genuinely good news for anyone whose value sits above that layer, and it is a straightforward argument to stop investing in plumbing.
What we would take from them without hesitation is the connection experience. Dynamic client registration handled automatically, a single toggle for per-user versus shared credentials, a documented redirect URI flow. Getting a Google credential minted at the right scope and surviving a container restart is one of the roughest edges in this whole ecosystem, and Cloudflare made it a switch. That is a design worth copying.
The honest summary: they solved the front door properly, and the front door was worth solving. The room behind it is still empty.
Related
- Google Workspace MCP: Official vs Community Server — what per-operator OAuth costs when you build it yourself
- Google Search Console MCP: 5 Setup Errors — the credential failures a good connection UX would prevent
- Gmail MCP Search Returns IDs, Not Senders — the failure class that never appears in an access log
- Claude Code MCP Scopes: Local, Project, User + a 4th Layer — where MCP configuration lives before any gateway sees it
- Isolate Claude MCP Connections Per Client — isolation as a structural property rather than a policy setting
Frequently asked questions
What is a Cloudflare MCP Server Portal?
It is a managed gateway in Cloudflare One that puts multiple MCP servers behind a single authenticated endpoint. Users configure one portal URL in their MCP client, authenticate through your corporate identity provider via Cloudflare Access, and see only the servers and tools they are authorized to use. Tools are automatically namespaced as {server_id}_{tool_name}. It launched in Open Beta in August 2025 and is available on Cloudflare One's free plan, which covers up to 50 users.
Does Cloudflare MCP Server Portal support stdio MCP servers?
No. Servers must expose an HTTP endpoint. Stdio-only servers, which are typically run as a local subprocess, are incompatible unless you self-host them behind an HTTP wrapper first. The portal auto-detects transport, preferring Streamable HTTP for URLs ending in /mcp and SSE for URLs ending in /sse, and when Gateway routing is enabled only Streamable HTTP is supported.
Does Cloudflare handle per-user OAuth to upstream MCP servers?
Yes. Portals have a Require user auth toggle: enabled, each user authenticates separately to each OAuth-protected upstream server; disabled, all users share a single admin credential. Where a server supports dynamic client registration Cloudflare handles it automatically; otherwise an admin registers a redirect URI and supplies a client ID and secret.
Does Cloudflare Access purpose justification work with MCP portals?
No. Cloudflare's portal documentation lists purpose justification under access policy features that are not enforced for server authorization through portals, alongside independent MFA and temporary authentication. Even where it does apply, purpose justification prompts once per Access session at login (eight hours in Cloudflare's example configuration), is an audit record rather than a gate, and does not affect what the user can subsequently do.
What do Cloudflare MCP Server Portal logs contain?
Timestamp, HTTP status, MCP server name, tool or capability name, and processing duration, with Logpush export to a SIEM on enterprise plans. There is no task or goal attribution, so you cannot reconstruct which calls belonged to the same piece of work, and HTTP status is the only outcome signal, so a tool returning 200 with an error payload in the body reads as a success.
How many MCP servers can one Cloudflare portal hold?
Forty. Other documented caveats: some MCP servers return 403 to proxy clients and will not work behind a portal, admin tokens can expire silently with no automatic notification, and tools captured through manual OAuth are only read at first user authentication because the background sync does not refresh them.