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 클라이언트. 사용자가 브라우저에서 요청된 스코프를 승인합니다.
Personal access token클라이언트 또는 자동화용 장기 액세스. 토큰은 ec_pat_ 접두사를 사용하며 관리자에서 생성합니다.
OAuth 2.0 Device Authorization Grant사용자에게 브라우저에서 코드 승인을 요청하는 CLI 클라이언트. emdash login이 이 흐름을 사용합니다.

세션 쿠키는 MCP 엔드포인트 인증에 사용되지 않습니다.

Scopes

OAuth 및 개인 액세스 토큰은 클라이언트가 호출할 수 있는 도구를 제한합니다. 사용자 역할은 별도로 확인되므로 스코프는 사용자가 갖지 않은 권한을 부여하지 않습니다.

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 또는 플러그인별 스코프가 필요합니다.

admin 스코프에는 transfer:export, transfer:analyze, transfer:execute가 포함됩니다. 각 전송 스코프는 자체 동작만 부여하며 관리자 역할이 필요합니다. 에이전트 등이 내보내기/가져오기 없이 사이트 패키지만 분석하도록 하려면 admin 대신 transfer:analyze를 부여하세요.

인가 코드 동의 페이지에서 사용자는 요청된 스코프를 제거할 수 있습니다. EmDash는 요청을 클라이언트 등록 스코프 및 사용자 역할과 교차하고 빈 부여를 거부합니다.

역할 요구 사항

다음 표는 넓은 기능별 최소 역할입니다. 다른 사용자 콘텐츠에 대해 작업할 때 소유권 검사로 더 높은 역할이 필요할 수 있습니다.

기능최소 역할
게시된 콘텐츠, 미디어, 분류체계, 용어, 메뉴 읽기Subscriber
초안, 예약 콘텐츠, 휴지통, 비교, 리비전 읽기Contributor
콘텐츠 생성 또는 미디어 업로드Contributor
소유 콘텐츠 편집/게시 및 미디어 등록Author
바이라인, 분류체계, 메뉴 또는 모든 사용자 콘텐츠 관리Editor
스키마 또는 설정 읽기Editor
스키마/설정 변경, 콘텐츠 영구 삭제, 미디어 사용 복구Admin
전체 사이트 내보내기 또는 가져오기Admin

전체 역할 정의는 사용자 역할을 참조하세요.

전송

서버는 stateless Streamable HTTP를 사용합니다. 각 요청은 독립적이며 MCP 세션이나 Server-Sent Events 연결을 유지하지 않습니다.

메서드엔드포인트동작
POST/_emdash/api/mcpJSON-RPC 초기화, 도구 목록, 도구 호출을 수락합니다.
GET/_emdash/api/mcp405 Method Not Allowed를 반환합니다.
DELETE/_emdash/api/mcp405 Method Not Allowed를 반환합니다.

응답은 JSON-RPC 2.0을 사용합니다. 도구 요청을 구성하기 전에 tools/list를 호출해 현재 입력 스키마와 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 스코프는 이 표의 모든 요구를 충족합니다.

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는 스코프 없는 토큰도 수락합니다. 승인된 요청이 시작하는 작업에 대해 site_export_status, site_import_status, site_import_resume, site_import_receipt도 동일 토큰을 스코프 없이 수락합니다.

도구 스키마 사용

tools/list는 각 도구의 설명, JSON 입력 스키마, 주석을 반환합니다. 설치된 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 텍스트로 반환됩니다. 출력 스키마가 있는 도구는 같은 값을 structuredContent에도 반환할 수 있습니다.

콘텐츠 수명 주기 및 바이라인

콘텐츠 수명 주기 참조는 MCP, REST, CLI, 관리 패널이 공유하는 상태, 리비전, 권한, 충돌, 훅 동작을 정의합니다.

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 검사는 이를 받는 작업을 보호하지만, 편집자가 열어 둔 동안 다른 쓰기 도구가 항목을 변경할 수 있습니다.

번역

콘텐츠, 바이라인, 분류 용어, 메뉴 번역 도구는 해당 번역 그룹의 모든 로케일 변형을 반환합니다. 스키마에 translationOf가 있으면 생성 도구 입력을 사용하세요. 필수 필드는 tools/list가 기준입니다.

