MCP 伺服器參考

本頁內容

EmDash 在 /_emdash/api/mcp 提供內建 Model Context Protocol(MCP)伺服器。MCP 用戶端透過它讀取和管理內容、署名、結構、媒體、分類法、選單、修訂和設定,並匯出或匯入整個網站。

驗證

MCP 端點需要 Bearer 權杖。EmDash 支援以下權杖流程:

方式用途
OAuth 2.1 Authorization Code with Proof Key for Code Exchange (PKCE)互動式 MCP 用戶端。使用者在瀏覽器中核准請求的 scope。
Personal access token面向用戶端或自動化的長期存取。權杖使用 ec_pat_ 前綴,在管理後台建立。
OAuth 2.0 Device Authorization Grant命令列用戶端,要求使用者在瀏覽器中核准代碼。emdash login 使用此流程。

工作階段 Cookie 無法用於驗證 MCP 端點。

Scopes

OAuth 和個人存取權杖限制用戶端可呼叫的工具。使用者角色另行檢查,因此 scope 不會授予使用者沒有的權限。

Scope存取
content:read讀取和搜尋內容、署名、分類法、術語、選單和修訂。類草稿內容還需要使用者的 content:read_drafts 權限。
content:write建立和修改內容、署名和修訂。為相容現有權杖,還授予 taxonomies:manage 和 menus:manage。
media:read讀取媒體記錄。
media:write上傳、註冊、更新和刪除媒體。
schema:read讀取集合和欄位。
schema:write建立、更新和刪除集合和欄位。
taxonomies:manage建立、更新和刪除分類法定義和術語。
menus:manage建立、更新和刪除選單和選單項目。
settings:read讀取網站設定。
settings:manage更新網站設定。
mcp:tools呼叫任何已啟用外掛暴露的 MCP 工具。
mcp:tools:<pluginId>呼叫某一已啟用外掛暴露的 MCP 工具。
transfer:export將整個網站匯出為網站套件並下載。
transfer:analyze上傳網站套件並分析以準備匯入。
transfer:execute啟動、推進、取消和放棄網站匯入。
admin呼叫所有核心工具,包括網站轉移工具。外掛工具仍需要 mcp:tools 或外掛專用 scope。

admin scope 包含 transfer:export、transfer:analyze 和 transfer:execute。每個轉移 scope 僅授予自身操作,且需要管理員角色。若希望用戶端(如智能體)在不匯出或匯入的情況下分析網站套件,應授予 transfer:analyze 而非 admin。

授權碼同意頁允許使用者移除請求的 scope。EmDash 還會將請求與用戶端註冊的 scope 和使用者角色取交集,並拒絕空授權。

角色要求

下表列出各類能力的最低角色要求。當使用者操作他人內容時,所有權檢查可能要求更高角色。

能力最低角色
讀取已發布內容、媒體、分類法、術語和選單Subscriber
讀取草稿、排程內容、資源回收筒、對比和修訂Contributor
建立內容或上傳媒體Contributor
編輯或發布自己的內容並註冊媒體Author
管理署名、分類法、選單或所有使用者的內容Editor
讀取結構或設定Editor
修改結構或設定、永久刪除內容或修復媒體使用Admin
匯出或匯入整個網站Admin

完整角色定義見使用者角色。

傳輸

伺服器使用無狀態 Streamable HTTP。每個請求獨立;伺服器不保持 MCP 工作階段或 Server-Sent Events 連線。

方法端點行為
POST/_emdash/api/mcp接受 JSON-RPC 初始化、工具列表和工具呼叫。
GET/_emdash/api/mcp傳回 405 Method Not Allowed。
DELETE/_emdash/api/mcp傳回 405 Method Not Allowed。

回應使用 JSON-RPC 2.0。建構工具請求前請呼叫 tools/list 取得目前輸入 schema 和 MCP 註解。

工具清單

以下清單與 tools/list 傳回的靜態工具一致。包含註冊標題,因為用戶端可能顯示標題而非工具名稱。

內容工具

ToolRegistered titleRequired scope
content_listList Contentcontent:read
content_getGet Contentcontent:read
content_createCreate Contentcontent:write
content_updateUpdate Contentcontent:write
content_deleteDelete Content (Trash)content:write
content_restoreRestore Contentcontent:write
content_permanent_deletePermanently Delete Contentcontent:write
content_publishPublish Contentcontent:write
content_unpublishUnpublish Contentcontent:write
content_scheduleSchedule Contentcontent:write
content_unscheduleCancel Scheduled Publicationcontent:write
content_compareCompare Live vs Draftcontent:read
content_discard_draftDiscard Draftcontent:write
content_list_trashedList Trashed Contentcontent:read
content_duplicateDuplicate Contentcontent:write
content_translationsGet Content Translationscontent:read

