MCP 服务器参考

本页内容

EmDash 包含一个内置的 Model Context Protocol(MCP)服务器,位于 /_emdash/api/mcp,将内容管理操作作为工具暴露给 AI 助手。

本页涵盖协议详情:身份验证、传输、工具规范、OAuth 发现和错误处理。

身份验证

MCP 服务器支持三种身份验证方式:

方式工作原理
OAuth 2.1 Authorization Code + PKCEMCP 客户端的标准流程。用户在浏览器中批准范围。
个人访问令牌(PAT)在管理面板中创建的长期有效 ec_pat_* 令牌。
设备流CLI 风格的流程,您在浏览器中批准代码。由 emdash login 使用。

会话 Cookie(来自管理 UI)也可以使用,但对外部 MCP 客户端不实用。

范围

令牌的范围限制客户端可以执行的操作。范围在 OAuth 授权期间请求,并在每次工具调用时强制执行。在授权码同意页面上,默认选择所有请求的范围以保持兼容性;用户可以在批准前移除范围,但不能添加客户端未请求的范围。有效授权还受客户端已注册范围和用户角色的限制,EmDash 拒绝空授权。

范围授予访问权限
content:read列出、获取、比较和搜索内容。列出分类法、分类法术语和菜单。
content:write创建、更新、删除、发布、取消发布、安排、取消安排、复制和恢复内容。为向后兼容隐式授予 taxonomies:managemenus:manage
media:read列出和获取媒体项。
media:write注册(创建)、更新和删除媒体元数据。
schema:read列出集合和获取集合 schema。
schema:write创建、更新和删除集合和字段。
taxonomies:manage创建、更新和删除分类法术语。
menus:manage创建、更新和删除导航菜单及其项目。
settings:read读取站点范围的设置。
settings:manage更新站点范围的设置。
mcp:tools调用任何插件中显式启用的 MCP 工具。
mcp:tools:<pluginId>调用一个插件中显式启用的 MCP 工具。
admin所有操作的完全访问权限。

admin 范围授予核心操作的访问权限,但不授予插件 MCP 访问权限。插件工具始终需要 mcp:tools 或匹配的插件特定范围。基于会话的身份验证根据用户角色和插件的显式管理员启用来确定访问权限。

content:write 隐式授予 taxonomies:managemenus:manage,因此在这些范围拆分之前发放的个人访问令牌无需重新发放即可继续使用。新令牌应请求细粒度范围。

角色要求

除了范围之外,某些工具还需要最低的 RBAC 角色。两者都必须满足——即使令牌拥有正确的范围,如果调用用户的角色过低也会失败。

插件工具使用其底层路由声明的权限。在管理员启用该插件的 MCP 表面之前,它们不会出现在 tools/list 中。工具名称使用确定性的 <pluginId>__<localName> 形式,调用记录在审计日志中,包含插件、工具、路由和操作者来源。

