Originally published on IndieSeek.
Cloudflare API MCP OAuth scopes: grant an agent only the permissions its workflow needs
Quick answer
On August 22, 2026, Cloudflare changed the OAuth consent flow for Wrangler and the Cloudflare API MCP server so users can decline optional scopes while required scopes remain selected. If a later command or MCP tool call needs a scope you withheld, Cloudflare's documented path is to reauthorize the client and add it.
That is a useful least-privilege control, but the permission picker is not the finished safety case. The Cloudflare API MCP server exposes only search() and execute(), yet those two tools can reach more than 2,500 API endpoints. Before connecting an agent, map one workflow to the smallest permission set, prove the intended action succeeds, prove one nearby unapproved action fails, and record how to revoke the grant.
Who this is for
This guide is for developers who use Wrangler interactively or connect Claude Code, Codex, Cursor, or another MCP client to https://mcp.cloudflare.com/mcp. It is especially relevant when the agent can inspect or change DNS, Workers, R2, Pages, D1, Zero Trust, or account settings.
It does not replace account roles, API-token policy, deployment review, or Cloudflare audit logs. If the broader risk is opening an untrusted repository, start with the AI coding-agent sandbox checklist. If the risk is a duplicate write after reconnect, use the MCP safe-replay checklist.
What changed—and what did not
| Surface | Confirmed behavior | Boundary |
|---|---|---|
| OAuth consent | Wrangler and the Cloudflare API MCP server let the user edit optional permissions during authorization | Required scopes remain selected; the changelog does not publish one universal minimal set for every workflow |
| Missing scope | A command or tool call that needs a declined scope requires reauthorization with that scope | Do not respond to every denial by granting all permissions |
| Cloudflare API MCP | Two Code Mode tools search and execute against a typed representation of more than 2,500 Cloudflare API endpoints | A small tool count does not mean a small authority surface |
| API tokens | CI and automation may use a bearer API token with explicitly chosen permissions | Token storage, rotation, IP filtering support, and account-resource access remain separate decisions |
| Dynamic Worker | Generated Code Mode JavaScript runs in an isolated Dynamic Worker sandbox | The sandbox limits code execution; OAuth scopes still decide which Cloudflare resources the request may affect |
The important distinction is between tool visibility, execution isolation, and resource authority. Passing one of those checks does not prove the other two.
Build the task-to-scope matrix first
Start with an observable workflow, not a broad role such as “manage Cloudflare.” Break it into API-shaped actions.
| Workflow step | Resource | Operation | Expected authority | Canary |
|---|---|---|---|---|
| Inspect a Worker | one account / named script | read | allow | return metadata without source secrets |
| Publish a canary Worker | one disposable script | write | allow only in rollout lane | deploy a harmless marker, then remove it |
| Read production DNS | one zone | read | allow if required | resolve one known record |
| Change production DNS | one zone | write | deny by default | attempted change must fail before side effect |
| Enumerate other accounts | unrelated accounts | read | deny | search and execute must not return their resources |
Keep Wrangler and the MCP client as separate grant records. They are different clients with different workflows; a broad interactive Wrangler grant is not evidence that an unattended agent should inherit the same authority.
A six-stage rollout
1. Freeze identity, client, and target
Record the Cloudflare user, account, zone, client name, MCP endpoint, and task owner. Use a disposable Worker, test zone, or non-production account for the first write canary. Never use a production secret as proof that the permission flow works.
2. Select only task-required optional scopes
At consent, leave required scopes selected and add only the optional permissions supported by the matrix. Do not select “everything” to avoid thinking about failures later. Take a redacted scope snapshot or export the connected-application record; never copy access tokens into the audit.
For unattended CI, compare OAuth with an explicitly scoped API token. Choose the identity model first, then the permissions. An API token is not automatically safer just because it is non-interactive, and OAuth is not automatically narrower just because a consent page was shown.
3. Run the positive read canary
Ask the client to inspect one known resource. Capture the planned endpoint, account or zone identifier, tool result, and Cloudflare-side read evidence where available. Pass only if the result belongs to the intended target and no unrelated account data appears.
4. Run one bounded write canary, if the workflow writes
Create or update a disposable resource with a unique marker, read it back through a separate path, and remove it. The MCP response saying “success” is not enough; require Cloudflare-side state or audit evidence. If the production workflow is read-only, skip the positive write and keep write scopes ungranted.
5. Prove a neighboring action is denied
Choose a harmless operation just outside the approved boundary: list an unrelated account, modify a protected zone, or write when only read was granted. The expected result is a permission denial with no state change.
Do not broaden the grant until you can name the exact required operation and target. A denial may also reveal an endpoint or OAuth-mapping limitation; Cloudflare issues show that “all visible permissions selected” has not always meant every API family accepts that OAuth token. Diagnose identity, target, endpoint support, and scope separately.
6. Reauthorize deliberately, then test revocation
When a real workflow change needs another scope, update the matrix, reauthorize the specific client, and rerun both the positive canary and the closest negative canary. Finally, revoke the connected application or token in a test lane and confirm the old credential can no longer call the API. Record the owner and review date for every surviving grant.
Scope decision tree
Does the workflow need Cloudflare account access?
no -> do not connect the API MCP server
yes -> is it interactive human work or unattended automation?
interactive -> evaluate optional OAuth scopes per client
unattended -> compare scoped OAuth with a scoped API token
Does the workflow modify state?
no -> keep write scopes declined; prove a write is denied
yes -> isolate a disposable target; grant only the required write family
Did a tool call fail for permission?
no -> keep the grant unchanged
yes -> confirm identity, account/zone, endpoint support, and exact operation
unclear -> stop; do not grant everything
clear -> reauthorize one scope and rerun positive + negative canaries
Common mistakes
- Equating two MCP tools with a two-action blast radius.
- Reusing a broad Wrangler grant as the agent's permission policy.
- Granting every optional scope after the first expected denial.
- Testing a write permission on production DNS, production Workers, or live access policy.
- Treating a successful MCP response as proof of a completed Cloudflare-side change.
- Assuming a Dynamic Worker sandbox limits the OAuth token's resource authority.
- Storing a bearer token, consent screenshot, or debug log in the repository.
- Keeping a grant with no owner, expiry review, or revocation canary.
Copyable acceptance record
date / owner / client / client_version:
identity / account / zone / environment:
workflow / approved_resources / approved_operations:
required_scopes / selected_optional_scopes / declined_scopes:
positive_read_canary / Cloudflare_read_evidence:
positive_write_canary_or_not_applicable / state_readback / cleanup:
negative_canary / expected_denial / no_side_effect_evidence:
reauthorization_reason / scope_delta / reviewer:
revocation_test / old_credential_result:
decision: hold | narrow | reauthorize | limited-rollout | promote
next_review_at:
FAQ
Should I decline every optional scope initially?
Decline every optional scope the defined workflow does not need. A useful minimum is task-specific, not universally zero. Required scopes remain selected by the authorization flow.
Does the new picker make the Cloudflare API MCP server safe for production changes?
No. It makes least-privilege grants easier. You still need account roles, target isolation, human approval for consequential changes, side-effect readback, audit evidence, and revocation.
Should CI use OAuth or an API token?
Use the identity type your automation can store, rotate, restrict, and audit safely. Cloudflare documents bearer API tokens for CI and automation, but the token still needs an explicit permission and resource boundary. Do not place it in source control or agent-visible logs.
What if a selected scope still returns an authorization error?
Do not assume the answer is more permissions. Verify the authenticated identity, account or zone selection, endpoint support for that token type, and the exact scope-to-API mapping. If the boundary remains unclear, keep the workflow blocked or use a narrower supported route.
Sources
- Cloudflare changelog: optional OAuth scopes for Wrangler and the API MCP server
- Cloudflare: Cloudflare API MCP server
- Cloudflare: MCP authorization and permission-based tool access
- Cloudflare MCP issue: document required OAuth scopes and API-token permissions
- Cloudflare MCP issue: selected OAuth permissions did not authorize every tested API family
Read the maintained original on IndieSeek.
Top comments (0)