Bỏ qua để đến nội dung

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.

  1. Never delete posts/pages on WordPress or Duda. There are no delete_post / delete_page tools, and adapters refuse DELETE on posts/pages. (Documented exception: delete_astro_route removes a .astro code file, super-admin only; the post-content rule is intact.)
  2. 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.
  3. 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_page refuse with E_PUBLISH_NOT_ALLOWED.
  • When ON: tools flip the post/page to status=publish (WordPress) or draft_status=PUBLISHED (Duda). Every call is written to audit_log.

Tools:

ToolDescription
publish_postFlip a draft / scheduled post to live.
publish_pageFlip 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_schema call on a status=publish post refuses with E_FORBIDDEN_OP (REST channel checks via /wp/v2/posts/:id?_fields=status; plugin channel checks via the bridge’s get_post_status() call).
  • ON: those calls go through. The worker auto-detects when the post is published, sets allow_published=true in the bridge request body, and injects _published: true into 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.

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 via create_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.

Lets Astro tools push directly to the site’s primary github_branch (typically main, the branch Cloudflare Pages builds for production).

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_deploy with 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.

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.

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.

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.

CodeMeaning
E_PUBLISH_NOT_ALLOWEDSite’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_LOCKEDAstro 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_ALLOWEDbulk_write_astro_files was called on a site without allow_full_repo_write. Super-admin must enable it.
E_FILE_TOO_LARGEwrite_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_LARGEbulk_write_astro_files exceeded the per-call limits (1000 files / 100 MB total / 25 MB per file). Split the call.
E_BAD_PATHPath failed validation. Includes the reason — usually a secret path that the flag does not unlock.
E_GITHUB_BRANCH_MISSINGTried to fork a preview off a primary branch that doesn’t exist on the repo. Check github_branch in the site config.

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_page explicitly.
  • Astro source files in src/pages/** still require create_astro_route (which writes the MCP marker) or update_astro_routewrite_astro_file refuses src/pages/** paths.
  • Config files (astro.config.*, package.json, tsconfig.json, wrangler.toml), .env*, .github/**, node_modules/, and dist/ remain unwritable via MCP.