署名工具

ToolRegistered titleRequired scope
byline_listList Bylinescontent:read
byline_getGet Bylinecontent:read
byline_createCreate Bylinecontent:write
byline_updateUpdate Bylinecontent:write
byline_deleteDelete Bylinecontent:write
byline_translationsList Byline Translationscontent:read

結構工具

ToolRegistered titleRequired scope
schema_list_collectionsList Collectionsschema:read
schema_get_collectionGet Collection Schemaschema:read
schema_list_block_typesList Block Typesschema:read
schema_get_block_typeGet Block Typeschema:read
schema_create_block_typeCreate Block Typeschema:write
schema_update_block_typeUpdate Block Typeschema:write
schema_activate_block_type_versionActivate Block Type Versionschema:write
schema_create_collectionCreate Collectionschema:write
schema_delete_collectionDelete Collectionschema:write
schema_update_collectionUpdate Collectionschema:write
schema_create_fieldAdd Field to Collectionschema:write
schema_delete_fieldRemove Field from Collectionschema:write
schema_update_fieldUpdate Fieldschema:write

媒體工具

ToolRegistered titleRequired scope
media_listList Mediamedia:read
media_createConfirm Signed Media Uploadmedia:write
media_uploadUpload Mediamedia:write
media_getGet Media Itemmedia:read
media_updateUpdate Media Metadatamedia:write
media_deleteDelete Mediamedia:write
media_usage_repairRepair Media Usage Indexadmin

搜尋工具

ToolRegistered titleRequired scope
searchSearch Contentcontent:read

分類法工具

ToolRegistered titleRequired scope
taxonomy_listList Taxonomiescontent:read
taxonomy_getGet Taxonomy Definitioncontent:read
taxonomy_createCreate Taxonomy Definitiontaxonomies:manage
taxonomy_updateUpdate Taxonomy Definitiontaxonomies:manage
taxonomy_deleteDelete Taxonomy Definitiontaxonomies:manage
taxonomy_list_termsList Taxonomy Termscontent:read
taxonomy_create_termCreate Taxonomy Termtaxonomies:manage
taxonomy_update_termUpdate Taxonomy Termtaxonomies:manage
taxonomy_delete_termDelete Taxonomy Termtaxonomies:manage
taxonomy_term_translationsList Term Translationscontent:read

選單工具

ToolRegistered titleRequired scope
menu_listList Menuscontent:read
menu_getGet Menu with Itemscontent:read
menu_translationsList Menu Translationscontent:read
menu_createCreate Menumenus:manage
menu_updateUpdate Menumenus:manage
menu_deleteDelete Menumenus:manage
menu_set_itemsSet Menu Itemsmenus:manage

修訂工具

ToolRegistered titleRequired scope
revision_listList Revisionscontent:read
revision_restoreRestore Revisioncontent:write

設定工具

ToolRegistered titleRequired scope
settings_getGet Site Settingssettings:read
settings_updateUpdate Site Settingssettings:manage

網站轉移工具

transfer:* 表示 transfer:export、transfer:analyze 或 transfer:execute 中的任一項。admin scope 滿足本表所有要求。

ToolRegistered titleRequired scope
site_transfer_capabilitiesGet Site Transfer Capabilitiestransfer:*
site_export_startStart Site Exporttransfer:export
site_export_statusGet Site Export Statustransfer:export
site_import_analyzeAnalyze Site Importtransfer:analyze
site_import_startStart Site Importtransfer:execute
site_import_statusGet Site Import Statustransfer:*
site_import_resumeResume Site Importtransfer:execute
site_import_receiptGet Site Import Receipttransfer:*

管理員核准請求時,site_export_start 和 site_import_start 也可接受無對應 scope 的權杖。對於已核准請求所啟動的操作,site_export_status、site_import_status、site_import_resume 和 site_import_receipt 也可接受同一權杖且無需 scope。

使用工具 schema

tools/list 傳回每個工具的描述、JSON 輸入 schema 和註解。建構呼叫前請閱讀這些中繼資料,以便用戶端使用已安裝 EmDash 版本支援的欄位、允許值和限制。

例如,更新文章的用戶端先呼叫 content_get 並保留傳回的 _rev,然後可傳送如下 JSON-RPC 請求:

{
	"jsonrpc": "2.0",
	"id": 2,
	"method": "tools/call",
	"params": {
		"name": "content_update",
		"arguments": {
			"collection": "articles",
			"id": "01JARTICLE0000000000000000",
			"data": { "title": "Updated title" },
			"_rev": "opaque-revision-token"
		}
	}
}

