@cloudhal/mcp-server

中文文档
0.6.5发布于 2026/11/09Apache-2.0TypeScriptES Module构建来源已验证近 30 天下载 4394

Cloudhal MCP server: semantic site tools (pages, articles, snapshots, preview, publish) governed by the policy engine

原始使用文档

@cloudhal/mcp-server

The Model Context Protocol surface of Cloudhal (spec 2026-07-28, @modelcontextprotocol/server 2.3). ADR-0004 and ADR-0011.

Tools: every tool, with its scopes and whether a person approves it, is in the tool reference below, generated from the definitions in src/tools.ts (node scripts/mcp-tools-doc.ts; CI fails when it is stale). The server lists them in a fixed order. Every tool has JSON Schema input/output (built from the contract schemas), honest annotations and structuredContent. Updates need the current rev (optimistic locking). Every mutation snapshots automatically (exactly one snapshot per call; governance snapshots carry cloudhal.opId).

Taxonomy (RFC-0002): create_entry / update_entry take terms: { [taxonomy]: { set?, add?, remove?, primary? } } with values by id, slug, old slug, name, synonym or singular/plural, resolved by the store; an unknown or ambiguous value is an error with suggestions (unknown_term, ambiguous_term), never an implicit create. tags is a deprecated alias for terms.tag.add. list_entries takes the RFC §5 filter. Agents add terms only through propose_term (allowNewTerms: none → denied, propose → proposed, free → active; an existing match is returned). Structural tools (site:write) always wait for a person; their prompts list the articles touched and every redirect. Agents never redirect off-site, never reclaim slugs and never approve their own proposals (checked before anyone is asked). Store invariant errors map to stable codes (required_term, too_many_terms, …) with the next step in the text. Assignment deltas and governance results (opId, counts, redirects) go into the audit row's input.effect.

Approval: publish, rollback, delete_* and the structural taxonomy/redirect tools return MCP's multi-round-trip input_required with an elicitation (the message carries the diff summary) and an HMAC-signed requestState bound to the tool, the arguments and the principal. The person answers in their client; the call completes only on an explicit accept. Clients without elicitation get a confirmToken to pass on a second identical call (confirmTokenFallback: false turns that off).

Skills: skill://<name>/SKILL.md and skill://<name>/references/<file> resources. A client that follows a skill sends _meta["cloudhal.skill"] = "<name>"; the policy engine then limits the call to that skill's declared scopes.

import { createCloudhalMcpServer } from "@cloudhal/mcp-server";          // McpServer for one principal
import { serveCloudhalStdio } from "@cloudhal/mcp-server/stdio";          // what `cloudhal mcp` runs
import { createCloudhalMcpHandler } from "@cloudhal/mcp-server/http";     // fetch(request, principal) — mounted at /mcp by @cloudhal/api

tools.ts is SDK-independent (defineTools(), runTool() = policy → audit → handler) and is what the tests exercise first; test/e2e.test.ts runs a real client ↔ server pair over the in-memory transport and proves the Sprint 5 exit criterion.

Tool reference

110 tools, in the order the server lists them.

