Executor MCP on Cloudflare Access
The complete Zero Trust → Managed OAuth → Codex setup runbook for cross-device MCP access.
The Worker deploy was only half the job. Cross-device MCP access required a matching Cloudflare Access application, the Worker’s JWT-verification vars, Managed OAuth with localhost and loopback callbacks, and Codex registration with an explicit --oauth-resource.
Live deployment
- Worker URL
- https://executor-cloudflare.davis-benjamin41902.workers.dev
- MCP endpoint
- https://executor-cloudflare.davis-benjamin41902.workers.dev/mcp
- Access application
executor-cloudflare- Access team domain
bitter-term-c4e1.cloudflareaccess.com- Host checkout
/Users/davis/Developer/executor-pr877/apps/host-cloudflare
Fast path: the checklist
Use this short path. The detailed explanation for every step is below.
- In Cloudflare Zero Trust, create or open the self-hosted Access app for
executor-cloudflare.davis-benjamin41902.workers.dev. - Add an Allow policy for the intended email address or domain.
- Copy the Access application’s Application Audience (AUD) Tag.
- Set
ACCESS_TEAM_DOMAIN,ACCESS_AUD, andADMIN_EMAILSin the Worker config, then redeploy. - Edit the Access app and enable Advanced settings → Managed OAuth.
- Within Managed OAuth, enable Allow localhost clients and Allow loopback clients.
- Verify that Cloudflare advertises both
cloudflaredandoauth. - Register Codex with both
--urland--oauth-resource, using the same MCP URL for each. - Complete browser login, then verify the MCP server in Codex.
1. Create the Cloudflare Access application
Open Cloudflare Zero Trust, then navigate to:
Access controls
→ Applications
→ Add an application
→ Self-hosted
Configure the application:
| Field | Value |
|---|---|
| Application name | executor-cloudflare |
| Application domain | executor-cloudflare.davis-benjamin41902.workers.dev |
Do not include https:// in the application-domain field.
Add an Access policy for the intended users. A simple personal deployment can use:
Action: Allow
Include: Emails → your email address
Before the Access application existed, the Worker redirected browser requests to /cdn-cgi/access/login, but Cloudflare had no matching login application. That caused the misleading 404 page.
2. Copy the Access application AUD tag
Open the new executor-cloudflare Access application and copy its:
Application Audience (AUD) Tag
The Worker validates Cloudflare Access JWTs itself, so it needs both the team domain and the application audience.
3. Tell the Worker about Cloudflare Access
Open the Cloudflare host checkout:
cd /Users/davis/Developer/executor-pr877/apps/host-cloudflare
Update the vars block in wrangler.jsonc with the real Access values:
"vars": {
"ACCESS_TEAM_DOMAIN": "bitter-term-c4e1.cloudflareaccess.com",
"ACCESS_AUD": "<your Access application AUD tag>",
"ADMIN_EMAILS": "<your email address>"
}
Redeploy the Worker:
bunx wrangler deploy
Keep EXECUTOR_SECRET_KEY as a Wrangler secret. Do not move it into the plain-text vars block and do not rotate it during an idempotent redeploy. Existing encrypted values depend on it.
4. Enable Managed OAuth for non-browser clients
A basic Access application is sufficient for browser login, but it is not sufficient for Codex and other cross-device MCP clients.
Edit the same Access application:
Access controls
→ Applications
→ executor-cloudflare
→ Edit
→ Advanced settings
→ Managed OAuth
Enable all three settings:
- Managed OAuth
- Allow localhost clients
- Allow loopback clients
codex mcp login opens an interactive browser login and dynamically registers a temporary callback such as http://127.0.0.1:60183/callback/.... Cloudflare must accept that callback.
Worker deployment and Zero Trust configuration are separate control planes. Running wrangler deploy again cannot enable Managed OAuth. A Wrangler login can be authorized to deploy Workers and manage D1/R2 while still lacking permission to edit Access applications.
5. Verify Managed OAuth at the HTTP boundary
Check Cloudflare’s protected-resource metadata:
curl -fsS \
https://executor-cloudflare.davis-benjamin41902.workers.dev/.well-known/cloudflare-access-protected-resource/mcp
Before enabling Managed OAuth, Cloudflare advertised only:
[
"cloudflared"
]
After enabling Managed OAuth correctly, it advertises both:
[
"cloudflared",
"oauth"
]
Also inspect the unauthenticated MCP response:
curl -i \
https://executor-cloudflare.davis-benjamin41902.workers.dev/mcp
| State | Observed response | Meaning |
|---|---|---|
| Before Managed OAuth | 302 browser redirect | Fine for a human browser, unusable for ordinary MCP OAuth discovery. |
| After Managed OAuth | 401 with WWW-Authenticate: Bearer ... | Correct OAuth-capable challenge for Codex and other remote MCP clients. |
The post-fix 401 is expected. It protects the endpoint while giving OAuth-capable clients enough metadata to authenticate.
6. Register Executor in Codex with an OAuth resource indicator
Cloudflare Managed OAuth requires the OAuth resource parameter. If the server was previously registered without it, remove the stale Codex entry:
codex mcp remove executor
Re-add the remote MCP server with the exact MCP URL for both flags:
codex mcp add executor \
--url https://executor-cloudflare.davis-benjamin41902.workers.dev/mcp \
--oauth-resource https://executor-cloudflare.davis-benjamin41902.workers.dev/mcp
Use the same URL, including /mcp, for --url and --oauth-resource.
If Codex adds the server without opening the browser automatically, run:
codex mcp login executor
Without --oauth-resource, Codex reached its localhost callback successfully but Cloudflare rejected the authorization request with:
OAuth provider returned `invalid_target`: No+resource+parameter+found
7. Verify the Codex connection
Check the registered MCP servers:
codex mcp list
Then launch Codex:
codex
Inside the Codex TUI, run:
/mcp
Executor should appear as an authenticated remote MCP server.
Troubleshooting map
| Symptom | Root cause | Fix |
|---|---|---|
Browser shows a 404 at /cdn-cgi/access/login | No matching Cloudflare Access application exists for the Worker hostname. | Create the self-hosted Access application and policy. |
Worker returns 401 after Access login | ACCESS_AUD or ACCESS_TEAM_DOMAIN does not match the Access application. | Re-copy the AUD tag, confirm the team domain, and redeploy. |
codex mcp login executor fails while parsing metadata | Managed OAuth is still disabled, so Access returns a browser-only 302. | Enable Advanced settings → Managed OAuth, plus localhost and loopback clients. |
invalid_target: No resource parameter found | Codex was registered without Cloudflare’s required OAuth resource indicator. | Remove and re-add the MCP entry with --oauth-resource .../mcp. |
API edit of the Access application returns 403 | The normal Wrangler OAuth session lacks Zero Trust Access-app administration permission. | Use the dashboard, or use a separately scoped API token with Access: Apps and Policies Write. Never paste that token into chat. |
| Logged in but not an Executor admin | The login email is absent from ADMIN_EMAILS. | Add the email to ADMIN_EMAILS and redeploy. |
Reusable copy-paste block
For an existing Worker whose Access vars are already correct:
# Cloudflare dashboard:
# Access controls → Applications → executor-cloudflare → Edit
# → Advanced settings → Managed OAuth
# → Enable Allow localhost clients
# → Enable Allow loopback clients
# → Save
curl -fsS \
https://executor-cloudflare.davis-benjamin41902.workers.dev/.well-known/cloudflare-access-protected-resource/mcp
codex mcp remove executor
codex mcp add executor \
--url https://executor-cloudflare.davis-benjamin41902.workers.dev/mcp \
--oauth-resource https://executor-cloudflare.davis-benjamin41902.workers.dev/mcp
codex mcp login executor
codex mcp list
What was non-obvious
- Cloudflare Access setup is separate from Worker deployment.
- Cross-device MCP clients need Managed OAuth, not merely a browser Access policy.
- Codex’s temporary browser callback requires both localhost and loopback allowances.
- Codex must send an explicit
resourcevalue through--oauth-resource. - A healthy protected MCP endpoint returns an unauthenticated
401Bearer challenge after Managed OAuth is enabled; that is success, not an exposure or deployment failure.