Publishing & preview branches
Nội dung này hiện chưa có sẵn bằng ngôn ngữ của bạn.
By default this server never publishes anything. Drafts only. Two super-admin-only, default-OFF site flags opt specific sites into live publishing or direct production push.
The hard rule (still)
Section titled “The hard rule (still)”- Never delete posts/pages on WordPress or Duda. There are no
delete_post/delete_pagetools, and adapters refuseDELETEon posts/pages. (Documented exception:delete_astro_routeremoves a.astrocode file, super-admin only; the post-content rule is intact.) - Tools that create content (
create_draft,create_page_draft,create_page_from_code,create_astro_route…) never publish on create. They always start as drafts. - Publishing now needs a separate, opt-in tool call on a site that has been explicitly opted in.
Flag 1 — allow_publish (WordPress + Duda)
Section titled “Flag 1 — allow_publish (WordPress + Duda)”Enables the dedicated tools publish_post and publish_page.
Where: /admin/sites → edit a WordPress or Duda site → ”⚠ Danger zone” →
tick Allow publish-now tools. The fieldset only appears for super-admin
users; regular users can’t see or set the flag.
Behavior:
- When OFF (default):
publish_post/publish_pagerefuse withE_PUBLISH_NOT_ALLOWED. - When ON: tools flip the post/page to
status=publish(WordPress) ordraft_status=PUBLISHED(Duda). Every call is written toaudit_log.
Tools:
| Tool | Description |
|---|---|
publish_post | Flip a draft / scheduled post to live. |
publish_page | Flip a draft page (Gutenberg, Elementor, code-page, or Duda Pages v2). |
The row on /admin/sites shows a red badge ⚠ Publish ON so any
super-admin reviewing the page knows the site is opted in.
Flag 2 — allow_seo_on_published (WordPress + RankMath)
Section titled “Flag 2 — allow_seo_on_published (WordPress + RankMath)”Lets set_seo_meta and set_seo_schema write RankMath metadata
(rank_math_*) on a post whose status='publish'. By default they refuse
with E_FORBIDDEN_OP — you’d have to unpublish to a draft first to edit
SEO meta. This flag relaxes that for sites where you intentionally need to
tune SEO on live content (the common reason: post is already ranking and
you want to iterate title/description without taking it offline).
Why split this from allow_publish: SEO meta edits don’t republish or
take the post live — the post is already public. They only change
metadata (title tag, meta description, focus keyword, robots, schema). A
site might legitimately want this loose without unlocking the
publish-now tools.
Where: same Danger Zone fieldset in /admin/sites. WordPress only —
the checkbox is hidden for Duda and Astro sites.
Behavior:
- Default OFF: every
set_seo_meta/set_seo_schemacall on astatus=publishpost refuses withE_FORBIDDEN_OP(REST channel checks via/wp/v2/posts/:id?_fields=status; plugin channel checks via the bridge’sget_post_status()call). - ON: those calls go through. The worker auto-detects when the post is
published, sets
allow_published=truein the bridge request body, and injects_published: trueinto the audit log args so admins can filter later.
Tools affected: set_seo_meta, set_seo_schema. Both get_*
variants are read-only and never bound by this flag. set_seo_redirect
is unrelated — redirects don’t have a “published” status.
The row on /admin/sites shows an amber badge ⚠ SEO on live ON
when this flag is enabled.
Flag 3 — allow_full_repo_write (Astro)
Section titled “Flag 3 — allow_full_repo_write (Astro)”Lifts the path whitelist on write_astro_file AND unlocks
bulk_write_astro_files for the site. With this flag on, MCP tools can
touch any path in the Astro project root:
src/pages/**(normally routed viacreate_astro_route)astro.config.mjs,package.json,tsconfig.json,wrangler.toml- Top-level files (
README.md,scripts/*)
The secret blocklist (.env*, .github/**, node_modules/, dist/,
path traversal, absolute paths) is unconditional — never writable
regardless of this flag.
Why it exists: pushing a fresh Astro project from local → GitHub requires writing every file in the tree, including config and pages. Without this flag, the default whitelist is intentionally narrow to prevent accidental damage.
Bulk uploads via bulk_write_astro_files: this tool does N file
writes in ONE atomic git commit (via the Git Data API: blobs + tree +
commit + ref). For a 50-file project that means 1 commit + 1 Cloudflare
Pages build, not 50. It also handles empty repos by creating the initial
commit and primary branch automatically. Limits: ≤1000 files per call,
≤100 MB total, ≤25 MB per file. Larger binary blobs need Git LFS. Plain
write_astro_file caps at 900 KB per file (GitHub Contents API limit).
Where: same Danger Zone in /admin/sites. Astro only.
Row badge: ⚠ Full repo write ON in fuchsia.
Flag 4 — allow_main_branch_push (Astro)
Section titled “Flag 4 — allow_main_branch_push (Astro)”Lets Astro tools push directly to the site’s primary github_branch
(typically main, the branch Cloudflare Pages builds for production).
Default behaviour: preview branches
Section titled “Default behaviour: preview branches”Without this flag, Astro write tools (create_astro_route,
update_astro_route, write_astro_file) push to a per-session preview
branch named mcp/<token>/<unix>. The branch is:
- Created on first use, forked from the primary branch HEAD.
- Cached on the calling token row so subsequent calls in the same session reuse it.
- Built by Cloudflare Pages as a preview deployment — call
check_astro_deploywith the commit_sha to get the preview URL.
To start a new preview branch (e.g. switching from one feature to another),
call reset_astro_preview_branch — the next write mints a fresh branch off
the primary HEAD. The old branch stays on GitHub; delete it manually if you
want to clean up.
Opting into main-branch push
Section titled “Opting into main-branch push”Set allow_main_branch_push in the Danger Zone, then pass
target_branch="main" on the tool call:
// create_astro_route input{ "site_id": "my-astro", "route": "/pricing", "html": "<h1>Pricing</h1>", "target_branch": "main"}Without the flag, this same call refuses with E_MAIN_BRANCH_LOCKED.
Why split this from publish?
Section titled “Why split this from publish?”Because Astro “publish” is a git push, not a CMS status flip. Cloudflare
auto-builds whatever lands on the configured branch. So the analogous
“don’t go live by accident” gate is which branch can we push to. Preview
branches give Claude (and you) a safe place to iterate; main is the
production trigger.
Audit trail
Section titled “Audit trail”Every publish_* call lands in audit_log with the tool name, site, token,
and target post id. View it on /admin/audit. The hard rule is still that
no delete tool ships — there’s nothing to log there because it can’t happen.
Error reference
Section titled “Error reference”| Code | Meaning |
|---|---|
E_PUBLISH_NOT_ALLOWED | Site’s allow_publish is off. Super-admin opt-in required. |
E_FORBIDDEN_OP (on set_seo_*) | Tried to edit SEO meta on a published post and the site’s allow_seo_on_published is off. Either unpublish the post to a draft or have a super-admin enable the flag. |
E_MAIN_BRANCH_LOCKED | Astro tool was called with target_branch="main" on a site without allow_main_branch_push. Stay on preview, or have a super-admin flip the flag. |
E_FULL_REPO_WRITE_NOT_ALLOWED | bulk_write_astro_files was called on a site without allow_full_repo_write. Super-admin must enable it. |
E_FILE_TOO_LARGE | write_astro_file rejected a >900 KB file (GitHub Contents API cap). Use bulk_write_astro_files instead. |
E_BULK_TOO_MANY_FILES / E_BULK_TOO_LARGE | bulk_write_astro_files exceeded the per-call limits (1000 files / 100 MB total / 25 MB per file). Split the call. |
E_BAD_PATH | Path failed validation. Includes the reason — usually a secret path that the flag does not unlock. |
E_GITHUB_BRANCH_MISSING | Tried to fork a preview off a primary branch that doesn’t exist on the repo. Check github_branch in the site config. |
What’s not opened up
Section titled “What’s not opened up”Even with both flags on:
- WordPress / Duda posts and pages still cannot be deleted via this server.
- Publishing-on-create is still refused; you must call
publish_post/publish_pageexplicitly. - Astro source files in
src/pages/**still requirecreate_astro_route(which writes the MCP marker) orupdate_astro_route—write_astro_filerefusessrc/pages/**paths. - Config files (
astro.config.*,package.json,tsconfig.json,wrangler.toml),.env*,.github/**,node_modules/, anddist/remain unwritable via MCP.