MCP 伺服器參考

本頁內容

EmDash 在 /_emdash/api/mcp 提供內建的 Model Context Protocol(MCP)伺服器,將內容管理操作以工具形式公開給 AI 助手。

本頁說明通訊協定內容:身分驗證、傳輸、工具規格、OAuth 探索與錯誤處理。

身分驗證

MCP 伺服器支援三種身分驗證方式:

方式運作方式
OAuth 2.1 授權碼 + PKCEMCP 用戶端的標準流程。使用者在瀏覽器中核准權限範圍(scope)。
個人存取權杖(PAT)在管理後台建立的長期有效 ec_pat_* 權杖。
裝置碼流程類似 CLI 的流程,在瀏覽器中核准驗證碼。由 emdash login 使用。

管理後台產生的工作階段 Cookie 也可使用,但對外部 MCP 用戶端不實用。

權限範圍(Scopes)

權杖透過 scope 限制用戶端可執行的操作。scope 在 OAuth 授權時申請,並於每次工具呼叫時強制檢查。

Scope授予的權限
content:read列出、取得、比較與搜尋內容。列出分類法、分類詞彙與選單。
content:write建立、更新、刪除、發布、下架、排程發布、取消排程、複製與還原內容。為相容在拆分出下列 scope 之前簽發的權杖,隱含 taxonomies:managemenus:manage
media:read列出並取得媒體項目。
media:write登記(建立)、更新與刪除媒體中繼資料。
schema:read列出集合並取得集合結構(schema)。
schema:write建立與刪除集合及欄位。
taxonomies:manage建立、更新與刪除分類詞彙。
menus:manage建立、更新與刪除導覽選單及其項目。
settings:read讀取網站層級設定。
settings:manage更新網站層級設定。
admin對所有操作的完整存取。

admin scope 可存取一切。以工作階段為基礎的驗證(無權杖)也會依使用者角色擁有與其角色相符的全部權限。

content:write 隱含 taxonomies:managemenus:manage,因此在拆分這些 scope 之前簽發的個人存取權杖無需重新簽發仍可運作。新簽發的權杖應申請更細緻的 scope。

角色要求

除 scope 外,部分工具還要求最低 RBAC 角色。兩者須同時滿足——即使權杖 scope 正確,若呼叫使用者角色不足仍會失敗。

