describe_collections | List every collection this server has (blog, docs, any user-registered ones, tokens, nav, collections, site, permissions, taxonomies) and its shape — extra metadata fields (with real current defaults) for entry-style collections, the known token names for tokens, an example items/cta shape for nav, an example shape for collections/site/permissions/taxonomies. Discover what a collection accepts before calling create_entry/update_entry/update_single (name: "tokens"/"nav"/"site"/"taxonomies"/"collections")/update_permissions against it. Call describe_taxonomies (not this tool) for live values currently in use per taxonomy. | (none) |
describe_components | List purpose-built components available beyond plain HTML (e.g. video-embed) — the tag to write, its required attributes, and a real usage example. Discover these instead of guessing at a raw <iframe> or similar, which will be rejected. | (none) |
search_icons | Find a real icon name to use with the icon component (see describe_components) — matches the query against ~1750 Lucide icon names and their upstream keyword tags (e.g. "cart" also finds shopping-cart via its own tags), case-insensitive substring, not relevance-ranked. Name matches sort before tag-only matches. Use this instead of guessing an icon name — an unrecognized name gets the whole <icon> element dropped at write time. | query, limit? |
list_entries | List entries from a collection, each with its editorial status (drafting / in review / changes requested / published / archived) derived from git/PR state | collection? |
read_entry | Read an entry's content and metadata | slug, collection? |
create_entry | Create a new entry (allowlist-validated), commit it to the content repo. Call describe_components first for the full HTML vocabulary — layout primitives (stack/wrap/card/carousel/column/section/grid), video-embed, and button classes — beyond plain text. | slug, html, title, date, draft?, tags?, collection?, excerpt?, featuredImage?, seoMetadata?, category?, pillar?, taxonomyValues?, order?, section?, path? |
update_entry | Update content/metadata of an existing entry (allowlist-validated), commit the change. Call describe_components first for the full HTML vocabulary — layout primitives (stack/wrap/card/carousel/column/section/grid), video-embed, and button classes — beyond plain text. | slug, html?, title?, date?, draft?, tags?, collection?, excerpt?, featuredImage?, seoMetadata?, category?, pillar?, taxonomyValues?, order?, section?, path? |
delete_entry | Remove an entry, commit the deletion | slug, collection? |
read_single | Read one of the site's config singles — "tokens" (design tokens), "nav" (top nav), "site" (global identity), "taxonomies" (the taxonomy registry), or "collections" (user-registered collections beyond blog/docs). Each returns the exact shape describe_collections documents for it (colorTokens/navShape/siteShape/taxonomiesShape/collectionsShape). permissions has its own dedicated read_permissions tool instead, not this one. | name |
update_single | Change one of the site's config singles. Pass "name" plus the one matching data field ("tokens"/"nav"/"site"/"taxonomies"/"collections") for the fields you want to set — whichever sub-fields you omit within it keep their current stored value, same partial-update posture each of these had as its own tool. taxonomies/collections replace their full list wholesale (pass every item you want to keep, not just the one you're changing) — same posture they always had. Like any other collection, create_draft/publish_content/submit_for_review/discard_draft all work here too — pass slug/collection matching name, e.g. slug: "nav", collection: "nav". permissions has its own dedicated update_permissions tool instead, not this one. | name, tokens?, nav?, site?, taxonomies?, collections? |
read_permissions | Read who can do what on the remote MCP server (this local server stays full-access regardless — permissions only govern workers/mcp-remote). Two parts: "roles" (permission-set name -> the tool names it grants — writer/editor/designer/dev are the built-in defaults, listed here only where explicitly overridden) and "assignments" (GitHub username -> role name). A username with no explicit assignment falls back to GitHub's own collaborator permission level (admin/maintain -> designer, write -> writer). | (none) |
update_permissions | Change who can do what on the remote MCP server. Grants access — use with real care, this is the one tool that controls every other tool's reach there. "roles" merges by name over the built-in writer/editor/designer/dev tool lists: defining "writer" replaces the built-in writer list; defining a new name (e.g. "marketing") adds a wholly new permission set. Pass the complete tool-name list for any role you set, not a delta. "assignments" merges by username: pass only the usernames you want to add or change, existing ones not mentioned keep their current assignment. Call describe_collections first to see every real tool name that exists. Like any other collection, create_draft/publish_content/submit_for_review/discard_draft all work here too — pass slug: "permissions", collection: "permissions". | roles?, assignments? |
describe_taxonomies | List every registered taxonomy plus every distinct value currently in use for it, computed live across its applicable collections. Call this before writing taxonomyValues on an entry, so you reuse an existing value instead of accidentally minting a near-duplicate (e.g. "Guide" vs "guide"). | (none) |
upload_image | Upload an image (base64-encoded) into an existing entry's image directory and commit it to the content repo. Reference it in the entry's HTML as <img src="<filename>" alt="...">, a bare filename — do not write <picture>/srcset/width/height, those are generated automatically at build time. | slug, filename, data, collection? |
create_draft | Start (or resume) the draft branch for an entry. Fails if another draft is already checked out for this slug — see spec §5.4 "Per-entry draft locking". | slug, collection? |
discard_draft | Discard an entry's draft without publishing, releasing the lock on it | slug, collection? |
diff | Show an entry's draft-branch changes against main (or another ref) | slug, against?, collection? |
publish_content | Publish an entry's draft — makes it live. mode picks direct git merge vs. open+merge a real GitHub PR; omit it to use whatever PUBLISH_MODE defaults to server-wide. Pass mode: "pr" to open a PR and stop there without merging (needs MCP_PUSH_TOKEN with "Pull requests: Write" scope) — the old submit_for_review behavior, now this same tool. Batch-publishing several entries? Pass revalidateNow: false on every call but the last (or call revalidate standalone once afterward) — one rebuild for N publishes, not N rebuilds; revalidateNow is ignored for mode: "pr" (nothing goes live from opening a PR alone). | slug, collection?, revalidateNow?, mode? |
preview | Push an entry's draft branch to the content repo and get back a hosted preview URL a reviewer can open, if PREVIEW_WORKER_URL is configured — omitted otherwise (the branch still pushes either way). | slug, collection? |
revalidate | Trigger a Cloudflare Pages rebuild via its deploy hook | (none) |
deploy_status | Read the most recent Cloudflare Pages deployment's real state — closes the loop publish/revalidate open, since a deploy hook accepting a POST doesn't prove the build actually succeeded | (none) |
search_entries | Grep-shaped full-text search across every entry in every collection, including drafts not yet merged to main — matches the query against title + raw HTML, case-insensitive substring, not a relevance-ranked search. Distinct from the site's own Pagefind search: that only sees the published live site, not drafts, and isn't a tool a model can call. Real use: hunting stale terminology after a rename, or leftover references to something already removed, across every entry at once instead of reading them one at a time. | query, collection? |
search_images | Grep-shaped substring search over every uploaded image's auto-generated description + alt text, across every entry in every collection (drafts included) — case-insensitive, not relevance-ranked, same posture as search_entries. Returns each match's collection/slug/filename/description/altText, enough to reference the image (<img src="<filename>">) without a separate read. Use this to find an existing image by what's in it instead of remembering filenames. Only images uploaded while an image-description API key was configured (see edit_site) appear here. | query, collection? |
list_images | List every uploaded image with an auto-generated description across every entry (drafts included) — collection/slug/filename/description/altText for each, no query filter. The whole media library at once; use search_images to filter by what's in an image. Only images uploaded while an image-description API key was configured (see edit_site) appear here. | collection? |
rollback | Revert to a previous commit — pass slug to revert just that entry, omit it to revert a whole commit repo-wide | commitHash, slug?, collection? |