content_translations는 컬렉션과 콘텐츠 ID 또는 슬러그를 받습니다. 바이라인, 용어, 메뉴 번역 도구는 한 레코드 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_* 도구는 전체 사이트를 사이트 패키지로 내보내고 빈 사이트에 패키지를 가져옵니다. 작업을 시작·진행하고 제한된 요약을 반환합니다. 패키지 바이트, 미디어, 레코드 내용, principal 이메일, 다운로드 URL은 전달하지 않습니다. CLI 또는 REST API로 내보내기를 다운로드하고 가져오기용 패키지를 업로드한 뒤 작업 ID로 참조하세요.

모든 전송 도구는 Admin 역할이 필요합니다. 역할은 스코프보다 먼저 확인되며, 비관리자는 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, 개수, 크기, principal, decisions, transformations, warnings, blockers가 포함된 계획 요약을 얻습니다. 각 transformation은 code, 레코드 kind(있을 때), count로 나열되며 적용 ID나 값은 없습니다. principal, warnings, blockers는 각 최대 50개, 전체 개수는 total에 있습니다. principal은 이메일 없이 제안 및 현재 매핑된 대상 사용자 ID로 나열됩니다. decisions로 principal을 대상 사용자 ID(또는 null)에 매핑하고 패키지 또는 대상 제목·태그라인을 선택하세요. 변경마다 새 planDigest가 생성됩니다.

site_import_start는 작업 ID와 최신 계획의 packageDigest, planDigest를 받습니다. 계획에 blocker가 없어야 합니다. 도구는 destructiveHint: true입니다. 시작 후 가져오기는 사이트에 쓰고 완료되거나 관리자가 포기할 때까지 다른 쓰기를 차단합니다. 호출 전 계획을 사용자에게 보여 확인을 받으세요.

site_import_resume은 하나의 제한된 가져오기 단계를 실행하고 작업과 nextRequestInMs를 보고합니다. nextRequestInMs가 null이 될 때까지 호출하세요. 연결 끊김 후 반복해도 안전합니다. site_import_status는 가져오기를 진행하지 않고 작업과 업로드된 파일 수를 보고합니다. site_import_receipt는 가져오기 완료 후 receiptDigest를 포함한 전체 영수증을 반환합니다.

가져오기 실행 중 및 실패·취소 후 포기 전까지 쓰기 가능한 다른 모든 도구는 TRANSFER_IMPORT_IN_PROGRESS로 실패합니다(플러그인 도구 포함). readOnlyHint: true 도구와 8개의 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 또는 필요한 전송 스코프가 있는 토큰은 승인을 요청하지 않습니다. 둘 다 없는 토큰(예: transfer:analyze만 있는 에이전트)에서는 관리자가 승인하면 site_export_start와 site_import_start가 실행됩니다.

  1. 스코프 없는 첫 호출은 보류 승인 요청을 만들고 TRANSFER_APPROVAL_REQUIRED로 실패합니다. 메시지와 _meta.details에 approvalId와 expiresAt이 있습니다. 같은 인수로 approvalId 없이 다시 호출하면 같은 열린 요청이 반환됩니다.
  2. 관리자는 설정 → Transfer의 Approval requests 또는 REST API의 세션 전용 승인 엔드포인트에서 승인합니다. API 토큰은 요청을 승인할 수 없습니다.
  3. 클라이언트는 같은 인수와 approvalId로 다시 호출합니다. 승인은 해당 호출이 작업을 시작할 때 소비됩니다. 시작에 실패하면 만료 전까지 같은 approvalId로 재시도할 수 있습니다.

요청은 사용자, 토큰, 동작, 정확한 인수(내보내기 옵션 또는 가져오기 작업 ID와 두 digest)에 묶입니다. 보류 요청은 생성 후 15분, 승인된 요청은 승인 후 15분에 만료됩니다. 다른 인수·토큰이거나 거부·만료·사용된 승인이면 TRANSFER_APPROVAL_INVALID입니다.

site_import_start는 요청 생성 전 digest, 작업 상태, 계획 blocker를 확인하므로 관리자는 실행 가능한 가져오기만 승인합니다. 승인에는 토큰 ID가 필요하며 없으면 INSUFFICIENT_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

이 문서는 현재 인가, 토큰, 등록, 디바이스 인가 엔드포인트, 지원 스코프, 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을 사용하며 기본 예외는 노출하지 않습니다.