操作最低角色
內容讀取已發布項目:訂閱者(10);草稿、排程、資源回收筒與修訂:貢獻者(20)
內容建立/編輯自己的/刪除自己的作者(30)
內容發布自己的項目:作者(30);操作他人項目:編輯(40)
結構讀取編輯(40)
結構寫入管理員(50)
分類管理編輯(40)
選單管理編輯(40)
設定讀取編輯(40)
設定管理管理員(50)
媒體上傳(media_create作者(30)

角色定義見驗證指南

傳輸

伺服器在無狀態模式下使用可串流 HTTP(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 錯誤碼;scope 與權限失敗時另有 MCP 專用錯誤碼。

工具

伺服器在八個領域中共公開 43 個工具:內容、結構(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 時有效。

Scope: content:read | 唯讀:

content_get

依 ID 或 slug 取得單一內容。回傳全部欄位值、中繼資料,以及用於樂觀並行控制的 _rev 權杖。

參數類型必填說明
collectionstring集合 slug
idstring內容項目 ID(ULID)或 slug
localestring以 slug 查詢時的語系地區。ID 全域唯一。

Scope: content:read | 唯讀:

content_create

建立新內容項目。data 物件中的欄位值須符合集合 schema——可用 schema_get_collection 查看可用欄位。預設以 draft 建立。

參數類型必填說明
collectionstring集合 slug
dataobject欄位鍵值對
slugstringURL slug(省略時通常由標題產生)
statusstring初始狀態:draftpublished(預設 draft
localestring此內容的語系地區(預設網站預設語系)
translationOfstring若此筆為翻譯,所指向的來源項目 ID

Scope: content:write

content_update

更新既有內容。只傳需要修改的欄位——未出現的欄位保持不變。

參數類型必填說明
collectionstring集合 slug
idstring內容項目 ID 或 slug
dataobject要更新的欄位值
slugstring新的 URL slug
statusstring新狀態:draftpublished
_revstring來自 content_get 的修訂權杖,用於衝突偵測

Scope: content:write

content_delete

軟刪除:將內容移至資源回收筒。可用 content_restore 復原,或用 content_permanent_delete 永久刪除。

參數類型必填說明
collectionstring集合 slug
idstring內容項目 ID 或 slug

Scope: content:write | 破壞性:

content_restore

從資源回收筒復原已軟刪除的內容項目。

參數類型必填說明
collectionstring集合 slug
idstring內容項目 ID 或 slug

Scope: content:write

content_permanent_delete

永久且不可逆地刪除已在資源回收筒中的內容項目。項目須先位於資源回收筒。

參數類型必填說明
collectionstring集合 slug
idstring內容項目 ID 或 slug

Scope: content:write | 破壞性:

content_publish

發布內容,使其在網站上線。會根據目前草稿建立已發布修訂。後續編輯產生新草稿,在再次發布前不會影響線上版本。

參數類型必填說明
collectionstring集合 slug
idstring內容項目 ID 或 slug

Scope: content:write

content_unpublish

將已發布項目改回草稿,網站前台不再顯示,但內容仍保留。

參數類型必填說明
collectionstring集合 slug
idstring內容項目 ID 或 slug

Scope: content:write

content_schedule

為內容項目安排未來發布時間,屆時自動發布。

參數類型必填說明
collectionstring集合 slug
idstring內容項目 ID 或 slug
scheduledAtstringISO 8601 日期時間(例如 2026-06-01T09:00:00Z

Scope: content:write

content_unschedule

取消已安排的排程發布。項目保持目前狀態;僅清除 scheduledAt 時間戳記。冪等:對未安排發布的項目呼叫無效果。

參數類型必填說明
collectionstring集合 slug
idstring內容項目 ID 或 slug

Scope: content:write

content_compare

比較內容項目之已發布(線上)版本與目前草稿。回傳兩個版本及是否有差異的旗標。

參數類型必填說明
collectionstring集合 slug
idstring內容項目 ID 或 slug

Scope: content:read | 唯讀:

content_discard_draft

捨棄目前草稿,回復到最後一次已發布版本。僅適用於至少發布過一次的項目。

參數類型必填說明
collectionstring集合 slug
idstring內容項目 ID 或 slug

Scope: content:write | 破壞性:

content_list_trashed

列出集合資源回收筒中的軟刪除內容。

參數類型必填說明
collectionstring集合 slug
limitinteger最多筆數(1–100,預設 50)
cursorstring分頁游標

Scope: content:read | 唯讀:

content_duplicate

複製既有內容項目。副本以草稿建立,標題附加「(Copy)」,slug 自動產生。

參數類型必填說明
collectionstring集合 slug
idstring要複製的內容項目 ID 或 slug

Scope: content:write

content_translations

取得某內容項目在各語系地區下的變體。回傳翻譯群組及每個語系版本的摘要。僅在啟用 i18n 時有效。

參數類型必填說明
collectionstring集合 slug
idstring內容項目 ID 或 slug

Scope: content:read | 唯讀:

結構(Schema)工具

schema_list_collections

列出 CMS 中定義的全部內容集合。回傳 slug、標籤、支援的能力與時間戳記。

無參數。

Scope: schema:read | 最低角色: 編輯 | 唯讀:

schema_get_collection

取得集合詳情,含全部欄位定義。欄位描述資料模型:名稱、類型、限制與驗證規則。用於理解 content_createcontent_update 的預期。

參數類型必填說明
slugstring集合 slug(例如 posts

Scope: schema:read | 最低角色: 編輯 | 唯讀:

schema_create_collection

建立新內容集合。會建立資料庫表與結構定義。slug 須為小寫英數字加底線,且以字母開頭。

參數類型必填說明
slugstring唯一識別(/^[a-z][a-z0-9_]*$/
labelstring顯示名稱(複數,例如 “Blog Posts”)
labelSingularstring單數顯示名稱
descriptionstring集合說明
iconstring管理後台使用的圖示名稱
supportsstring[]能力:draftsrevisionspreviewschedulingsearch(預設:['drafts', 'revisions']

Scope: schema:write | 最低角色: 管理員

schema_delete_collection

刪除集合及其資料庫表。不可逆,會刪除集合內全部內容。

參數類型必填說明
slugstring要刪除的集合 slug
forceboolean若集合仍有內容是否仍強制刪除

Scope: schema:write | 最低角色: 管理員 | 破壞性:

schema_create_field

向集合結構新增欄位,即在資料表中新增欄。

參數類型必填說明
collectionstring集合 slug
slugstring欄位識別(/^[a-z][a-z0-9_]*$/
labelstring顯示名稱
typestring資料類型(見下)
requiredboolean是否必填
uniqueboolean是否要求值唯一
defaultValueany新項目的預設值
validationobject限制:minmaxminLengthmaxLengthpatternoptions
optionsobject控制項設定:collection(參照)、rows(多行文字)
searchableboolean是否納入全文檢索索引
translatableboolean是否可翻譯(預設 true)

欄位類型:stringtextnumberintegerbooleandatetimeselectmultiSelectportableTextimagefilereferencejsonslug

selectmultiSelect 的允許取值放在 validation.options 中。

Scope: schema:write | 最低角色: 管理員

schema_delete_field

從集合移除欄位。會刪除欄與該欄全部資料。不可逆。

參數類型必填說明
collectionstring集合 slug
fieldSlugstring要移除的欄位 slug

Scope: schema:write | 最低角色: 管理員 | 破壞性:

媒體工具

media_list

列出已上傳的媒體檔案,支援依 MIME 類型前綴篩選與分頁。

參數類型必填說明
mimeTypestringMIME 類型前綴(例如 image/application/pdf
limitinteger最多筆數(1–100,預設 50)
cursorstring分頁游標

Scope: media:read | 唯讀:

media_create

登記已上傳至儲存空間的媒體檔案。呼叫方須負責將檔案放到 storageKey(通常使用管理後台或獨立 API 回傳的簽章上傳 URL)。此工具持久化中繼資料,使檔案可透過 media_list / media_get 探索並被內容參照。

參數類型必填說明
filenamestring原始檔名(例如 logo.png
mimeTypestringMIME 類型(例如 image/png
storageKeystring檔案在儲存空間中的路徑/鍵
sizeinteger檔案大小(位元組)
widthinteger圖片寬度(像素)
heightinteger圖片高度(像素)
contentHashstring內容雜湊(去重用)
blurhashstring圖片占位用 Blurhash
dominantColorstring主色十六進位色值

Scope: media:write | 最低角色: 作者

media_get

依 ID 取得單一媒體檔案的詳情。回傳檔名、MIME 類型、尺寸、替代文字、URL 等中繼資料。

參數類型必填說明
idstring媒體項目 ID

Scope: media:read | 唯讀:

media_update

更新已上傳媒體檔案的中繼資料。檔案二進位本體不可更換。

參數類型必填說明
idstring媒體項目 ID
altstring無障礙替代文字
captionstring說明文字
widthinteger圖片寬度(像素)
heightinteger圖片高度(像素)

Scope: media:write

media_delete

永久刪除媒體檔案:刪除資料庫紀錄與儲存空間中的檔案。參照此媒體的內容將出現中斷參照。

參數類型必填說明
idstring媒體項目 ID

Scope: media:write | 破壞性:

搜尋工具

跨內容集合全文搜尋。集合的 supports 須包含 search,且欄位須標記為 searchable

參數類型必填說明
querystring搜尋關鍵字
collectionsstring[]僅搜尋指定集合 slug
localestring依語系地區篩選結果
limitinteger最多結果數(1–50,預設 20)

Scope: content:read | 唯讀:

分類法工具

taxonomy_list

列出全部分類法定義(例如分類、標籤)。回傳名稱、標籤、是否階層式及關聯集合。

無參數。

Scope: content:read | 唯讀:

taxonomy_list_terms

分頁列出某分類法下的詞彙。

參數類型必填說明
taxonomystring分類法名稱(例如 categoriestags
limitinteger最多筆數(1–100,預設 50)
cursorstring分頁游標

Scope: content:read | 唯讀:

taxonomy_create_term

在分類法下建立新詞彙。階層式分類法可指定 parentId 建立子項目。父層祖先鏈深度不得超過 100 層。

參數類型必填說明
taxonomystring分類法名稱
slugstringURL 安全識別碼
labelstring顯示名稱
parentIdstring父詞彙 ID(階層式分類法)
descriptionstring詞彙說明

Scope: taxonomies:manage | 最低角色: 編輯

taxonomy_update_term

更新分類法中既有詞彙。可省略欄位以保持原值。重新命名 slug 不得與同分類法下其他詞彙衝突。將 parentId 設為 null 可脫離父層。新父層須存在、同屬該分類法,且不得產生循環。

參數類型必填說明
taxonomystring分類法名稱
termSlugstring待更新詞彙的目前 slug
slugstring新 slug(在分類法內唯一)
labelstring新顯示名稱
parentIdstring | null新父詞彙 ID;null 表示脫離父層
descriptionstring新說明

Scope: taxonomies:manage | 最低角色: 編輯

taxonomy_delete_term

從分類法永久刪除詞彙。曾打上該標籤的內容將失去關聯。若詞彙仍有子項目則不可刪——須先刪除子項目。

參數類型必填說明
taxonomystring分類法名稱
termSlugstring要刪除詞彙的 slug

Scope: taxonomies:manage | 最低角色: 編輯 | 破壞性:

選單工具

列出全部導覽選單。回傳名稱、標籤與時間戳記。

無參數。

Scope: content:read | 唯讀:

依名稱取得選單及其有序項目。項目含標籤、URL、類型及選用父級以支援巢狀。

參數類型必填說明
namestring選單名稱(例如 mainfooter

Scope: content:read | 唯讀:

建立新導覽選單。name 為網站範本使用的穩定識別碼;label 為管理後台顯示名稱。項目稍後透過 menu_set_items 新增。

參數類型必填說明
namestring穩定識別碼(/^[a-z][a-z0-9_]*$/
labelstring管理後台顯示名稱

Scope: menus:manage | 最低角色: 編輯

更新選單的標籤。穩定識別碼 name 不可變更。

參數類型必填說明
namestring要更新的選單名稱
labelstring新顯示標籤

Scope: menus:manage | 最低角色: 編輯

刪除選單及其全部項目。無法復原。

參數類型必填說明
namestring要刪除的選單名稱

Scope: menus:manage | 最低角色: 編輯 | 破壞性:

單次呼叫取代選單的全部項目。原子操作:先刪舊項目,再依給定順序插入新清單。比逐筆增刪更清楚,順序與父子關係明確。

項目位置由陣列索引決定。巢狀透過 parentIndex 表達——parentIndex: 0 表示巢狀在索引 0 的項目下。父項目須出現在清單較前位置。無 parentIndex 者為頂層項目。

參數類型必填說明
namestring要更新的選單名稱
itemsMenuItem[]有序選單項目清單(見下)

每個 MenuItem 欄位:

欄位類型必填說明
labelstring顯示文字
typestringcustompageposttaxonomycollection 之一
customUrlstringtype: "custom" 時的 URL(其他類型忽略)
referenceCollectionstring內容參照目標集合 slug
referenceIdstring參照目標內容/詞彙 ID
titleAttrstringHTML title 屬性
targetstringHTML target(例如 _blank
cssClassesstring空白分隔的 CSS 類別
parentIndexinteger父項目在陣列中的索引;頂層項目省略

Scope: menus:manage | 最低角色: 編輯

修訂工具

revision_list

列出內容項目的修訂歷史,新的在前。集合須啟用 revisions

參數類型必填說明
collectionstring集合 slug
idstring內容項目 ID 或 slug
limitinteger最多修訂筆數(1–50,預設 20)

Scope: content:read | 唯讀:

revision_restore

將內容項目還原到某次修訂:以指定修訂的資料取代目前草稿。不會自動發布——需要時請再呼叫 content_publish

參數類型必填說明
revisionIdstring要還原的修訂 ID

Scope: content:write

設定工具

網站層級設定——標題、標語、Logo、網站圖示、標準網址、預設分頁大小、日期與時間格式、社交帳號及 SEO 預設值等。

settings_get

取得全部網站層級設定。媒體參照(logofaviconseo.defaultOgImage)在回應中含解析後的 URL 及底層 mediaId。未設定的值不出現在回應中。

無參數。

Scope: settings:read | 最低角色: 編輯 | 唯讀:

settings_update

更新一項或多項網站層級設定。部分更新:僅修改提供的欄位;未提供的保持不變。回傳更新後的完整設定物件。

設定媒體參照(logofaviconseo.defaultOgImage)時傳入含 mediaId(及選用 alt)的物件。媒體項目須已存在——請先 media_create

參數類型必填說明
titlestring網站標題
taglinestring標題旁簡短描述
logoMediaRefLogo 媒體參照({ mediaId, alt? }
faviconMediaRef網站圖示媒體參照
urlstring網站標準 URL(http 或 https)。空字串表示清除。
postsPerPageinteger內容列表預設每頁筆數(1–100)
dateFormatstring日期格式占位字串
timezonestringIANA 時區識別碼
socialobject社交帳號——twittergithubfacebookinstagramlinkedinyoutube
seoobjectSEO 預設值(見下)

seo 物件欄位:

欄位類型說明
titleSeparatorstring頁面標題與網站標題之間的分隔符號(例如 " | " 表示直線符號)
defaultOgImageMediaRef內容無圖時的預設 Open Graph 圖片
robotsTxtstring自訂 robots.txt 內文。省略則使用 EmDash 預設。
googleVerificationstringGoogle Search Console 驗證權杖
bingVerificationstringBing 網站管理員工具驗證權杖

Scope: settings:manage | 最低角色: 管理員

OAuth 探索

支援 OAuth 2.1 的 MCP 用戶端可自動探索如何驗證。伺服器發布兩份中繼資料:

受保護資源中繼資料

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

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

Scope 與權限錯誤以 MCP 通訊協定錯誤形式拋出:

{
  "jsonrpc": "2.0",
  "error": {
    "code": -32600,
    "message": "Insufficient scope: requires content:write"
  },
  "id": 1
}

傳輸層錯誤(伺服器設定錯誤、未處理的例外等)回傳 JSON-RPC 錯誤碼 -32603(內部錯誤),且不洩露實作細節。