ToolScopesKindApprovalWhat it does
list_sitessite:readread—Sites this principal can operate.
get_sitesite:readread—A site with its page order, locales, theme, published snapshot and per-collection settings (collections.<key>.permalink, e.g. /blog/{slug}; a collection without one lives at /<c…
list_pagescontent:readread—Pages of a site in navigation order (all statuses).
get_pagecontent:readread—One page with its sections and current revision (send rev back when updating).
create_pagecontent:writewriteby the key's modeCreate a draft page and append it to the site's navigation.
update_pagecontent:writewriteby the key's modeReplace a page's title, path, sections or seo, or set its own motion level and chrome (RFC-0025: header default|transparent|hidden, footer default|minimal|hidden; null goes back t…
get_catalogcontent:readread—The components a page surface may use on this site (RFC-0020): Cloudhal's layout, content and interactive primitives plus the theme's block types, with their props, child rules, b…
patch_draftcontent:writewriteby the key's modeBuild or change a page step by step with RFC 6902 JSON Patch operations on /title, /sections and /seo, e.g. {"op":"add","path":"/sections/-","value":{…a surface…}}.
import_surfacecontent:writewriteby the key's modeAdd (or replace) a page surface from another generative-UI format: a2ui takes A2UI v0.9 messages (createSurface, updateComponents, updateDataModel; basic catalog), json-render…
export_surfacecontent:readread—A page's surface section in another generative-UI format: a2ui (A2UI v0.9 messages for the basic catalog, images as absolute URLs when the site has a primary domain) or json-re…
delete_pagecontent:writewrite (destructive)by the key's modeDelete a page and remove it from navigation.
list_entriescontent:readread—Content entries, newest first.
get_entrycontent:readread—One content entry with its body and current revision.
create_entrycontent:writewriteby the key's modeCreate a draft content entry (markdown body) in an existing collection (list_collections; a new one needs create_collection first), optionally filed under existing terms (terms;…
update_entrycontent:writewriteby the key's modeUpdate title, summary, body, slug, status (draft → review → published), terms (terms: add, remove or set categories and tags by id, slug or name) or typed custom fields (fields…
add_correctioncontent:writewriteby the key's modeAppend a correction, clarification or update notice to an article (RFC-0019 §2) when a published story changed in substance.
delete_entrycontent:writewrite (destructive)by the key's modeDelete a content entry.
list_translationscontent:readread—Every language version of a page or entry (its translation group): locale, status, method (original, human, machine, machine-reviewed), whether it is stale (its source changed sin…
list_stale_translationscontent:readread—Translations whose source changed since they were made (or whose source is gone), optionally in one locale: the work queue for keeping languages in step.
get_translation_sourcecontent:readread—What you need to translate a page or entry into locale: the source (translate its title, text, summary and SEO; keep section ids, kinds, links, numbers, images and bindings), fo…
save_translationcontent:writewriteby the key's modeSave your translation of a page or entry into locale as a draft linked to the source's current revision, with your model as its provenance.
search_sitecontent:readread—Find nodes by words instead of listing everything.
get_theme_settingscontent:readread—The theme's design settings (RFC-0017): their schema (colors as #rrggbb, enums, numbers; per-locale titles), the contrast rules colors must meet, and the site's current values.
set_theme_settingssite:writewritealways a personChange the site's design settings (colors, type, spacing: get_theme_settings lists them).
list_block_typescontent:readread—The typed blocks this site can use (RFC-0015): callouts, buttons, video embeds, FAQs and the theme's own.
get_bodycontent:readread—Read a markdown body (an article's, or a page's rich-text section) as blocks: each with its id, hash, type, markdown and who last changed it.
edit_bodycontent:writewritedepends on the callChange a markdown body by block instead of rewriting it: replace a block, replace text inside one, insert, move or delete blocks, insert a typed block (insertBlock: a callout, a b…
diff_nodecontent:readread—Compare one page or article between two versions: the fields that changed, and its body (or each rich-text section) block by block, with the words that changed inside edited block…
get_designsite:readread—Read this first when you build or redesign pages (RFC-0021).
get_design_tokenssite:readread—The site's design tokens as a W3C Design Tokens (DTCG 2025.10) file, for Figma (Tokens Studio), Style Dictionary or a designer: the color roles for light and dark, corner radii, s…
set_designsite:writewritealways a personReplace the site's design rules (DESIGN.md, Markdown, at most 24,000 characters; null removes them).
get_chromesite:readread—The site's header, footer and brand (RFC-0025): what is set, what pages show (the defaults filled in), the form schemas with every allowed value, and the menu keys the header and…
set_chromesite:writewritealways a personChange the site's header and footer (get_chrome lists the fields and allowed values).
set_brandsite:writewritealways a personChange the site's brand (get_chrome lists the fields): logo and logoDark as an image asset of the site (asset:<id>, from list_assets or upload_asset; the site's name shows without…
render_pagepreview:createread—Look at a page's draft as people will see it: renders it in a real browser at desktop (1440), tablet (768) and phone (390) widths and returns screenshots plus automatic checks (si…
list_taxonomiessite:readread—The site's taxonomies (e.g. category, tag) and their rules: required (review/published articles need a primary term), maxPerEntry, allowNewTerms (none: only people add terms…
list_termscontent:readread—Terms of one taxonomy with names per locale, synonyms (altNames), old slugs (slugHistory), parent, status, visibility and usage (articles in total and published, last used).
resolve_termscontent:readread—Which existing terms of a taxonomy the given ids, slugs, names or synonyms mean (the same rules as assigning terms: id → slug → old slug → name → synonym → singular/plural).
propose_termcontent:draft:ownwriteby the key's modeSuggest a new term when no existing one fits (check list_terms / resolve_terms first).
update_termcontent:writewriteby the key's modeChange a term's text only: names, synonyms, archive intro (description) and SEO per locale, and its image.
rename_termsite:writewritealways a personChange a term's slug (its archive URL).
merge_termssite:writewritealways a personMerge duplicate terms into one target term of the same taxonomy: every article is re-filed under the target (primary terms follow), the sources retire and their names and slugs be…
retire_termsite:writewrite (destructive)always a personRetire a term: it is removed from every article, its sub-terms move up, and its archive redirects (301) to redirectToId (or, for categories, to its parent) — without a redirect…
set_term_parentsite:writewritealways a personMove a term under another term of the same hierarchical taxonomy (null: to the top level).
set_term_visibilitysite:writewritealways a personMake a term public (archive, feed and sitemap entry; shown on articles) or internal (no public URL; themes and filters may still use it).
review_termsite:writewritealways a personDecide on a proposed term: approve (it becomes active and, if public, gets its archive), reject (retired and removed from articles) or merge (into an existing term, mergeIntoId).
taxonomy_reportcontent:readread—Findings about the vocabulary: single-use and unused terms, near-duplicates (edit distance ≤ 2, singular/plural) and synonym collisions, empty or oversized categories, archives wi…
create_taxonomysite:writewritealways a personCreate a taxonomy (e.g. series, region) with its rules and archive path.
update_taxonomysite:writewritealways a personChange a taxonomy's rules, labels or archive (the key never changes).
list_redirectssite:readread—The site's redirects (from → to, 301/302, exact/prefix, reason, source node).
create_redirectsite:writewritealways a personRedirect a path the site no longer serves to another path of this site (agents cannot redirect to other hosts).
delete_redirectsite:writewrite (destructive)always a personDelete a redirect; its old path then answers 404 unless something serves it.
list_collectionscontent:readread—The site's collections (RFC-0040): declared ones, ones that already have entries, and posts.
create_collectionsite:writewritealways a personDeclare a new collection (RFC-0040), e.g. events, team or jobs, with its names in the site's default locale (labels), an optional icon, permalink (/<prefix>/{slug}, default /<key>…
update_collectionsite:writewritealways a personChange a collection's names (merged per locale), icon, feed, sitemap, default sort (RFC-0040) or its typed custom fields (fields, the whole list; RFC-0041), list fields, date-dr…
preview_structured_datacontent:readread—The JSON-LD document an entry's page emits under its collection's structured-data preset (RFC-0042: Event, JobPosting, Product, Recipe), built exactly as the site builds it, with…
rename_fieldsite:write, content:writewritealways a personRename a typed custom field's key (RFC-0041 §6): every entry's value moves from from to to; nothing is converted.
change_field_typesite:write, content:writewrite (destructive)always a personChange a typed custom field's type, or a select's multiple (RFC-0041 §6), converting every value by a closed table (text↔richText, text↔number, text↔select, text↔url, date↔datetim…
set_field_localizedsite:write, content:writewritealways a personMake a typed custom field localized (each language version has its own value; translations fall back to the original's) or shared (only the original holds it; translations' own co…
remove_fieldsite:write, content:writewrite (destructive)always a personRemove a typed custom field (RFC-0041 §6): its value is deleted from every entry, then its definition.
set_collection_permalinksite:writewritealways a personMove where a collection's entries live (RFC-0038): permalink "/blog/{slug}" puts collection "posts" at /blog/<slug>; null goes back to the default /<collection>/{slug}.
list_menussite:readread—The site's navigation menus (primary = header, footer, sidebar, custom keys) with id, rev, maxDepth, item count and how many items are hidden on the site.
get_menusite:readread—One menu: the stored tree (send its rev back when writing) and, per item for a locale, whether the site shows it (state), why not (reason: missing, unpublished, other-locale,…
update_menusite:writewritealways a personEdit a menu with operations, applied in order and all or nothing: add {item, parent?, index?}, remove {itemId} (with its subtree), move {itemId, parent?, index?}, update {itemId,…
set_menusite:writewritealways a personReplace a menu's whole tree (or create the menu: omit rev).
delete_menusite:writewrite (destructive)always a personDelete a menu; the site falls back to the theme's derived default for that key (e.g. top-level pages in the header).
list_assetscontent:readread—Files of a site's media library, newest first: images, video, audio, documents and data.
get_assetcontent:readread—One file of the media library with its URL, checksum file and every place that uses it (node, field and title).
upload_assetasset:uploadwriteby the key's modeAdd a file to the site's media library from base64 data (at most 4 MB decoded).
fetch_asset_urlasset:uploadwriteby the key's modeHave the server download a public https file (at most 25 MB) into the site's media library: the server fetches it under strict rules (https only, no internal hosts or IP addresses…
update_assetasset:uploadwriteby the key's modeChange a file's alt text, title or caption (in locale), credit, license, decorative flag, URL slug or an image's focal point (focal: where the subject is, x and y from 0 to 1…
retire_assetasset:managewriteby the key's modeHide a file from the library and pickers so nothing new uses it.
restore_assetasset:managewriteby the key's modeMake a retired file available again.
delete_assetasset:managewrite (destructive)by the key's modeDelete a file from the media library.
create_snapshotcontent:draft:ownwriteby the key's modeFreeze the current state of the site as an immutable, labelled snapshot.
list_snapshotssite:readread—Snapshots of a site, newest first, and which one is live.
diff_snapshotssite:readread—Added, changed and removed nodes between two snapshots.
preview_pagepreview:createread—Render a page (or an article by entryId) to HTML as the site would show it, plus a preview link (signed, to the deployed site, or the cloudhal dev URL).
publishsite:publishwrite (destructive)always a personSnapshot the current state and make it live.
rollbacksite:rollbackwrite (destructive)always a personPoint production at an earlier snapshot (must be an ancestor of the live one).
get_analyticsanalytics:readread—How the site is doing over a range: page views, visits (entrances from other sites or typed in), unique visitors when the site counts them, the estimated cache-hit ratio (on Cloud…
top_contentanalytics:readread—The most viewed pages, articles and archives in a range, with their current title and path (renamed articles show their new ones; deleted ones read as gone) and the change of page…
content_statsanalytics:readread—Readers of one page, article or archive (by id, so the history survives slug changes): page views and visits with the previous period, a series, visits by channel, referrer hosts,…
broken_linksanalytics:readread—Requests that ended in 404 or 410 in a range, most hits first, with the same-site pages that link to them, when they were last seen and a suggested target (an existing redirect, o…
list_commentscomments:readread—Reader comments of a site, newest first (status pending, approved, hidden, spam, deleted, or reported for open reports).
get_comment_threadcomments:readread—One article's comments in display order (top level oldest first, each followed by its replies), with the thread's state and open reports' details.
comments_summarycomments:readread—Counts for a site's comments: by status, pending ages, open reports, the busiest threads, labels, unanswered questions and the daily cap.
label_commentscomments:moderatewritedepends on the callAdd or remove advisory labels on up to 50 comments (spam-suspect, toxic, off-topic, question, needs-reply, praise, personal-data, …) for the people who review them.
moderate_commentscomments:moderatewritedepends on the callChange the status of up to 50 comments.
draft_comment_replycomments:replywritedepends on the callDraft a reply on the site's behalf to an approved comment (plain text, 2–5,000 characters).
set_comment_threadcomments:moderatewritedepends on the callSet an article's comment thread: closed (no new comments, existing ones stay) and hidden (nothing shown) reduce visibility; open, default and a closesAt date wait for a person in…
list_scheduleschedules:readread—What happens on the site between from and to (at most 62 days): releases (scheduled publishes), time gates (embargoes and expiries on articles and pages) and automation runs, with…
get_scheduleschedules:readread—One item from list_schedule by its id (rel_…, gate:<nodeId>:from|until, occ:<automationId>:<at>), with detail.
list_releasesschedules:readread—The site's releases (scheduled publishes) in time order, by state: draft, awaiting_approval, scheduled, running, published, conflict, missed, expired, failed, canceled.
get_releaseschedules:readread—A release with its pinned items (titles, paths, pinned and live versions), what the dependency closure added, overlaps with other releases, locked nodes, the approval and the wait…
propose_releaseschedules:writewritedepends on the callLeave a draft release for a person: the named articles and pages are pinned at their current versions (plus what they need that is not live yet), optionally with a time.
schedule_releaseschedules:writewritedepends on the callPublish a release (or the named articles and pages, pinned now) at a time, or "on-approval".
rescheduleschedules:writewritedepends on the callMove a release to another time.
cancel_scheduleschedules:writewritedepends on the callWithdraw a release: nothing in it is published.
set_embargoschedules:write, content:writewritedepends on the callKeep an article or page off the live site until from (an instant): it is absent from every page, list, feed and sitemap until then, enforced by the site itself.
lift_embargoschedules:writewritedepends on the callAsk a person to publish an article or page before its embargo (remove from, or move it earlier).
schedule_unpublishschedules:write, content:writewritedepends on the callTake an article or page off the live site at a time (it disappears from every page, list, feed and sitemap from then on, enforced by the site itself).
list_automationsschedules:readread—The site's automations: built-in jobs and scheduled agent tasks, with their recurrence, state and next run.
list_runsschedules:readread—What happened at each occurrence of an automation or release, newest first: state (ran or not) and outcome (did something or not), usage, taint and the summary.
get_runschedules:readread—One run with the audit rows, snapshots and approval requests it produced.
begin_runread—Start this automation's run while its window is open (its key works only inside a run).
end_runread—Close your run with a short plain-text summary (what you did, what a person should look at) and its outcome: did-work, nothing-to-do, proposed (you left proposals) or waiting-appr…
pause_automationread—Stop an automation from running again (your own automation's key, or an automation of the person behind your key).
get_moderead—Your current mode, your key's own mode, any time-boxed elevation in force (and when it ends), and the status of your latest elevation request.
request_elevationsite:readread—Ask a person for a more autonomous mode for a limited time (5–1440 minutes), e.g. AUTO for an hour to publish a series of small article updates.

版本与发布记录

@cloudhal/mcp-server 共发布 26 个版本,首次发布于 2026/10/20;过去 12 个月发布了 26 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
0.6.5latest2026/11/091 天前
0.6.42026/11/081 天前
0.6.32026/11/081 天前
0.6.22026/10/2614 天前
0.6.12026/10/2417 天前
0.6.02026/10/2317 天前

关于 @cloudhal/mcp-server 的常见问题

@cloudhal/mcp-server 是什么?

Cloudhal MCP server: semantic site tools (pages, articles, snapshots, preview, publish) governed by the policy engine

如何安装 @cloudhal/mcp-server?

在项目目录运行 npm install @cloudhal/mcp-server,或使用 pnpm add / yarn add / bun add。

@cloudhal/mcp-server 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@cloudhal/mcp-server 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@cloudhal/mcp-server 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=24。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@cloudhal/mcp-server 可以商用吗?

@cloudhal/mcp-server 使用 Apache-2.0 许可。宽松许可:允许商业使用、修改和再分发,并附带明确的专利授权;分发时需保留许可与 NOTICE 文件,修改过的文件要注明改动。以上为概括,不构成法律意见,请以许可原文为准。

@cloudhal/mcp-server 的下载量有多少?

根据 npm 官方下载统计,@cloudhal/mcp-server 在 2026/10/10 – 2026/11/08 这 30 天内被下载 4,394 次,日均约 146 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@cloudhal/mcp-server 还在维护吗?

最新版本 0.6.5 发布于 2026/11/09(1 天前);至今共发布 26 个版本,其中过去 12 个月发布了 26 个;首次发布于 2026/10/20。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。