操作最低角色
内容读取订阅者(10)用于已发布项目;贡献者(20)用于草稿、已安排、回收站和修订版本
内容创建贡献者(20)
编辑/删除自己的内容作者(30)
内容发布作者(30)用于自己的项目;编辑者(40)用于操作他人的项目
Schema 读取编辑者(40)
Schema 写入管理员(50)
分类法管理编辑者(40)
菜单管理编辑者(40)
设置读取编辑者(40)
设置管理管理员(50)
媒体上传(media_upload贡献者(20)
媒体注册(media_create作者(30)
媒体使用修复管理员(50)

参见身份验证指南了解角色定义。

传输

服务器使用无状态模式的 Streamable HTTP 传输。每个请求都是独立的——没有会话或长连接。

  • POST /_emdash/api/mcp — 发送 JSON-RPC 工具调用
  • GET /_emdash/api/mcp — 返回 405(无状态模式下无 SSE)
  • DELETE /_emdash/api/mcp — 返回 405(无会话可关闭)

响应遵循 JSON-RPC 2.0 格式。错误使用标准 JSON-RPC 错误码,范围和权限失败使用 MCP 特定码。

工具

服务器跨八个领域暴露工具:内容、schema、媒体、搜索、分类法、菜单、修订版本和设置。每个工具以 JSON 文本内容返回结果,失败时返回带有 isError: true 的错误消息。

内容工具

content_list

列出集合中的内容项,支持可选的过滤和分页。

参数类型必需描述
collectionstring集合 slug(例如 postspages
statusstring过滤:draftpublishedscheduled
limitinteger最大返回项数(1-100,默认 50)
cursorstring来自上一响应的分页游标
orderBystring排序字段(例如 created_atupdated_at
orderstring排序方向:ascdesc(默认 desc
localestring按语言区域过滤(例如 enfr)。仅在 i18n 时相关。

范围: content:read | 只读:

content_get

按 ID 或 slug 获取单个内容项。返回所有字段值、元数据和 _rev 令牌。content_updatecontent_publishcontent_unpublishcontent_discard_draft 需要该令牌,因此在调用它们之前先在这里读取项目。

参数类型必需描述
collectionstring集合 slug
idstring内容项 ID(ULID)或 slug
localestring用于 slug 查找的语言区域。ID 是全局唯一的。

范围: content:read | 只读:

content_create

创建新的内容项。data 对象应包含与集合 schema 匹配的字段值——使用 schema_get_collection 检查可用字段。默认创建为 draft

参数类型必需描述
collectionstring集合 slug
dataobject键值对形式的字段值
slugstringURL slug(省略时从标题自动生成)
statusstring初始状态:draftpublished(默认 draft
localestring此内容的语言区域(默认为站点默认值)
translationOfstring此项是其翻译的项目 ID

范围: content:write

content_update

更新现有内容项。仅包含要更改的字段——未指定的字段保持不变。当未设置 status 时,对已发布项目的更改作为草稿暂存:响应显示新值,而实时版本保持旧值直到 content_publish

参数类型必需描述
collectionstring集合 slug
idstring内容项 ID 或 slug
dataobject要更新的字段值
slugstring新 URL slug
statusstring新状态:draftpublished
_revstring来自 content_get 的修订令牌。如果项目在该读取后已更改,更新将因冲突而失败。

范围: content:write

content_delete

通过移至回收站软删除内容项。使用 content_restore 撤销,或 content_permanent_delete 永久删除。

参数类型必需描述
collectionstring集合 slug
idstring内容项 ID 或 slug

范围: content:write | 破坏性:

content_restore

从回收站恢复软删除的内容项。

参数类型必需描述
collectionstring集合 slug
idstring内容项 ID 或 slug

范围: content:write

content_permanent_delete

永久且不可逆地删除已回收的内容项。项目必须先在回收站中。

参数类型必需描述
collectionstring集合 slug
idstring内容项 ID 或 slug

范围: content:write | 破坏性:

content_publish

发布内容项,使其在站点上可见。从当前草稿创建已发布的修订版本。后续编辑创建新草稿而不影响实时版本,直到重新发布。不带 publishedAt 重新发布会重用保留的发布日期。

参数类型必需描述
collectionstring集合 slug
idstring内容项 ID 或 slug
publishedAtstringISO 8601 发布日期。设置它需要 content:publish_any
_revstring来自 content_get 的修订令牌。如果项目在该读取后已更改,调用将因冲突而失败。

范围: content:write

content_unpublish

将已发布的项目恢复为草稿状态。它将不再在实时站点上可见,但其内容和发布日期会被保留。

参数类型必需描述
collectionstring集合 slug
idstring内容项 ID 或 slug
_revstring来自 content_get 的修订令牌。如果项目在该读取后已更改,调用将因冲突而失败。

范围: content:write

content_schedule

安排内容项在未来发布。它将在指定的日期/时间自动发布。

参数类型必需描述
collectionstring集合 slug
idstring内容项 ID 或 slug
scheduledAtstringISO 8601 日期时间(例如 2026-06-01T09:00:00Z

范围: content:write

content_unschedule

取消先前安排的发布。项目保持其当前状态;仅清除 scheduledAt 时间戳。幂等——对未安排的项目调用是无操作的。

参数类型必需描述
collectionstring集合 slug
idstring内容项 ID 或 slug

范围: content:write

content_compare

比较内容项的已发布(实时)版本与其当前草稿。返回两个版本和一个指示是否有更改的标志。

参数类型必需描述
collectionstring集合 slug
idstring内容项 ID 或 slug

范围: content:read | 只读:

content_discard_draft

丢弃当前草稿并恢复到最后的已发布版本。仅适用于至少发布过一次的项目。

参数类型必需描述
collectionstring集合 slug
idstring内容项 ID 或 slug
_revstring来自 content_get 的修订令牌。如果项目在该读取后已更改,调用将因冲突而失败。

范围: content:write | 破坏性:

content_list_trashed

列出集合回收站中软删除的内容项。

参数类型必需描述
collectionstring集合 slug
limitinteger最大项数(1-100,默认 50)
cursorstring分页游标

范围: content:read | 只读:

content_duplicate

创建现有内容项的副本。副本创建为草稿,标题附加”(Copy)“并自动生成 slug。

参数类型必需描述
collectionstring集合 slug
idstring要复制的内容项 ID 或 slug

范围: content:write

content_translations

获取内容项的所有语言区域变体。返回翻译组和每个语言区域版本的摘要。仅在启用 i18n 时相关。

参数类型必需描述
collectionstring集合 slug
idstring内容项 ID 或 slug

范围: content:read | 只读:

Schema 工具

schema_list_collections

列出 CMS 中定义的所有内容集合。返回 slug、标签、支持的特性和时间戳。

无参数。

范围: schema:read | 最低角色: 编辑者 | 只读:

schema_get_collection

获取集合的详细信息,包括所有字段定义。字段描述数据模型:名称、类型、约束和验证规则。使用此工具了解 content_createcontent_update 期望的内容。

参数类型必需描述
slugstring集合 slug(例如 posts

范围: schema:read | 最低角色: 编辑者 | 只读:

schema_create_collection

创建新的内容集合。这会创建数据库表和 schema 定义。slug 必须是以字母开头的小写字母数字和下划线。

参数类型必需描述
slugstring唯一标识符(/^[a-z][a-z0-9_]*$/
labelstring显示名称(复数,例如 “Blog Posts”)
labelSingularstring单数显示名称
descriptionstring此集合的描述
iconstring管理 UI 的图标名称
supportsstring[]特性:draftsrevisionspreviewschedulingsearchseo(默认:['drafts', 'revisions']

范围: schema:write | 最低角色: 管理员

schema_update_collection

更新现有集合而不删除其表、字段或内容。仅更改提供的设置;省略的设置保持当前值。集合 slug 不能更改。

参数类型必需描述
slugstring要更新的集合 slug
labelstring新的复数显示名称
labelSingularstring新的单数显示名称
descriptionstring新的集合描述
iconstring新的管理 UI 图标名称
supportsstring[]要启用的完整特性列表;省略保持当前列表
urlPatternstring | null新的公共 URL 模式;null 清除它
hasSeoboolean集合是否支持 SEO 元数据
commentsEnabledboolean是否启用评论
commentsModerationstring审核策略:allfirst_timenone
commentsClosedAfterDaysinteger在此天数后关闭评论;0 保持开放
commentsAutoApproveUsersboolean自动批准来自已认证用户的评论

范围: schema:write | 最低角色: 管理员

schema_delete_collection

删除集合及其数据库表。这是不可逆的,会删除集合中的所有内容。

参数类型必需描述
slugstring要删除的集合 slug
forceboolean即使集合有内容也强制删除

范围: schema:write | 最低角色: 管理员 | 破坏性:

schema_create_field

向集合的 schema 添加新字段。这会向数据库表添加列。

参数类型必需描述
collectionstring集合 slug
slugstring字段标识符(/^[a-z][a-z0-9_]*$/
labelstring显示名称
typestring数据类型(见下文)
requiredboolean该字段是否必需
uniqueboolean值是否必须唯一
defaultValueany新项目的默认值
validationobject约束:minmaxminLengthmaxLengthpatternoptions
optionsobject小部件配置:collection(用于引用)、rows(用于文本区域)
searchableboolean包含在全文搜索索引中
indexedboolean启用按此字段的索引排序
translatableboolean该字段是否可翻译(默认 true)

字段类型:stringtextnumberintegerbooleandatetimeselectmultiSelectportableTextimagefilereferencejsonslug

对于 selectmultiSelect 类型,在 validation.options 中提供允许的值。

范围: schema:write | 最低角色: 管理员

schema_update_field

更新现有字段而不删除其列或存储的值。仅更改提供的设置;省略的设置保持当前值。stringtextslug 可以相互更改。需要内容或列迁移的其他类型更改和设置会被拒绝并提供迁移指引。无效的正则表达式和矛盾的验证范围在任何 schema 元数据更改之前被拒绝。

参数类型必需描述
collectionstring包含该字段的集合
fieldSlugstring要更新的字段 slug
labelstring新显示名称
typestring新字段类型;只有 stringtextslug 别名可以就地更改
requiredboolean该字段是否必需;更改需要手动内容迁移
uniqueboolean字段值是否必须唯一;更改需要手动内容迁移
defaultValueany新内容的默认值
validationobject | null验证约束;null 清除它们
widgetstring管理编辑器小部件名称
optionsobject小部件配置
sortOrderinteger内容编辑器中的字段顺序
searchableboolean全文搜索是否索引该字段
indexedboolean创建或移除用于结构化排序的物理索引
translatableboolean值是否因语言区域而异;更改为 false 需要手动内容迁移

范围: schema:write | 最低角色: 管理员

schema_delete_field

从集合中移除字段。这会删除列和该字段中的所有数据。不可逆。

参数类型必需描述
collectionstring集合 slug
fieldSlugstring要移除的字段 slug

范围: schema:write | 最低角色: 管理员 | 破坏性:

媒体工具

media_list

列出已上传的媒体文件,支持可选的 MIME 类型过滤和分页。

参数类型必需描述
mimeTypestring按 MIME 类型前缀过滤(例如 image/application/pdf
limitinteger最大项数(1-100,默认 50)
cursorstring分页游标

范围: media:read | 只读:

media_upload

从 base64 编码数据或外部 URL 上传媒体文件并在媒体库中注册。返回带有 idstorageKeyurl 的媒体项——可通过 content_create / content_update 直接从内容字段(例如 featured_image)引用。

上传通过内容哈希去重:重新上传相同字节返回带有 deduplicated: true 的现有项。图片上传自动丰富尺寸、blurhash 占位符和主色调。

参数类型必需描述
filenamestring包含扩展名的文件名(例如 cover.png
base64stringbase64 / url 二选一Base64 编码的文件内容
urlstringbase64 / url 二选一获取文件的公共 http(s) URL
contentTypestring使用 base64 时需要MIME 类型(例如 image/png)。使用 url 时默认为响应的 Content-Type 头。
altstring无障碍替代文本

范围: media:write | 最低角色: 贡献者

media_create

注册已上传到存储的媒体文件。调用者负责将文件放置在 storageKey(通常使用来自管理 UI 或单独 API 的签名上传 URL)。此工具持久化元数据记录,使文件可通过 media_list / media_get 发现并被内容引用。

参数类型必需描述
filenamestring原始文件名(例如 logo.png
mimeTypestringMIME 类型(例如 image/png
storageKeystring文件上传到的存储路径/键
sizeinteger文件大小(字节)
widthinteger图片宽度(像素)
heightinteger图片高度(像素)
contentHashstring文件内容的哈希(用于去重)
blurhashstring图片占位符的 Blurhash
dominantColorstring图片主色调的十六进制颜色字符串

范围: media:write | 最低角色: 作者

media_get

按 ID 获取单个媒体文件的详情。返回元数据,包括文件名、MIME 类型、大小、尺寸、替代文本和 URL。

参数类型必需描述
idstring媒体项 ID

范围: media:read | 只读:

media_update

更新已上传媒体文件的元数据。文件本身不能更改。

参数类型必需描述
idstring媒体项 ID
altstring无障碍替代文本
captionstring标题文本
widthinteger图片宽度(像素)
heightinteger图片高度(像素)

范围: media:write

media_delete

永久删除媒体文件。从数据库和存储中移除记录和文件。引用此媒体的内容将出现断开的引用。

参数类型必需描述
idstring媒体项 ID

范围: media:write | 破坏性:

media_usage_repair

修复一个集合或所有集合的内容媒体使用索引。修复同步运行,在大型站点上可能很慢或开销大;尽可能使用集合范围。

参数类型必需描述
scope"collection" | "all"修复一个集合还是所有集合
collectionstring集合范围时需要集合 slug;scopeall 时省略

结果有 completepartialfailedstale 的结构化 status,加上聚合和每集合的源计数。所有四种状态都是成功的 MCP 工具结果,因此调用者必须检查 status 而不是依赖 isError。身份验证、验证或意外修复错误返回 isError: true

范围: admin | 最低角色: 管理员

搜索工具

跨内容集合的全文搜索。集合必须在其 supports 列表中包含 search,字段必须标记为 searchable

参数类型必需描述
querystring搜索查询文本
collectionsstring[]限制搜索到特定集合 slug
localestring按语言区域过滤结果
limitinteger最大结果数(1-50,默认 20)

范围: content:read | 只读:

分类法工具

taxonomy_list

列出所有分类法定义(例如 categories、tags)。返回名称、标签、是否层级化和关联的集合。

参数类型必需描述
localestring按语言区域过滤(省略则列出所有语言区域变体)

范围: content:read | 只读:

taxonomy_get

按名称获取单个分类法定义。返回名称、标签、单数标签、是否层级化、关联的集合、语言区域和翻译组。传入 locale 以解析特定翻译。

参数类型必需描述
namestring分类法名称(例如 categoriestags
localestring要解析定义的语言区域

范围: content:read | 只读:

taxonomy_create

创建新的分类法定义。定义是按语言区域的;当同一分类法名称存在于多个翻译中时传入 localecollections 命名此分类法适用于哪些内容类型。如果设置了 translationOf,新定义加入源的翻译组,并在省略时从源继承 hierarchicalcollections

参数类型必需描述
namestring分类法名称(/^[a-z][a-z0-9_]*$/
labelstring显示名称
labelSingularstring单数显示名称
hierarchicalboolean术语是否支持父/子关系
collectionsstring[]此分类法适用的集合 slug
localestring此定义的语言区域(例如 fr-fr
translationOfstring从其创建此语言区域变体的现有分类法 ID

范围: taxonomies:manage | 最低角色: 编辑者

taxonomy_update

更新现有的分类法定义。分类法 name 不能更改。传入 locale 以更新特定翻译;否则更新最低匹配的语言区域。任何字段都可以省略以保持不变。

参数类型必需描述
namestring要更新的分类法名称
labelstring新显示名称
labelSingularstring | null新单数显示名称;null 清除
hierarchicalboolean术语是否支持父/子关系
collectionsstring[]此分类法适用的集合 slug
localestring要更新的定义的语言区域

范围: taxonomies:manage | 最低角色: 编辑者

taxonomy_delete

删除分类法定义及其在所有语言区域中的所有术语,以及这些术语持有的任何内容分配。这不能撤消。

参数类型必需描述
namestring要删除的分类法名称

范围: taxonomies:manage | 最低角色: 编辑者 | 破坏性:

taxonomy_list_terms

分页列出分类法中的术语。

参数类型必需描述
taxonomystring分类法名称(例如 categoriestags
limitinteger最大项数(1-100,默认 50)
cursorstring分页游标

范围: content:read | 只读:

taxonomy_create_term

在分类法中创建新术语。对于层级分类法,指定 parentId 以创建子术语。父级的祖先链不得超过 100 层。

参数类型必需描述
taxonomystring分类法名称
slugstringURL 安全标识符
labelstring显示名称
parentIdstring父术语 ID(用于层级分类法)
descriptionstring术语描述

范围: taxonomies:manage | 最低角色: 编辑者

taxonomy_update_term

更新分类法中的现有术语。任何字段都可以省略以保持不变。重命名 slug 不得与同一分类法中的另一个术语冲突。将 parentId 设为 null 以从父级分离。新父级必须存在、属于同一分类法且不引入循环。

参数类型必需描述
taxonomystring分类法名称
termSlugstring要更新的术语的当前 slug
slugstring新 slug(在分类法中必须唯一)
labelstring新显示名称
parentIdstring | null新父术语 ID;null 分离
descriptionstring新描述

范围: taxonomies:manage | 最低角色: 编辑者

taxonomy_delete_term

从分类法中永久删除术语。标记了该术语的任何内容都会失去关联。不能删除有子级的术语——先删除子级。

参数类型必需描述
taxonomystring分类法名称
termSlugstring要删除的术语的 slug

范围: taxonomies:manage | 最低角色: 编辑者 | 破坏性:

菜单工具

列出导航菜单。菜单是按语言区域的:传入 locale 只返回一个语言区域的行,或省略列出所有语言区域变体。

参数类型必需描述
localestring按语言区域过滤(省略则列出所有语言区域变体)

范围: content:read | 只读:

按名称获取菜单,包括其所有按顺序排列的项目。项目有标签、URL、类型和可选的父级用于嵌套。当同名菜单存在于多个语言区域时,传入 locale 以解析预期的翻译。

参数类型必需描述
namestring菜单名称(例如 mainfooter
localestring要解析菜单的语言区域

范围: content:read | 只读:

创建新的导航菜单。name 是站点模板使用的稳定标识符;label 是管理面板中显示的人类可读名称。菜单是按语言区域的,当同名菜单存在于多个翻译中时传入 locale。之后使用 menu_set_items 添加项目。如果设置了 translationOf,则还必须设置 locale

参数类型必需描述
namestring稳定标识符(/^[a-z][a-z0-9_]*$/
labelstring管理面板的显示名称
localestring此菜单的语言区域(例如 fr-fr
translationOfstring从其创建此语言区域变体的现有菜单 ID

范围: menus:manage | 最低角色: 编辑者

更新菜单的标签。name(稳定标识符)不能更改。在多语言区域安装中,传入 locale 以更新正确的翻译。

参数类型必需描述
namestring要更新的菜单名称
labelstring新显示标签
localestring要更新的菜单的语言区域

范围: menus:manage | 最低角色: 编辑者

删除菜单及其所有项目。不能撤消。在多语言区域安装中,传入 locale 以仅移除预期的翻译。

参数类型必需描述
namestring要删除的菜单名称
localestring要删除的菜单的语言区域

范围: menus:manage | 最低角色: 编辑者 | 破坏性:

在一次调用中替换菜单的整个项目列表。原子操作:现有项目被删除,新列表按提供的顺序插入。使用此工具而非逐项添加/移除操作,以确保结果顺序和父级链接明确。在多语言区域安装中,传入 locale 以仅重写预期的翻译。

项目按数组索引定位。嵌套通过 parentIndex 表达——parentIndex: 0 的项目嵌套在索引 0 处的项目下。父级必须在列表中较早出现。没有 parentIndex 的项目是顶级的。

参数类型必需描述
namestring要更新的菜单名称
localestring要重写的菜单的语言区域
itemsMenuItem[]有序的菜单项列表(见下文)

每个 MenuItem 有:

字段类型必需描述
labelstring项目显示文本
typestringcustompageposttaxonomycollection 之一
customUrlstringtype: "custom" 项目的 URL(否则忽略)
referenceCollectionstring内容引用的目标集合 slug
referenceIdstring引用的目标内容/术语 ID
titleAttrstringHTML title 属性
targetstringHTML target 属性(例如 _blank
cssClassesstring空格分隔的 CSS 类
parentIndexinteger父项目的数组索引。顶级项目省略。

范围: menus:manage | 最低角色: 编辑者

修订版本工具

revision_list

列出内容项的修订历史,最新的排在前面。需要集合支持 revisions

参数类型必需描述
collectionstring集合 slug
idstring内容项 ID 或 slug
limitinteger最大修订数(1-50,默认 20)

范围: content:read | 只读:

revision_restore

将内容项恢复到先前的修订版本。用指定修订版本的数据替换当前草稿。不会自动发布——如果需要,之后使用 content_publish

参数类型必需描述
revisionIdstring要恢复到的修订版本 ID

范围: content:write

设置工具

站点范围的设置——标题、标语、logo、favicon、规范 URL、默认页面大小、日期和时间格式、社交账号和 SEO 默认值。

settings_get

获取所有站点范围的设置。媒体引用(logofaviconseo.defaultOgImage)包含解析后的 URL 和底层的 mediaId。未设置的值从响应中省略。

无参数。

范围: settings:read | 最低角色: 编辑者 | 只读:

settings_update

更新一个或多个站点范围的设置。部分更新:仅更改提供的字段;省略的字段保持不变。更新后返回完整的设置对象。

要设置媒体引用(logofaviconseo.defaultOgImage),传入带有 mediaId(和可选 alt)的对象。媒体项必须已存在——先使用 media_create

参数类型必需描述
titlestring站点标题
taglinestring与标题一起显示的简短描述
logoMediaRefLogo 媒体引用({ mediaId, alt? }
faviconMediaRefFavicon 媒体引用
urlstring规范站点 URL(http 或 https)。空字符串清除它。
postsPerPageinteger内容列表的默认页面大小(1-100)
dateFormatstring日期格式令牌字符串
timezonestringIANA 时区标识符
socialobject社交账号——twittergithubfacebookinstagramlinkedinyoutube
seoobjectSEO 默认值(见下文)

seo 对象接受:

字段类型描述
titleSeparatorstring页面标题和站点标题之间的分隔符(例如 " | " 用于竖线)
defaultOgImageMediaRef内容没有 OG 图片时的默认 Open Graph 图片
robotsTxtstring自定义 robots.txt 内容。省略使用 EmDash 默认值。
googleVerificationstringGoogle Search Console 验证令牌
bingVerificationstringBing Webmaster Tools 验证令牌

范围: settings:manage | 最低角色: 管理员

OAuth 发现

大多数 MCP 客户端会为您处理这些;本节适用于直接针对 EmDash 构建 MCP 客户端。支持 OAuth 2.1 的客户端从服务器发布的两个元数据文档中发现如何进行身份验证:

受保护资源元数据

在以下端点请求受保护资源元数据:

GET /.well-known/oauth-protected-resource

服务器以资源标识符、其授权服务器和支持的范围响应:

{
  "resource": "https://example.com/_emdash/api/mcp",
  "authorization_servers": ["https://example.com/_emdash"],
  "scopes_supported": [
    "content:read", "content:write",
    "media:read", "media:write",
    "schema:read", "schema:write",
    "taxonomies:manage", "menus:manage",
    "settings:read", "settings:manage",
    "admin"
  ],
  "bearer_methods_supported": ["header"]
}

授权服务器元数据

在以下端点请求授权服务器元数据:

GET /.well-known/oauth-authorization-server/_emdash

服务器以其支持的端点、范围和授权类型响应:

{
  "issuer": "https://example.com/_emdash",
  "authorization_endpoint": "https://example.com/_emdash/oauth/authorize",
  "token_endpoint": "https://example.com/_emdash/api/oauth/token",
  "scopes_supported": ["content:read", "content:write", "..."],
  "response_types_supported": ["code"],
  "grant_types_supported": [
    "authorization_code",
    "refresh_token",
    "urn:ietf:params:oauth:grant-type:device_code"
  ],
  "code_challenge_methods_supported": ["S256"],
  "token_endpoint_auth_methods_supported": ["none"],
  "device_authorization_endpoint": "https://example.com/_emdash/api/oauth/device/code"
}

当未认证的请求命中 MCP 端点时,服务器返回:

HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer resource_metadata="https://example.com/.well-known/oauth-protected-resource"

这触发标准的 MCP 客户端发现流程。

错误处理

工具错误以带有 isError: true 的文本内容返回。消息以稳定的 [CODE] 为前缀,相同的代码在 _meta.code 中重复:

{
  "content": [{ "type": "text", "text": "[NOT_FOUND] Collection 'nonexistent' not found" }],
  "isError": true,
  "_meta": { "code": "NOT_FOUND" }
}

范围和权限错误使用相同的工具错误信封:

{
  "content": [
    { "type": "text", "text": "[INSUFFICIENT_SCOPE] Insufficient scope: requires content:write" }
  ],
  "isError": true,
  "_meta": { "code": "INSUFFICIENT_SCOPE" }
}

传输层错误(服务器配置错误、未处理的异常)返回 JSON-RPC 错误码 -32603(内部错误),不泄露实现细节。