結果以 JSON 文字形式傳回在第一個內容區塊中。帶輸出 schema 的工具還可能在 structuredContent 中傳回相同值。

內容生命週期與署名

內容生命週期參考定義 MCP、REST、CLI 和管理後台共用的狀態、修訂、 權限、衝突和 hook 行為。

content_get 傳回不透明的 _rev 值。將其傳給 content_update、content_publish、content_unpublish、content_schedule 或 content_discard_draft。過期值會傳回衝突,重試前請重新讀取項目。

content_update 為部分更新:未提供的欄位保持目前值。更新已發布項目會暫存草稿,線上版本不變。使用 content_compare 對比線上與草稿,再呼叫 content_publish 發布草稿或 content_discard_draft 捨棄。content_delete 將項目移入資源回收筒;僅 content_permanent_delete 永久刪除回收筒中的項目。

署名是可重複使用的作者或貢獻者資訊。byline_create 可建立訪客署名或關聯 CMS 使用者。將傳回的署名 ID 傳入 content_create 和 content_update 接受的 bylines 輸入。刪除署名會從內容中移除該資訊並清除主署名。

MCP 寫入不參與管理後台的項目編輯鎖。_rev 檢查保護接受它的操作,但其他寫入工具可能在編輯者開啟項目時修改項目。

翻譯

內容、署名、分類術語和選單的翻譯工具傳回相關翻譯群組中的各語系變體。若建立工具的 schema 提供 translationOf 輸入則使用它;必填欄位以 tools/list 為準。

content_translations 接受集合及內容 ID 或 slug。署名、術語和選單翻譯工具接受單筆記錄 ID 或共用翻譯群組 ID。無草稿存取權限的使用者只能看到已發布內容的翻譯。

結構、媒體、分類法與選單

結構工具會改變資料庫結構。建立內容或修改欄位前請使用 schema_get_collection;它傳回可用欄位名稱、類型、約束和驗證規則。刪除集合和欄位會移除已存內容或欄位值且無法復原。

使用 media_upload 傳送 base64 編碼的位元組。上傳受設定的大小和 MIME 類型限制;相同位元組可能傳回已有媒體項目並帶 deduplicated: true。

media_create 確認透過 POST /_emdash/api/media/upload-url 建立的待處理上傳。用傳回的簽署 URL 上傳檔案,再以同一使用者帳號和傳回的 storageKey 呼叫 media_create。工具在媒體庫可用前會驗證儲存檔案存在且大小與請求上傳 URL 時一致。

分類法定義描述分類及其適用的集合;術語是分配給內容的單個值。階層術語可使用 parentId,但父項須屬同一分類法且不能形成環。在非階層分類法中用 parentId 建立或更新術語會傳回 VALIDATION_ERROR。有子項的術語須先移除或移動子項才能刪除。

menu_set_items 在一次原子操作中替換選單的完整項目列表。陣列順序即選單順序。巢狀項目的 parentIndex 指向同陣列中更早的項目,因此每個父項應放在其子項之前。

media_usage_repair 可處理單個或全部集合,在大型網站上可能執行較久。其 complete、partial、failed 和 stale 狀態均為成功的工具回應。請檢查傳回的狀態和計數,而非依賴 isError;認證、驗證與意外執行失敗會設定 isError: true。

網站轉移

site_* 工具將整個網站匯出為網站套件並將套件匯入空網站。它們啟動並驅動操作並傳回有限摘要,從不承載套件位元組、媒體、記錄內容、主體電子郵件或下載 URL。請用 CLI 或 REST API 下載匯出並上傳匯入套件,再依 ID 參考操作。

每個轉移工具都需要 Admin 角色。角色在 scope 之前檢查;非管理員呼叫方收到 INSUFFICIENT_PERMISSIONS 且不會建立核准請求。

匯出

site_export_start 接受 comments(預設 true)並傳回新操作。site_export_status 每次呼叫執行一個有限匯出步驟並報告操作和 nextRequestInMs。在該延遲後重複呼叫直至 nextRequestInMs 為 null。傳入 advance: false 可不執行步驟僅讀狀態。匯出完成後,結果還包含 totals:依類型的記錄數、媒體數量與位元組、套件檔案數量與位元組。

匯入

請先上傳套件。CLI 的 emdash site import <file> --analyze 會上傳、分析並列印操作 ID。

