Cloudflare Remote MCP Worker
When to use
Use this when a repo already has an MCP server or similar backend and the user wants:
- a Cloudflare-hosted remote MCP endpoint,
- a browser app and MCP tool sharing the same Worker logic,
- Cloudflare deploy/secret setup notes,
- verification that the result is usable through
/mcp,
- repo-visible docs/screenshots/auth cleanup that should land on
main.
Do not use it for local-only stdio/plugin packaging with no remote deployment goal. Use skills/repo-plugin-packaging/SKILL.md for Codex plugin UI packaging.
Inputs and context to gather
- Confirm repo root, branch, dirty state, and default branch:
git rev-parse --show-toplevel
git status --short --branch
git remote show origin | sed -n '1,40p'
- Find the current MCP/server entrypoints and deployment files:
rg -n "StdioServerTransport|createMcpHandler|/mcp|wrangler|worker" src package.json README.md plugins scripts
- Check whether the repo already has:
- a local stdio path that must remain intact,
- an existing Worker entrypoint,
- a smoke test script,
.env or other local config the Worker dev path should reuse.
- If secrets are needed, plan the split:
- repo-safe work in-session,
wrangler login, wrangler secret put ..., or any real token entry handed to the user.
Procedure
- Keep the local path intact. If the repo already has a local stdio launcher, add the Worker as a separate entrypoint rather than replacing the existing local integration.
- Create or extend the Worker entrypoint so it exposes:
POST /mcp for the remote MCP server,
GET /health for fast verification,
- optional browser/demo routes such as
/ or /api/... when the repo needs a user-facing demo.
- Add/update
wrangler.jsonc and package scripts. Keep the naming explicit:
worker:dev
worker:dry-run
worker:deploy
- If local dev should reuse
.env, add a sync step for Wrangler local vars before wrangler dev.
- Document the remote connector shape in README/docs using placeholders, not personal deployed URLs.
- Add or update smoke tests:
- local build/smoke,
- MCP tool-surface contract smoke if the repo already has a non-trivial tool set,
- remote MCP protocol smoke against
/mcp,
- app/API smoke if a browser/demo route exists.
- If auth is needed, prefer a single clear mechanism such as
ACCESS_TOKEN with Authorization: Bearer ..., and document the client limitation if some MCP clients cannot send custom headers.
- Create local-only handoff notes only if the user asks. Keep them out of shared history with
.git/info/exclude unless the repo explicitly wants shared docs.
- For repo visibility, do not stop at a feature branch if the user expects the work visible on GitHub’s default branch. Verify whether it has landed on
main.
Efficiency plan
- Search for existing server/deploy code before writing new scaffolding.
- If the repo already exposes many tools, add or reuse one contract smoke that checks the expected list and samples a few representative workflow calls before expanding the surface further.
- Reuse one shared ranking/service layer when both browser UI and MCP tool need the same behavior.
- Use
/health first, then remote MCP smoke, then richer UI/API smoke.
- If the task changes Worker-visible HTML/app behavior, assume a redeploy is needed after merge and verify the hosted URL again instead of stopping at GitHub.
- Stop early if the blocker is secret entry or Cloudflare login and hand that step to the user instead of stalling.
Pitfalls and fixes
- Symptom:
wrangler deploy --dry-run or wrangler dev fails on a macOS log-path permission error.
Cause: Wrangler is trying to write logs outside the workspace.
Fix: set WRANGLER_LOG_PATH=/tmp/<repo>-wrangler.log before rerunning.
- Symptom: remote Worker works locally but public docs leak a personal
workers.dev URL.
Cause: committed docs used the real deployed URL instead of placeholders.
Fix: scrub the concrete URL from committed docs and keep it only in local notes.
- Symptom: user says “I don’t see it on GitHub.”
Cause: the work exists only on a feature branch or PR.
Fix: verify
origin/main explicitly before claiming the change is public.
- Symptom: a new smoke/verification script fails because one tool is missing locally but exists remotely.
Cause: local stdio and Worker tool surfaces drifted.
Fix: treat it as a parity bug and wire the missing tool into the local entrypoint instead of weakening the smoke.
- Symptom: UI or browser-demo changes merged to GitHub are not visible at the
workers.dev URL.
Cause: GitHub merge did not redeploy the Cloudflare Worker.
Fix: rerun worker:dry-run, then worker:deploy, then verify /health and the remote /mcp smoke again.
- Symptom: remote MCP auth works in smoke scripts but not in a third-party client.
Cause: the client cannot send bearer headers.
Fix: choose public mode, a different route/token scheme, or Cloudflare Access/OAuth.
- Symptom: live upstream API calls fail intermittently with resets.
Cause: network flakiness or upstream instability.
Fix: add retries and partial-failure tolerance instead of failing the whole result.
Verification checklist
- Local stdio/plugin path still works if the repo had one before.
npm run build or equivalent succeeds.
worker:dry-run or local Worker validation succeeds.
/health responds with the expected shape.
- Remote MCP smoke reaches
/mcp and lists/calls the expected tools.
- If the repo has a workflow-tool contract smoke, it passes locally and against the deployed Worker.
- Browser/API smoke passes if demo routes exist.
- Docs use placeholder URLs and explain auth/client caveats honestly.
- If the user expects public GitHub visibility, verify the final state on
main, not just the feature branch.
1---2name: cloudflare-remote-mcp-worker3description: Deploy or extend an existing MCP-capable repo onto a Cloudflare Worker when the user wants a remote `/mcp` URL, Cloudflare-hosted testing, auth/docs/screenshots, or a clean path from local repo work to repo-visible `main`.4---56# Cloudflare Remote MCP Worker78## When to use910Use this when a repo already has an MCP server or similar backend and the user wants:11- a Cloudflare-hosted remote MCP endpoint,12- a browser app and MCP tool sharing the same Worker logic,13- Cloudflare deploy/secret setup notes,14- verification that the result is usable through `/mcp`,15- repo-visible docs/screenshots/auth cleanup that should land on `main`.1617Do not use it for local-only stdio/plugin packaging with no remote deployment goal. Use `skills/repo-plugin-packaging/SKILL.md` for Codex plugin UI packaging.1819## Inputs and context to gather20211. Confirm repo root, branch, dirty state, and default branch:2223```bash24git rev-parse --show-toplevel25git status --short --branch26git remote show origin | sed -n '1,40p'27```28292. Find the current MCP/server entrypoints and deployment files:3031```bash32rg -n "StdioServerTransport|createMcpHandler|/mcp|wrangler|worker" src package.json README.md plugins scripts33```34353. Check whether the repo already has:36- a local stdio path that must remain intact,37- an existing Worker entrypoint,38- a smoke test script,39- `.env` or other local config the Worker dev path should reuse.40414. If secrets are needed, plan the split:42- repo-safe work in-session,43- `wrangler login`, `wrangler secret put ...`, or any real token entry handed to the user.4445## Procedure46471. Keep the local path intact. If the repo already has a local stdio launcher, add the Worker as a separate entrypoint rather than replacing the existing local integration.482. Create or extend the Worker entrypoint so it exposes:49- `POST /mcp` for the remote MCP server,50- `GET /health` for fast verification,51- optional browser/demo routes such as `/` or `/api/...` when the repo needs a user-facing demo.523. Add/update `wrangler.jsonc` and package scripts. Keep the naming explicit:53- `worker:dev`54- `worker:dry-run`55- `worker:deploy`564. If local dev should reuse `.env`, add a sync step for Wrangler local vars before `wrangler dev`.575. Document the remote connector shape in README/docs using placeholders, not personal deployed URLs.586. Add or update smoke tests:59- local build/smoke,60- MCP tool-surface contract smoke if the repo already has a non-trivial tool set,61- remote MCP protocol smoke against `/mcp`,62- app/API smoke if a browser/demo route exists.637. If auth is needed, prefer a single clear mechanism such as `ACCESS_TOKEN` with `Authorization: Bearer ...`, and document the client limitation if some MCP clients cannot send custom headers.648. Create local-only handoff notes only if the user asks. Keep them out of shared history with `.git/info/exclude` unless the repo explicitly wants shared docs.659. For repo visibility, do not stop at a feature branch if the user expects the work visible on GitHub’s default branch. Verify whether it has landed on `main`.6667## Efficiency plan6869- Search for existing server/deploy code before writing new scaffolding.70- If the repo already exposes many tools, add or reuse one contract smoke that checks the expected list and samples a few representative workflow calls before expanding the surface further.71- Reuse one shared ranking/service layer when both browser UI and MCP tool need the same behavior.72- Use `/health` first, then remote MCP smoke, then richer UI/API smoke.73- If the task changes Worker-visible HTML/app behavior, assume a redeploy is needed after merge and verify the hosted URL again instead of stopping at GitHub.74- Stop early if the blocker is secret entry or Cloudflare login and hand that step to the user instead of stalling.7576## Pitfalls and fixes7778- Symptom: `wrangler deploy --dry-run` or `wrangler dev` fails on a macOS log-path permission error.79 Cause: Wrangler is trying to write logs outside the workspace.80 Fix: set `WRANGLER_LOG_PATH=/tmp/<repo>-wrangler.log` before rerunning.81- Symptom: remote Worker works locally but public docs leak a personal `workers.dev` URL.82 Cause: committed docs used the real deployed URL instead of placeholders.83 Fix: scrub the concrete URL from committed docs and keep it only in local notes.84- Symptom: user says “I don’t see it on GitHub.”85 Cause: the work exists only on a feature branch or PR.86 Fix: verify `origin/main` explicitly before claiming the change is public.87- Symptom: a new smoke/verification script fails because one tool is missing locally but exists remotely.88 Cause: local stdio and Worker tool surfaces drifted.89 Fix: treat it as a parity bug and wire the missing tool into the local entrypoint instead of weakening the smoke.90- Symptom: UI or browser-demo changes merged to GitHub are not visible at the `workers.dev` URL.91 Cause: GitHub merge did not redeploy the Cloudflare Worker.92 Fix: rerun `worker:dry-run`, then `worker:deploy`, then verify `/health` and the remote `/mcp` smoke again.93- Symptom: remote MCP auth works in smoke scripts but not in a third-party client.94 Cause: the client cannot send bearer headers.95 Fix: choose public mode, a different route/token scheme, or Cloudflare Access/OAuth.96- Symptom: live upstream API calls fail intermittently with resets.97 Cause: network flakiness or upstream instability.98 Fix: add retries and partial-failure tolerance instead of failing the whole result.99100## Verification checklist101102- Local stdio/plugin path still works if the repo had one before.103- `npm run build` or equivalent succeeds.104- `worker:dry-run` or local Worker validation succeeds.105- `/health` responds with the expected shape.106- Remote MCP smoke reaches `/mcp` and lists/calls the expected tools.107- If the repo has a workflow-tool contract smoke, it passes locally and against the deployed Worker.108- Browser/API smoke passes if demo routes exist.109- Docs use placeholder URLs and explain auth/client caveats honestly.110- If the user expects public GitHub visibility, verify the final state on `main`, not just the feature branch.