site_import_analyze 每次呼叫執行一個有限分析步驟。重複直至 nextRequestInMs 為 null;結果將包含計畫摘要,含 packageDigest、planDigest、executable、計數、大小、主體、決策、轉換、警告和阻塞項。每項轉換列出其 code、記錄的 kind(如有)和 count,不含所套用的 ID 或值。主體、警告和阻塞項各最多 50 條,完整計數在 total。主體列表不含電子郵件,含建議與目前對應的目標使用者 ID。傳入 decisions 可將主體對應到目標使用者 ID(或 null)並選擇套件或目標的標題與副標題。每次變更產生新的 planDigest。

site_import_start 接受操作 ID 及最新計畫的 packageDigest 和 planDigest。計畫不得有阻塞項。該工具有 destructiveHint: true:啟動後匯入會寫入網站並阻塞其他寫入,直至完成或管理員放棄。呼叫前向使用者展示計畫並確認。

site_import_resume 執行一個有限匯入步驟並報告操作和 nextRequestInMs。重複直至 nextRequestInMs 為 null;斷線後重複安全。site_import_status 報告操作和已上傳檔案數且不推進匯入。site_import_receipt 在匯入完成後傳回完整回執,含 receiptDigest。

匯入執行期間,以及失敗或取消後直至放棄前,所有其他可寫工具均因 TRANSFER_IMPORT_IN_PROGRESS 失敗,包括外掛工具。標註 readOnlyHint: true 的工具和八個 site_* 工具仍可用,initialize 和 tools/list 從不阻塞。媒體使用啟用期間,寫入工具同樣因 MEDIA_USAGE_ACTIVATION_IN_PROGRESS 失敗。

操作摘要包含 id、kind、state、stage、progress、packageDigest、planDigest、error({ code } 或 null)和時間戳記。progress 為 { done, total } 步驟,外加匯出已寫入的 records,以及已知時的 bytesDone 和 bytesTotal。MCP 工具不能取消或放棄匯入;請使用 REST API。

核准

帶有 admin 或所需轉移 scope 的權杖從不請求核准。對兩者皆無的權杖(如僅授予 transfer:analyze 的智能體),管理員核准後 site_export_start 和 site_import_start 才會執行:

  1. 無 scope 的首次呼叫建立待核准請求並以 TRANSFER_APPROVAL_REQUIRED 失敗。訊息文字和 _meta.details 攜帶 approvalId 及其 expiresAt。相同參數且無 approvalId 再次呼叫傳回同一未決請求。
  2. 管理員在 設定 → Transfer 的 Approval requests 中核准,或透過 REST API 的僅工作階段核准端點。API 權杖不能核准請求。
  3. 用戶端以相同參數和 approvalId 重複呼叫。該呼叫啟動操作時消耗核准。若操作未能啟動,用戶端可用同一 approvalId 重試直至過期。

請求綁定使用者、權杖、操作和精確參數:匯出選項,或匯入操作 ID 與兩個摘要。待決請求在建立後 15 分鐘過期,已核准的在核准後 15 分鐘過期。參數或權杖不同,或核准被拒絕、過期或已用時,呼叫因 TRANSFER_APPROVAL_INVALID 失敗。

site_import_start 在建立請求前檢查摘要、操作狀態和計畫阻塞項,因此管理員只需核准可執行的匯入。核准需要權杖 ID;無權杖 ID 的呼叫方收到 INSUFFICIENT_SCOPE。

已核准呼叫啟動操作後,同一使用者和權杖可無 scope 呼叫該操作的 site_export_status,或 site_import_status、site_import_resume 和 site_import_receipt。

外掛工具

管理員須啟用各外掛的 MCP 介面。已啟用工具在 tools/list 中顯示為 <pluginId>__<localName>,權杖驗證呼叫需要 mcp:tools 或 mcp:tools:<pluginId>。EmDash 還會檢查外掛路由宣告的權限,並在稽核記錄中記錄外掛、工具、路由和執行者。

外掛工具因安裝而異,不在上述靜態清單中。

OAuth 探索

MCP 用戶端從受保護資源中繼資料探索授權伺服器:

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

回應將 /_emdash/api/mcp 識別為受保護資源並連結到授權伺服器。用戶端隨後讀取:

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

該文件提供目前授權、權杖、註冊和裝置授權端點、支援的 scope、grant 類型及 PKCE 方法 S256。請使用探索值,勿硬編碼 OAuth 協定路由。

未驗證的 MCP 請求傳回帶探索 URL 的 401:

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

錯誤

工具失敗時 isError: true。第一個文字區塊以穩定代碼開頭,_meta.code 為讀取結構化中繼資料的用戶端重複該代碼:

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

驗證失敗使用如 INSUFFICIENT_SCOPE 和 INSUFFICIENT_PERMISSIONS 等代碼。傳輸失敗使用 JSON-RPC 內部錯誤碼 -32603,不暴露底層例外。