payload-mcp-toolkit 0.3.3 → 0.3.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -3
- package/dist/draft-workflow.d.ts +6 -5
- package/dist/draft-workflow.js +18 -13
- package/dist/draft-workflow.js.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/tools/create-document.d.ts +36 -0
- package/dist/tools/create-document.js +79 -0
- package/dist/tools/create-document.js.map +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -23,11 +23,12 @@ The official Payload MCP plugin gives every collection a generic CRUD surface. T
|
|
|
23
23
|
**Auto-generated resources** (machine-readable JSON for the LLM):
|
|
24
24
|
- `blocks://catalog`, `collections://schema`, `collections://relationships`.
|
|
25
25
|
|
|
26
|
-
**Custom tools (
|
|
26
|
+
**Custom tools (11, plus an auto-registered scheduler)**
|
|
27
27
|
|
|
28
28
|
*Authoring*
|
|
29
|
+
- `createDocument` — local-API based creation for any collection. Pass `data` as a JSON string. Defaults to `draft: true` on draft-enabled collections. Replaces the official plugin's per-collection `create<Resource>` tools, which silently drop every content field on collections with richText/upload/blocks/relationship-array fields.
|
|
29
30
|
- `patchLayout` — surgical append/prepend/insertAt/replaceAt against any blocks-typed field. Validates each block (recursively, at any depth) against the introspected nesting map. Safer than `updateDocument` for incremental layout edits.
|
|
30
|
-
- `updateDocument` —
|
|
31
|
+
- `updateDocument` — local-API based update for any collection. Replaces the official plugin's per-collection `update<Resource>` tools, which crash on collections with richText/upload/blocks fields.
|
|
31
32
|
- `uploadMedia` — fetch a public HTTPS image, validate (SSRF-safe with streaming size cap), create a Media doc.
|
|
32
33
|
|
|
33
34
|
*Discovery*
|
|
@@ -42,7 +43,7 @@ The official Payload MCP plugin gives every collection a generic CRUD surface. T
|
|
|
42
43
|
- `safeDelete` — relationship-aware delete. Walks the relationship graph, refuses with a structured impact summary if other documents reference the target. Fail-closed on permission errors. Override with `confirm: true`.
|
|
43
44
|
|
|
44
45
|
**Draft workflow** wired into the official plugin's `mcpCollections`:
|
|
45
|
-
- The official plugin's per-collection raw `update<Resource>`
|
|
46
|
+
- The official plugin's per-collection raw `create<Resource>` and `update<Resource>` tools are disabled for every collection. Authoring flows through `createDocument` / `updateDocument` / `patchLayout` (all local-API based), which preserve draft semantics for draftable collections and survive the schema-conversion bugs in the official plugin's authoring path.
|
|
46
47
|
- Appends preview URLs to draft responses by calling each collection's own `admin.livePreview.url` or `admin.preview` function — no separate path config needed.
|
|
47
48
|
|
|
48
49
|
## Install
|
package/dist/draft-workflow.d.ts
CHANGED
|
@@ -47,11 +47,12 @@ export declare function getDraftBehavior(collection: CollectionConfig, options?:
|
|
|
47
47
|
* Generates the mcpCollections config object for the official mcpPlugin.
|
|
48
48
|
*
|
|
49
49
|
* For each non-excluded collection:
|
|
50
|
-
* - Enables `find` / `
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
* upload
|
|
54
|
-
*
|
|
50
|
+
* - Enables `find` / `delete`; disables the official plugin's raw
|
|
51
|
+
* `create<Resource>` and `update<Resource>` tools universally. Both
|
|
52
|
+
* crash or silently drop fields on collections whose schemas contain
|
|
53
|
+
* richText, upload, blocks, or relationship-array fields. The toolkit's
|
|
54
|
+
* `createDocument` / `updateDocument` / `patchLayout` cover both ops via
|
|
55
|
+
* the local API. Draft semantics are preserved by `publishDraft`.
|
|
55
56
|
* - For draft collections: attaches an `overrideResponse` that appends a
|
|
56
57
|
* preview URL — sourced from the collection's own livePreview/preview
|
|
57
58
|
* function — to draft documents. Falls back to a generic admin-panel
|
package/dist/draft-workflow.js
CHANGED
|
@@ -91,11 +91,12 @@ function createOverrideResponse(collection, siteUrl) {
|
|
|
91
91
|
* Generates the mcpCollections config object for the official mcpPlugin.
|
|
92
92
|
*
|
|
93
93
|
* For each non-excluded collection:
|
|
94
|
-
* - Enables `find` / `
|
|
95
|
-
*
|
|
96
|
-
*
|
|
97
|
-
* upload
|
|
98
|
-
*
|
|
94
|
+
* - Enables `find` / `delete`; disables the official plugin's raw
|
|
95
|
+
* `create<Resource>` and `update<Resource>` tools universally. Both
|
|
96
|
+
* crash or silently drop fields on collections whose schemas contain
|
|
97
|
+
* richText, upload, blocks, or relationship-array fields. The toolkit's
|
|
98
|
+
* `createDocument` / `updateDocument` / `patchLayout` cover both ops via
|
|
99
|
+
* the local API. Draft semantics are preserved by `publishDraft`.
|
|
99
100
|
* - For draft collections: attaches an `overrideResponse` that appends a
|
|
100
101
|
* preview URL — sourced from the collection's own livePreview/preview
|
|
101
102
|
* function — to draft documents. Falls back to a generic admin-panel
|
|
@@ -117,16 +118,20 @@ function createOverrideResponse(collection, siteUrl) {
|
|
|
117
118
|
if (behavior !== 'publish') {
|
|
118
119
|
draftCollections.add(collection.slug);
|
|
119
120
|
}
|
|
120
|
-
//
|
|
121
|
-
//
|
|
122
|
-
// whose JSON schema can't
|
|
123
|
-
//
|
|
124
|
-
//
|
|
125
|
-
//
|
|
126
|
-
//
|
|
121
|
+
// Disable the official plugin's per-collection `create<Resource>` and
|
|
122
|
+
// `update<Resource>` tools. Both call `convertCollectionSchemaToZod` and
|
|
123
|
+
// produce broken input schemas on any collection whose JSON schema can't
|
|
124
|
+
// be losslessly converted (richText, upload, blocks, relationship-array
|
|
125
|
+
// fields → fallback returns `z.record()`):
|
|
126
|
+
// - update<Resource>: throws `convertedFields.partial is not a function`
|
|
127
|
+
// - create<Resource>: registers with metadata-only params, then the MCP
|
|
128
|
+
// SDK strips every content field before it reaches `payload.create()`,
|
|
129
|
+
// so creates fail required-field validation with empty data.
|
|
130
|
+
// The toolkit's `createDocument` / `updateDocument` / `patchLayout` cover
|
|
131
|
+
// both ops via the local API and survive these upstream bugs.
|
|
127
132
|
const enabled = {
|
|
128
133
|
find: true,
|
|
129
|
-
create:
|
|
134
|
+
create: false,
|
|
130
135
|
update: false,
|
|
131
136
|
delete: true
|
|
132
137
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/draft-workflow.ts"],"sourcesContent":["import type { CollectionConfig, PayloadRequest } from 'payload'\nimport { hasCollectionDrafts } from './introspection'\n\n/** MCP response shape used by overrideResponse */\ninterface McpResponse {\n content: Array<{ text: string; type: string }>\n}\n\n/** Per-collection MCP config with enabled operations and optional overrideResponse */\ninterface McpCollectionConfig {\n description: string\n enabled: {\n create: boolean\n delete: boolean\n find: boolean\n update: boolean\n }\n overrideResponse?: (\n response: McpResponse,\n doc: Record<string, unknown>,\n req: PayloadRequest,\n ) => McpResponse | Promise<McpResponse>\n}\n\ninterface GenerateOptions {\n /**\n * Optional absolute base URL prepended to relative preview paths returned\n * by the collection's own preview URL function. Resolved upstream from\n * (in order): `options.preview.siteUrl`, `incomingConfig.serverURL`,\n * `process.env.NEXT_PUBLIC_SERVER_URL`, `process.env.SITE_URL`. May be\n * undefined — relative-path returns will then be skipped.\n */\n siteUrl?: string\n /** Per-collection draft behavior overrides */\n draftBehavior?: Record<string, 'always-draft' | 'always-publish'>\n /** Collection slugs to exclude from MCP */\n excludeCollections?: string[]\n /** Disable preview URL injection entirely */\n previewDisabled?: boolean\n}\n\n/**\n * Determines the draft behavior for a collection.\n *\n * - No drafts configured → 'publish' (raw update allowed; no draft concept)\n * - Drafts configured + override given → use override\n * - Drafts configured + no override → 'always-draft' (raw update locked)\n */\nexport function getDraftBehavior(\n collection: CollectionConfig,\n options?: { draftBehavior?: Record<string, 'always-draft' | 'always-publish'> },\n): 'always-draft' | 'always-publish' | 'publish' {\n if (!hasCollectionDrafts(collection)) return 'publish'\n\n const override = options?.draftBehavior?.[collection.slug]\n if (override) return override\n\n return 'always-draft'\n}\n\n/**\n * Build a preview URL for a draft document by delegating to the collection's\n * own configured preview URL function. Tries `admin.livePreview.url` first\n * (the modern API), then `admin.preview` (the older `GeneratePreviewURL`).\n *\n * If neither is configured, or the function returns null/undefined/empty,\n * returns null and the override response will skip preview injection.\n */\nasync function resolvePreviewUrl(\n collection: CollectionConfig,\n doc: Record<string, unknown>,\n req: PayloadRequest,\n siteUrl: string | undefined,\n): Promise<string | null> {\n const admin = (collection.admin ?? {}) as Record<string, any>\n const locale = (req as any).locale ?? 'en'\n\n let raw: string | null | undefined\n\n const livePreviewUrl = admin.livePreview?.url\n if (typeof livePreviewUrl === 'function') {\n try {\n raw = await livePreviewUrl({\n data: doc,\n locale: { code: locale, label: locale },\n req,\n payload: req.payload,\n collectionConfig: collection as any,\n })\n } catch {\n raw = null\n }\n } else if (typeof livePreviewUrl === 'string') {\n raw = livePreviewUrl\n }\n\n if (!raw && typeof admin.preview === 'function') {\n try {\n raw = await admin.preview(doc, {\n locale,\n req,\n token: null,\n })\n } catch {\n raw = null\n }\n }\n\n if (!raw || typeof raw !== 'string') return null\n\n if (raw.startsWith('http://') || raw.startsWith('https://')) {\n return raw\n }\n\n if (!siteUrl) return null\n\n const base = siteUrl.endsWith('/') ? siteUrl.slice(0, -1) : siteUrl\n const path = raw.startsWith('/') ? raw : `/${raw}`\n return `${base}${path}`\n}\n\nfunction createOverrideResponse(\n collection: CollectionConfig,\n siteUrl: string | undefined,\n): McpCollectionConfig['overrideResponse'] {\n return async (response, doc, req): Promise<McpResponse> => {\n if (doc._status !== 'draft') return response\n\n const previewUrl = await resolvePreviewUrl(collection, doc, req, siteUrl)\n if (!previewUrl) {\n return {\n content: [\n ...response.content,\n {\n type: 'text',\n text: '\\n📋 This document is a draft. Use the admin panel to preview it.',\n },\n ],\n }\n }\n\n return {\n content: [\n ...response.content,\n {\n type: 'text',\n text: `\\n📋 This document is a draft. Preview it here: ${previewUrl}`,\n },\n ],\n }\n }\n}\n\n/**\n * Generates the mcpCollections config object for the official mcpPlugin.\n *\n * For each non-excluded collection:\n * - Enables `find` / `create` / `delete`; disables the official plugin's\n * raw `update<Resource>` tool universally. The toolkit's `updateDocument`\n * and `patchLayout` cover updates via the local API (and survive the\n * upload-field / schema-conversion bugs in the official plugin's update\n * path). Draft semantics are preserved by `publishDraft`.\n * - For draft collections: attaches an `overrideResponse` that appends a\n * preview URL — sourced from the collection's own livePreview/preview\n * function — to draft documents. Falls back to a generic admin-panel\n * message when no preview function is configured.\n *\n * @returns Map of slug → MCP collection config, plus the set of draft slugs\n */\nexport function generateMcpCollectionConfigs(\n collections: CollectionConfig[],\n options: GenerateOptions,\n): {\n mcpCollections: Record<string, McpCollectionConfig>\n draftCollections: Set<string>\n} {\n const mcpCollections: Record<string, McpCollectionConfig> = {}\n const draftCollections = new Set<string>()\n\n const excludeSlugs = new Set([\n 'payload-mcp-api-keys',\n ...(options.excludeCollections ?? []),\n ])\n\n for (const collection of collections) {\n if (excludeSlugs.has(collection.slug)) continue\n\n // Auth-enabled collections are users — never expose them via MCP.\n if ((collection as any).auth) continue\n\n const behavior = getDraftBehavior(collection, options)\n\n if (behavior !== 'publish') {\n draftCollections.add(collection.slug)\n }\n\n // Always disable the official plugin's per-collection `update<Resource>` tool.\n // It calls `convertCollectionSchemaToZod` and crashes on any collection\n // whose JSON schema can't be losslessly converted (richText, upload,\n // blocks fields → fallback returns `z.record()`, then `.partial()` throws).\n // The toolkit's `updateDocument` and `patchLayout` cover updates via the\n // local API and survive the upload-field / schema-conversion bugs, so the\n // raw update tool is redundant. See README \"What it adds → updateDocument\".\n const enabled = {\n find: true,\n create: true,\n update: false,\n delete: true,\n }\n\n const config: McpCollectionConfig = {\n description: `Manage ${collection.slug} content`,\n enabled,\n }\n\n if (draftCollections.has(collection.slug) && !options.previewDisabled) {\n config.overrideResponse = createOverrideResponse(collection, options.siteUrl)\n }\n\n mcpCollections[collection.slug] = config\n }\n\n return { mcpCollections, draftCollections }\n}\n"],"names":["hasCollectionDrafts","getDraftBehavior","collection","options","override","draftBehavior","slug","resolvePreviewUrl","doc","req","siteUrl","admin","locale","raw","livePreviewUrl","livePreview","url","data","code","label","payload","collectionConfig","preview","token","startsWith","base","endsWith","slice","path","createOverrideResponse","response","_status","previewUrl","content","type","text","generateMcpCollectionConfigs","collections","mcpCollections","draftCollections","Set","excludeSlugs","excludeCollections","has","auth","behavior","add","enabled","find","create","update","delete","config","description","previewDisabled","overrideResponse"],"mappings":"AACA,SAASA,mBAAmB,QAAQ,kBAAiB;AAwCrD;;;;;;CAMC,GACD,OAAO,SAASC,iBACdC,UAA4B,EAC5BC,OAA+E;IAE/E,IAAI,CAACH,oBAAoBE,aAAa,OAAO;IAE7C,MAAME,WAAWD,SAASE,eAAe,CAACH,WAAWI,IAAI,CAAC;IAC1D,IAAIF,UAAU,OAAOA;IAErB,OAAO;AACT;AAEA;;;;;;;CAOC,GACD,eAAeG,kBACbL,UAA4B,EAC5BM,GAA4B,EAC5BC,GAAmB,EACnBC,OAA2B;IAE3B,MAAMC,QAAST,WAAWS,KAAK,IAAI,CAAC;IACpC,MAAMC,SAAS,AAACH,IAAYG,MAAM,IAAI;IAEtC,IAAIC;IAEJ,MAAMC,iBAAiBH,MAAMI,WAAW,EAAEC;IAC1C,IAAI,OAAOF,mBAAmB,YAAY;QACxC,IAAI;YACFD,MAAM,MAAMC,eAAe;gBACzBG,MAAMT;gBACNI,QAAQ;oBAAEM,MAAMN;oBAAQO,OAAOP;gBAAO;gBACtCH;gBACAW,SAASX,IAAIW,OAAO;gBACpBC,kBAAkBnB;YACpB;QACF,EAAE,OAAM;YACNW,MAAM;QACR;IACF,OAAO,IAAI,OAAOC,mBAAmB,UAAU;QAC7CD,MAAMC;IACR;IAEA,IAAI,CAACD,OAAO,OAAOF,MAAMW,OAAO,KAAK,YAAY;QAC/C,IAAI;YACFT,MAAM,MAAMF,MAAMW,OAAO,CAACd,KAAK;gBAC7BI;gBACAH;gBACAc,OAAO;YACT;QACF,EAAE,OAAM;YACNV,MAAM;QACR;IACF;IAEA,IAAI,CAACA,OAAO,OAAOA,QAAQ,UAAU,OAAO;IAE5C,IAAIA,IAAIW,UAAU,CAAC,cAAcX,IAAIW,UAAU,CAAC,aAAa;QAC3D,OAAOX;IACT;IAEA,IAAI,CAACH,SAAS,OAAO;IAErB,MAAMe,OAAOf,QAAQgB,QAAQ,CAAC,OAAOhB,QAAQiB,KAAK,CAAC,GAAG,CAAC,KAAKjB;IAC5D,MAAMkB,OAAOf,IAAIW,UAAU,CAAC,OAAOX,MAAM,CAAC,CAAC,EAAEA,KAAK;IAClD,OAAO,GAAGY,OAAOG,MAAM;AACzB;AAEA,SAASC,uBACP3B,UAA4B,EAC5BQ,OAA2B;IAE3B,OAAO,OAAOoB,UAAUtB,KAAKC;QAC3B,IAAID,IAAIuB,OAAO,KAAK,SAAS,OAAOD;QAEpC,MAAME,aAAa,MAAMzB,kBAAkBL,YAAYM,KAAKC,KAAKC;QACjE,IAAI,CAACsB,YAAY;YACf,OAAO;gBACLC,SAAS;uBACJH,SAASG,OAAO;oBACnB;wBACEC,MAAM;wBACNC,MAAM;oBACR;iBACD;YACH;QACF;QAEA,OAAO;YACLF,SAAS;mBACJH,SAASG,OAAO;gBACnB;oBACEC,MAAM;oBACNC,MAAM,CAAC,gDAAgD,EAAEH,YAAY;gBACvE;aACD;QACH;IACF;AACF;AAEA;;;;;;;;;;;;;;;CAeC,GACD,OAAO,SAASI,6BACdC,WAA+B,EAC/BlC,OAAwB;IAKxB,MAAMmC,iBAAsD,CAAC;IAC7D,MAAMC,mBAAmB,IAAIC;IAE7B,MAAMC,eAAe,IAAID,IAAI;QAC3B;WACIrC,QAAQuC,kBAAkB,IAAI,EAAE;KACrC;IAED,KAAK,MAAMxC,cAAcmC,YAAa;QACpC,IAAII,aAAaE,GAAG,CAACzC,WAAWI,IAAI,GAAG;QAEvC,kEAAkE;QAClE,IAAI,AAACJ,WAAmB0C,IAAI,EAAE;QAE9B,MAAMC,WAAW5C,iBAAiBC,YAAYC;QAE9C,IAAI0C,aAAa,WAAW;YAC1BN,iBAAiBO,GAAG,CAAC5C,WAAWI,IAAI;QACtC;QAEA,+EAA+E;QAC/E,wEAAwE;QACxE,qEAAqE;QACrE,4EAA4E;QAC5E,yEAAyE;QACzE,0EAA0E;QAC1E,4EAA4E;QAC5E,MAAMyC,UAAU;YACdC,MAAM;YACNC,QAAQ;YACRC,QAAQ;YACRC,QAAQ;QACV;QAEA,MAAMC,SAA8B;YAClCC,aAAa,CAAC,OAAO,EAAEnD,WAAWI,IAAI,CAAC,QAAQ,CAAC;YAChDyC;QACF;QAEA,IAAIR,iBAAiBI,GAAG,CAACzC,WAAWI,IAAI,KAAK,CAACH,QAAQmD,eAAe,EAAE;YACrEF,OAAOG,gBAAgB,GAAG1B,uBAAuB3B,YAAYC,QAAQO,OAAO;QAC9E;QAEA4B,cAAc,CAACpC,WAAWI,IAAI,CAAC,GAAG8C;IACpC;IAEA,OAAO;QAAEd;QAAgBC;IAAiB;AAC5C"}
|
|
1
|
+
{"version":3,"sources":["../src/draft-workflow.ts"],"sourcesContent":["import type { CollectionConfig, PayloadRequest } from 'payload'\nimport { hasCollectionDrafts } from './introspection'\n\n/** MCP response shape used by overrideResponse */\ninterface McpResponse {\n content: Array<{ text: string; type: string }>\n}\n\n/** Per-collection MCP config with enabled operations and optional overrideResponse */\ninterface McpCollectionConfig {\n description: string\n enabled: {\n create: boolean\n delete: boolean\n find: boolean\n update: boolean\n }\n overrideResponse?: (\n response: McpResponse,\n doc: Record<string, unknown>,\n req: PayloadRequest,\n ) => McpResponse | Promise<McpResponse>\n}\n\ninterface GenerateOptions {\n /**\n * Optional absolute base URL prepended to relative preview paths returned\n * by the collection's own preview URL function. Resolved upstream from\n * (in order): `options.preview.siteUrl`, `incomingConfig.serverURL`,\n * `process.env.NEXT_PUBLIC_SERVER_URL`, `process.env.SITE_URL`. May be\n * undefined — relative-path returns will then be skipped.\n */\n siteUrl?: string\n /** Per-collection draft behavior overrides */\n draftBehavior?: Record<string, 'always-draft' | 'always-publish'>\n /** Collection slugs to exclude from MCP */\n excludeCollections?: string[]\n /** Disable preview URL injection entirely */\n previewDisabled?: boolean\n}\n\n/**\n * Determines the draft behavior for a collection.\n *\n * - No drafts configured → 'publish' (raw update allowed; no draft concept)\n * - Drafts configured + override given → use override\n * - Drafts configured + no override → 'always-draft' (raw update locked)\n */\nexport function getDraftBehavior(\n collection: CollectionConfig,\n options?: { draftBehavior?: Record<string, 'always-draft' | 'always-publish'> },\n): 'always-draft' | 'always-publish' | 'publish' {\n if (!hasCollectionDrafts(collection)) return 'publish'\n\n const override = options?.draftBehavior?.[collection.slug]\n if (override) return override\n\n return 'always-draft'\n}\n\n/**\n * Build a preview URL for a draft document by delegating to the collection's\n * own configured preview URL function. Tries `admin.livePreview.url` first\n * (the modern API), then `admin.preview` (the older `GeneratePreviewURL`).\n *\n * If neither is configured, or the function returns null/undefined/empty,\n * returns null and the override response will skip preview injection.\n */\nasync function resolvePreviewUrl(\n collection: CollectionConfig,\n doc: Record<string, unknown>,\n req: PayloadRequest,\n siteUrl: string | undefined,\n): Promise<string | null> {\n const admin = (collection.admin ?? {}) as Record<string, any>\n const locale = (req as any).locale ?? 'en'\n\n let raw: string | null | undefined\n\n const livePreviewUrl = admin.livePreview?.url\n if (typeof livePreviewUrl === 'function') {\n try {\n raw = await livePreviewUrl({\n data: doc,\n locale: { code: locale, label: locale },\n req,\n payload: req.payload,\n collectionConfig: collection as any,\n })\n } catch {\n raw = null\n }\n } else if (typeof livePreviewUrl === 'string') {\n raw = livePreviewUrl\n }\n\n if (!raw && typeof admin.preview === 'function') {\n try {\n raw = await admin.preview(doc, {\n locale,\n req,\n token: null,\n })\n } catch {\n raw = null\n }\n }\n\n if (!raw || typeof raw !== 'string') return null\n\n if (raw.startsWith('http://') || raw.startsWith('https://')) {\n return raw\n }\n\n if (!siteUrl) return null\n\n const base = siteUrl.endsWith('/') ? siteUrl.slice(0, -1) : siteUrl\n const path = raw.startsWith('/') ? raw : `/${raw}`\n return `${base}${path}`\n}\n\nfunction createOverrideResponse(\n collection: CollectionConfig,\n siteUrl: string | undefined,\n): McpCollectionConfig['overrideResponse'] {\n return async (response, doc, req): Promise<McpResponse> => {\n if (doc._status !== 'draft') return response\n\n const previewUrl = await resolvePreviewUrl(collection, doc, req, siteUrl)\n if (!previewUrl) {\n return {\n content: [\n ...response.content,\n {\n type: 'text',\n text: '\\n📋 This document is a draft. Use the admin panel to preview it.',\n },\n ],\n }\n }\n\n return {\n content: [\n ...response.content,\n {\n type: 'text',\n text: `\\n📋 This document is a draft. Preview it here: ${previewUrl}`,\n },\n ],\n }\n }\n}\n\n/**\n * Generates the mcpCollections config object for the official mcpPlugin.\n *\n * For each non-excluded collection:\n * - Enables `find` / `delete`; disables the official plugin's raw\n * `create<Resource>` and `update<Resource>` tools universally. Both\n * crash or silently drop fields on collections whose schemas contain\n * richText, upload, blocks, or relationship-array fields. The toolkit's\n * `createDocument` / `updateDocument` / `patchLayout` cover both ops via\n * the local API. Draft semantics are preserved by `publishDraft`.\n * - For draft collections: attaches an `overrideResponse` that appends a\n * preview URL — sourced from the collection's own livePreview/preview\n * function — to draft documents. Falls back to a generic admin-panel\n * message when no preview function is configured.\n *\n * @returns Map of slug → MCP collection config, plus the set of draft slugs\n */\nexport function generateMcpCollectionConfigs(\n collections: CollectionConfig[],\n options: GenerateOptions,\n): {\n mcpCollections: Record<string, McpCollectionConfig>\n draftCollections: Set<string>\n} {\n const mcpCollections: Record<string, McpCollectionConfig> = {}\n const draftCollections = new Set<string>()\n\n const excludeSlugs = new Set([\n 'payload-mcp-api-keys',\n ...(options.excludeCollections ?? []),\n ])\n\n for (const collection of collections) {\n if (excludeSlugs.has(collection.slug)) continue\n\n // Auth-enabled collections are users — never expose them via MCP.\n if ((collection as any).auth) continue\n\n const behavior = getDraftBehavior(collection, options)\n\n if (behavior !== 'publish') {\n draftCollections.add(collection.slug)\n }\n\n // Disable the official plugin's per-collection `create<Resource>` and\n // `update<Resource>` tools. Both call `convertCollectionSchemaToZod` and\n // produce broken input schemas on any collection whose JSON schema can't\n // be losslessly converted (richText, upload, blocks, relationship-array\n // fields → fallback returns `z.record()`):\n // - update<Resource>: throws `convertedFields.partial is not a function`\n // - create<Resource>: registers with metadata-only params, then the MCP\n // SDK strips every content field before it reaches `payload.create()`,\n // so creates fail required-field validation with empty data.\n // The toolkit's `createDocument` / `updateDocument` / `patchLayout` cover\n // both ops via the local API and survive these upstream bugs.\n const enabled = {\n find: true,\n create: false,\n update: false,\n delete: true,\n }\n\n const config: McpCollectionConfig = {\n description: `Manage ${collection.slug} content`,\n enabled,\n }\n\n if (draftCollections.has(collection.slug) && !options.previewDisabled) {\n config.overrideResponse = createOverrideResponse(collection, options.siteUrl)\n }\n\n mcpCollections[collection.slug] = config\n }\n\n return { mcpCollections, draftCollections }\n}\n"],"names":["hasCollectionDrafts","getDraftBehavior","collection","options","override","draftBehavior","slug","resolvePreviewUrl","doc","req","siteUrl","admin","locale","raw","livePreviewUrl","livePreview","url","data","code","label","payload","collectionConfig","preview","token","startsWith","base","endsWith","slice","path","createOverrideResponse","response","_status","previewUrl","content","type","text","generateMcpCollectionConfigs","collections","mcpCollections","draftCollections","Set","excludeSlugs","excludeCollections","has","auth","behavior","add","enabled","find","create","update","delete","config","description","previewDisabled","overrideResponse"],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -3,6 +3,7 @@ import { introspectCollections, introspectBlocks, buildBlockNestingMap, buildRel
|
|
|
3
3
|
import { generatePrompts } from './prompts';
|
|
4
4
|
import { generateResources } from './resources';
|
|
5
5
|
import { generateMcpCollectionConfigs } from './draft-workflow';
|
|
6
|
+
import { createCreateDocumentTool } from './tools/create-document';
|
|
6
7
|
import { createPatchLayoutTool } from './tools/patch-layout';
|
|
7
8
|
import { createPublishDraftTool } from './tools/publish-draft';
|
|
8
9
|
import { createResolveReferenceTool } from './tools/resolve-reference';
|
|
@@ -52,6 +53,7 @@ import { createListVersionsTool, createRestoreVersionTool } from './tools/versio
|
|
|
52
53
|
}
|
|
53
54
|
}
|
|
54
55
|
const tools = [
|
|
56
|
+
createCreateDocumentTool(collectionSchemas, draftCollections),
|
|
55
57
|
createPatchLayoutTool(blockCatalog, blockNesting, draftCollections),
|
|
56
58
|
createPublishDraftTool(draftCollections),
|
|
57
59
|
createResolveReferenceTool(searchableCollections),
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type { Block, CollectionConfig, Config, Plugin } from 'payload'\nimport { mcpPlugin } from '@payloadcms/plugin-mcp'\nimport type { ContentToolkitOptions } from './types'\nimport {\n introspectCollections,\n introspectBlocks,\n buildBlockNestingMap,\n buildRelationshipGraph,\n} from './introspection'\nimport { generatePrompts } from './prompts'\nimport { generateResources } from './resources'\nimport { generateMcpCollectionConfigs } from './draft-workflow'\nimport { createPatchLayoutTool } from './tools/patch-layout'\nimport { createPublishDraftTool } from './tools/publish-draft'\nimport { createResolveReferenceTool } from './tools/resolve-reference'\nimport { createSafeDeleteTool } from './tools/safe-delete'\nimport { createSchedulePublishTool } from './tools/schedule-publish'\nimport { createSearchContentTool } from './tools/search-content'\nimport { createUpdateDocumentTool } from './tools/update-document'\nimport { createUploadMediaTool } from './tools/upload-media'\nimport { createListVersionsTool, createRestoreVersionTool } from './tools/versions'\n\n/**\n * Payload MCP Toolkit\n *\n * Layered on top of the official @payloadcms/plugin-mcp. The toolkit\n * introspects your Payload config and registers schema-aware prompts,\n * resources, and tools so AI clients can drive the CMS without\n * hand-built plumbing.\n *\n * Zero-config usage:\n * ```ts\n * plugins: [contentToolkitPlugin()]\n * ```\n *\n * Every option below is an optional escape hatch — see ContentToolkitOptions.\n */\nexport function contentToolkitPlugin(options: ContentToolkitOptions = {}): Plugin {\n return (incomingConfig: Config): Config => {\n const collections = (incomingConfig.collections ?? []) as CollectionConfig[]\n const allBlocks = (incomingConfig.blocks ?? []) as Block[]\n\n const collectionSchemas = introspectCollections(collections)\n const blockCatalog = introspectBlocks(allBlocks)\n const blockNesting = buildBlockNestingMap(collections, allBlocks)\n const relationships = buildRelationshipGraph(collectionSchemas)\n\n // Preview siteUrl resolves: explicit option → Payload serverURL → env vars.\n // May be undefined; relative-path preview URLs are skipped in that case.\n const previewSiteUrl =\n options.preview?.siteUrl ??\n incomingConfig.serverURL ??\n process.env.NEXT_PUBLIC_SERVER_URL ??\n process.env.SITE_URL\n\n const prompts = generatePrompts(\n collectionSchemas,\n blockCatalog,\n blockNesting,\n relationships,\n options.domainPrompts,\n )\n const resources = generateResources(\n collectionSchemas,\n blockCatalog,\n blockNesting,\n relationships,\n )\n\n const { mcpCollections, draftCollections } = generateMcpCollectionConfigs(collections, {\n siteUrl: previewSiteUrl,\n draftBehavior: options.draftBehavior,\n excludeCollections: options.exclude?.collections,\n previewDisabled: options.preview?.disabled,\n })\n\n const searchableCollections = new Map<string, string[]>()\n for (const [slug, schema] of collectionSchemas) {\n if (schema.searchableFields.length > 0) {\n searchableCollections.set(slug, schema.searchableFields)\n }\n }\n\n const tools: any[] = [\n createPatchLayoutTool(blockCatalog, blockNesting, draftCollections),\n createPublishDraftTool(draftCollections),\n createResolveReferenceTool(searchableCollections),\n createSafeDeleteTool(relationships),\n createSearchContentTool(collectionSchemas),\n createUpdateDocumentTool(collectionSchemas, draftCollections),\n createUploadMediaTool({\n maxFileSize: options.mediaUpload?.maxFileSize,\n collectionSlug: options.mediaUpload?.collectionSlug,\n }),\n createListVersionsTool(draftCollections),\n createRestoreVersionTool(draftCollections),\n ]\n\n const schedulePublish = createSchedulePublishTool(collectionSchemas, draftCollections)\n if (schedulePublish) tools.push(schedulePublish)\n\n // Globals get `find` only. The official plugin's `update<Global>` tool\n // hits the same `convertCollectionSchemaToZod` path that crashes on\n // richText / upload / blocks fields (here it throws\n // `Cannot convert undefined or null to object` because globals/update.ts\n // calls `Object.entries(convertedFields.shape)` and the fallback\n // `z.record()` has no `.shape`). Until the toolkit's `updateDocument`\n // gains global support, edit globals via the admin panel.\n const mcpGlobals: Record<\n string,\n { enabled: { find: boolean; update: boolean }; description?: string }\n > = {}\n const excludeGlobalSlugs = new Set(options.exclude?.globals ?? [])\n for (const global of (incomingConfig.globals ?? []) as Array<{ slug: string }>) {\n if (excludeGlobalSlugs.has(global.slug)) continue\n mcpGlobals[global.slug] = {\n enabled: { find: true, update: false },\n description: `Read ${global.slug} global settings`,\n }\n }\n\n // overrideAuth rebinds req.user from the API key's linked user so our\n // custom tools' `overrideAccess: false` checks run against the right\n // identity. userCollection passthrough lets the official plugin fall\n // back to `incomingConfig.admin.user`.\n const withMcp = mcpPlugin({\n collections: mcpCollections as any,\n globals: mcpGlobals as any,\n userCollection: options.userCollection as any,\n mcp: {\n tools: tools as any[],\n prompts: prompts as any[],\n resources: resources as any[],\n },\n overrideAuth: async (req, getDefault) => {\n const settings = await getDefault()\n req.user = (settings as any).user\n return settings\n },\n })\n\n return withMcp(incomingConfig)\n }\n}\n\nexport type {\n ContentToolkitOptions,\n DomainPrompt,\n CollectionSchema,\n BlockCatalog,\n BlockSchema,\n BlockNestingMap,\n BlockNestingEdge,\n RelationshipEdge,\n FieldSchema,\n} from './types'\n"],"names":["mcpPlugin","introspectCollections","introspectBlocks","buildBlockNestingMap","buildRelationshipGraph","generatePrompts","generateResources","generateMcpCollectionConfigs","createPatchLayoutTool","createPublishDraftTool","createResolveReferenceTool","createSafeDeleteTool","createSchedulePublishTool","createSearchContentTool","createUpdateDocumentTool","createUploadMediaTool","createListVersionsTool","createRestoreVersionTool","contentToolkitPlugin","options","incomingConfig","collections","allBlocks","blocks","collectionSchemas","blockCatalog","blockNesting","relationships","previewSiteUrl","preview","siteUrl","serverURL","process","env","NEXT_PUBLIC_SERVER_URL","SITE_URL","prompts","domainPrompts","resources","mcpCollections","draftCollections","draftBehavior","excludeCollections","exclude","previewDisabled","disabled","searchableCollections","Map","slug","schema","searchableFields","length","set","tools","maxFileSize","mediaUpload","collectionSlug","schedulePublish","push","mcpGlobals","excludeGlobalSlugs","Set","globals","global","has","enabled","find","update","description","withMcp","userCollection","mcp","overrideAuth","req","getDefault","settings","user"],"mappings":"AACA,SAASA,SAAS,QAAQ,yBAAwB;AAElD,SACEC,qBAAqB,EACrBC,gBAAgB,EAChBC,oBAAoB,EACpBC,sBAAsB,QACjB,kBAAiB;AACxB,SAASC,eAAe,QAAQ,YAAW;AAC3C,SAASC,iBAAiB,QAAQ,cAAa;AAC/C,SAASC,4BAA4B,QAAQ,mBAAkB;AAC/D,SAASC,qBAAqB,QAAQ,uBAAsB;AAC5D,SAASC,sBAAsB,QAAQ,wBAAuB;AAC9D,SAASC,0BAA0B,QAAQ,4BAA2B;AACtE,SAASC,oBAAoB,QAAQ,sBAAqB;AAC1D,SAASC,yBAAyB,QAAQ,2BAA0B;AACpE,SAASC,uBAAuB,QAAQ,yBAAwB;AAChE,SAASC,wBAAwB,QAAQ,0BAAyB;AAClE,SAASC,qBAAqB,QAAQ,uBAAsB;AAC5D,SAASC,sBAAsB,EAAEC,wBAAwB,QAAQ,mBAAkB;AAEnF;;;;;;;;;;;;;;CAcC,GACD,OAAO,SAASC,qBAAqBC,UAAiC,CAAC,CAAC;IACtE,OAAO,CAACC;QACN,MAAMC,cAAeD,eAAeC,WAAW,IAAI,EAAE;QACrD,MAAMC,YAAaF,eAAeG,MAAM,IAAI,EAAE;QAE9C,MAAMC,
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type { Block, CollectionConfig, Config, Plugin } from 'payload'\nimport { mcpPlugin } from '@payloadcms/plugin-mcp'\nimport type { ContentToolkitOptions } from './types'\nimport {\n introspectCollections,\n introspectBlocks,\n buildBlockNestingMap,\n buildRelationshipGraph,\n} from './introspection'\nimport { generatePrompts } from './prompts'\nimport { generateResources } from './resources'\nimport { generateMcpCollectionConfigs } from './draft-workflow'\nimport { createCreateDocumentTool } from './tools/create-document'\nimport { createPatchLayoutTool } from './tools/patch-layout'\nimport { createPublishDraftTool } from './tools/publish-draft'\nimport { createResolveReferenceTool } from './tools/resolve-reference'\nimport { createSafeDeleteTool } from './tools/safe-delete'\nimport { createSchedulePublishTool } from './tools/schedule-publish'\nimport { createSearchContentTool } from './tools/search-content'\nimport { createUpdateDocumentTool } from './tools/update-document'\nimport { createUploadMediaTool } from './tools/upload-media'\nimport { createListVersionsTool, createRestoreVersionTool } from './tools/versions'\n\n/**\n * Payload MCP Toolkit\n *\n * Layered on top of the official @payloadcms/plugin-mcp. The toolkit\n * introspects your Payload config and registers schema-aware prompts,\n * resources, and tools so AI clients can drive the CMS without\n * hand-built plumbing.\n *\n * Zero-config usage:\n * ```ts\n * plugins: [contentToolkitPlugin()]\n * ```\n *\n * Every option below is an optional escape hatch — see ContentToolkitOptions.\n */\nexport function contentToolkitPlugin(options: ContentToolkitOptions = {}): Plugin {\n return (incomingConfig: Config): Config => {\n const collections = (incomingConfig.collections ?? []) as CollectionConfig[]\n const allBlocks = (incomingConfig.blocks ?? []) as Block[]\n\n const collectionSchemas = introspectCollections(collections)\n const blockCatalog = introspectBlocks(allBlocks)\n const blockNesting = buildBlockNestingMap(collections, allBlocks)\n const relationships = buildRelationshipGraph(collectionSchemas)\n\n // Preview siteUrl resolves: explicit option → Payload serverURL → env vars.\n // May be undefined; relative-path preview URLs are skipped in that case.\n const previewSiteUrl =\n options.preview?.siteUrl ??\n incomingConfig.serverURL ??\n process.env.NEXT_PUBLIC_SERVER_URL ??\n process.env.SITE_URL\n\n const prompts = generatePrompts(\n collectionSchemas,\n blockCatalog,\n blockNesting,\n relationships,\n options.domainPrompts,\n )\n const resources = generateResources(\n collectionSchemas,\n blockCatalog,\n blockNesting,\n relationships,\n )\n\n const { mcpCollections, draftCollections } = generateMcpCollectionConfigs(collections, {\n siteUrl: previewSiteUrl,\n draftBehavior: options.draftBehavior,\n excludeCollections: options.exclude?.collections,\n previewDisabled: options.preview?.disabled,\n })\n\n const searchableCollections = new Map<string, string[]>()\n for (const [slug, schema] of collectionSchemas) {\n if (schema.searchableFields.length > 0) {\n searchableCollections.set(slug, schema.searchableFields)\n }\n }\n\n const tools: any[] = [\n createCreateDocumentTool(collectionSchemas, draftCollections),\n createPatchLayoutTool(blockCatalog, blockNesting, draftCollections),\n createPublishDraftTool(draftCollections),\n createResolveReferenceTool(searchableCollections),\n createSafeDeleteTool(relationships),\n createSearchContentTool(collectionSchemas),\n createUpdateDocumentTool(collectionSchemas, draftCollections),\n createUploadMediaTool({\n maxFileSize: options.mediaUpload?.maxFileSize,\n collectionSlug: options.mediaUpload?.collectionSlug,\n }),\n createListVersionsTool(draftCollections),\n createRestoreVersionTool(draftCollections),\n ]\n\n const schedulePublish = createSchedulePublishTool(collectionSchemas, draftCollections)\n if (schedulePublish) tools.push(schedulePublish)\n\n // Globals get `find` only. The official plugin's `update<Global>` tool\n // hits the same `convertCollectionSchemaToZod` path that crashes on\n // richText / upload / blocks fields (here it throws\n // `Cannot convert undefined or null to object` because globals/update.ts\n // calls `Object.entries(convertedFields.shape)` and the fallback\n // `z.record()` has no `.shape`). Until the toolkit's `updateDocument`\n // gains global support, edit globals via the admin panel.\n const mcpGlobals: Record<\n string,\n { enabled: { find: boolean; update: boolean }; description?: string }\n > = {}\n const excludeGlobalSlugs = new Set(options.exclude?.globals ?? [])\n for (const global of (incomingConfig.globals ?? []) as Array<{ slug: string }>) {\n if (excludeGlobalSlugs.has(global.slug)) continue\n mcpGlobals[global.slug] = {\n enabled: { find: true, update: false },\n description: `Read ${global.slug} global settings`,\n }\n }\n\n // overrideAuth rebinds req.user from the API key's linked user so our\n // custom tools' `overrideAccess: false` checks run against the right\n // identity. userCollection passthrough lets the official plugin fall\n // back to `incomingConfig.admin.user`.\n const withMcp = mcpPlugin({\n collections: mcpCollections as any,\n globals: mcpGlobals as any,\n userCollection: options.userCollection as any,\n mcp: {\n tools: tools as any[],\n prompts: prompts as any[],\n resources: resources as any[],\n },\n overrideAuth: async (req, getDefault) => {\n const settings = await getDefault()\n req.user = (settings as any).user\n return settings\n },\n })\n\n return withMcp(incomingConfig)\n }\n}\n\nexport type {\n ContentToolkitOptions,\n DomainPrompt,\n CollectionSchema,\n BlockCatalog,\n BlockSchema,\n BlockNestingMap,\n BlockNestingEdge,\n RelationshipEdge,\n FieldSchema,\n} from './types'\n"],"names":["mcpPlugin","introspectCollections","introspectBlocks","buildBlockNestingMap","buildRelationshipGraph","generatePrompts","generateResources","generateMcpCollectionConfigs","createCreateDocumentTool","createPatchLayoutTool","createPublishDraftTool","createResolveReferenceTool","createSafeDeleteTool","createSchedulePublishTool","createSearchContentTool","createUpdateDocumentTool","createUploadMediaTool","createListVersionsTool","createRestoreVersionTool","contentToolkitPlugin","options","incomingConfig","collections","allBlocks","blocks","collectionSchemas","blockCatalog","blockNesting","relationships","previewSiteUrl","preview","siteUrl","serverURL","process","env","NEXT_PUBLIC_SERVER_URL","SITE_URL","prompts","domainPrompts","resources","mcpCollections","draftCollections","draftBehavior","excludeCollections","exclude","previewDisabled","disabled","searchableCollections","Map","slug","schema","searchableFields","length","set","tools","maxFileSize","mediaUpload","collectionSlug","schedulePublish","push","mcpGlobals","excludeGlobalSlugs","Set","globals","global","has","enabled","find","update","description","withMcp","userCollection","mcp","overrideAuth","req","getDefault","settings","user"],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import type { PayloadRequest } from 'payload';
|
|
3
|
+
import type { CollectionSchema } from '../types';
|
|
4
|
+
/**
|
|
5
|
+
* Custom replacement for the official plugin's `create<Resource>` tools.
|
|
6
|
+
*
|
|
7
|
+
* The official plugin builds its create-tool input schema by spreading
|
|
8
|
+
* `convertCollectionSchemaToZod(schema).shape`, then validates the request
|
|
9
|
+
* with `additionalProperties: false`. For any collection whose JSON schema
|
|
10
|
+
* trips `json-schema-to-zod` (richText, upload, blocks, relationship arrays
|
|
11
|
+
* — i.e. virtually every real-world content collection), the converter
|
|
12
|
+
* falls back to `z.record(z.any())`, `.shape` is undefined, and the spread
|
|
13
|
+
* silently produces a metadata-only schema. The MCP SDK then strips every
|
|
14
|
+
* content field before it reaches `payload.create()`, so creates end up
|
|
15
|
+
* with empty `data` and fail required-field validation.
|
|
16
|
+
*
|
|
17
|
+
* `createDocument` sidesteps the whole pipeline: take a JSON `data` string,
|
|
18
|
+
* call `payload.create()` directly via the local API.
|
|
19
|
+
*
|
|
20
|
+
* Defaults to `draft: true` for draft-enabled collections so newly created
|
|
21
|
+
* documents land in the same draft-first workflow used by `updateDocument`.
|
|
22
|
+
*/
|
|
23
|
+
export declare function createCreateDocumentTool(collectionSchemas: Map<string, CollectionSchema>, draftCollections: Set<string>): {
|
|
24
|
+
name: string;
|
|
25
|
+
description: string;
|
|
26
|
+
parameters: {
|
|
27
|
+
collection: z.ZodString;
|
|
28
|
+
data: z.ZodString;
|
|
29
|
+
draft: z.ZodOptional<z.ZodBoolean>;
|
|
30
|
+
};
|
|
31
|
+
handler: (args: {
|
|
32
|
+
collection: string;
|
|
33
|
+
data: string;
|
|
34
|
+
draft?: boolean;
|
|
35
|
+
}, req: PayloadRequest, _extra: unknown) => Promise<import("./_helpers").McpTextResponse>;
|
|
36
|
+
};
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { DRAFT_NOTE, errorMessage, getDocDisplayName, stampMcpContext, textResponse } from './_helpers';
|
|
3
|
+
const MEDIA_SLUG = 'media';
|
|
4
|
+
/**
|
|
5
|
+
* Custom replacement for the official plugin's `create<Resource>` tools.
|
|
6
|
+
*
|
|
7
|
+
* The official plugin builds its create-tool input schema by spreading
|
|
8
|
+
* `convertCollectionSchemaToZod(schema).shape`, then validates the request
|
|
9
|
+
* with `additionalProperties: false`. For any collection whose JSON schema
|
|
10
|
+
* trips `json-schema-to-zod` (richText, upload, blocks, relationship arrays
|
|
11
|
+
* — i.e. virtually every real-world content collection), the converter
|
|
12
|
+
* falls back to `z.record(z.any())`, `.shape` is undefined, and the spread
|
|
13
|
+
* silently produces a metadata-only schema. The MCP SDK then strips every
|
|
14
|
+
* content field before it reaches `payload.create()`, so creates end up
|
|
15
|
+
* with empty `data` and fail required-field validation.
|
|
16
|
+
*
|
|
17
|
+
* `createDocument` sidesteps the whole pipeline: take a JSON `data` string,
|
|
18
|
+
* call `payload.create()` directly via the local API.
|
|
19
|
+
*
|
|
20
|
+
* Defaults to `draft: true` for draft-enabled collections so newly created
|
|
21
|
+
* documents land in the same draft-first workflow used by `updateDocument`.
|
|
22
|
+
*/ export function createCreateDocumentTool(collectionSchemas, draftCollections) {
|
|
23
|
+
const creatableSlugs = [];
|
|
24
|
+
const descriptionLines = [];
|
|
25
|
+
for (const [slug, schema] of collectionSchemas){
|
|
26
|
+
if (slug === MEDIA_SLUG) continue;
|
|
27
|
+
creatableSlugs.push(slug);
|
|
28
|
+
descriptionLines.push(` - "${slug}": ${schema.fields.map((f)=>f.name).join(', ')}`);
|
|
29
|
+
}
|
|
30
|
+
const collectionDescriptions = descriptionLines.join('\n');
|
|
31
|
+
return {
|
|
32
|
+
name: 'createDocument',
|
|
33
|
+
description: 'Create a new document in any collection. Pass the field values as a JSON string in `data`. ' + 'For draft-enabled collections, the document is created as a draft by default — use publishDraft to make it live, ' + 'or pass `draft: false` to publish immediately. ' + 'For relationship fields, pass the related document ID (use resolveReference to find IDs). ' + 'For upload fields, pass the media document ID (use uploadMedia to create one first).\n\n' + 'Available collections and their fields:\n' + collectionDescriptions,
|
|
34
|
+
parameters: {
|
|
35
|
+
collection: z.string().describe(`The collection slug. One of: ${creatableSlugs.join(', ')}`),
|
|
36
|
+
data: z.string().describe('JSON string of field names to values for the new document. ' + 'Examples: \'{"name": "Aria", "slug": "aria"}\', ' + '\'{"title": "First-Time Clients", "heroTitle": "Welcome", "slug": "first-time-clients"}\''),
|
|
37
|
+
draft: z.boolean().optional().describe('Override draft status. Defaults to `true` for draft-enabled collections, `false` otherwise. ' + 'Set explicitly to `false` on a draft-enabled collection to publish immediately.')
|
|
38
|
+
},
|
|
39
|
+
handler: async (args, req, _extra)=>{
|
|
40
|
+
const { collection } = args;
|
|
41
|
+
let data;
|
|
42
|
+
try {
|
|
43
|
+
data = JSON.parse(args.data);
|
|
44
|
+
} catch {
|
|
45
|
+
return textResponse('Error: "data" must be a valid JSON string. Example: \'{"name": "Aria", "slug": "aria"}\'');
|
|
46
|
+
}
|
|
47
|
+
if (!collectionSchemas.has(collection)) {
|
|
48
|
+
return textResponse(`Error: Unknown collection "${collection}". Available: ${creatableSlugs.join(', ')}`);
|
|
49
|
+
}
|
|
50
|
+
if (collection === MEDIA_SLUG) {
|
|
51
|
+
return textResponse('Error: Use the uploadMedia tool to create media files.');
|
|
52
|
+
}
|
|
53
|
+
if (!data || Object.keys(data).length === 0) {
|
|
54
|
+
return textResponse('Error: No fields provided in "data". Pass an object with field names and values for the new document.');
|
|
55
|
+
}
|
|
56
|
+
stampMcpContext(req);
|
|
57
|
+
const isDraftCollection = draftCollections.has(collection);
|
|
58
|
+
const asDraft = args.draft ?? isDraftCollection;
|
|
59
|
+
try {
|
|
60
|
+
const doc = await req.payload.create({
|
|
61
|
+
collection: collection,
|
|
62
|
+
data: data,
|
|
63
|
+
draft: asDraft,
|
|
64
|
+
req,
|
|
65
|
+
overrideAccess: false,
|
|
66
|
+
user: req.user
|
|
67
|
+
});
|
|
68
|
+
const displayName = getDocDisplayName(doc, String(doc.id ?? ''));
|
|
69
|
+
const newId = String(doc.id ?? '');
|
|
70
|
+
const draftNote = isDraftCollection && asDraft ? DRAFT_NOTE : '';
|
|
71
|
+
return textResponse(`Created "${displayName}" in ${collection} (ID: ${newId}).${draftNote}`);
|
|
72
|
+
} catch (error) {
|
|
73
|
+
return textResponse(`Error creating document in ${collection}: ${errorMessage(error)}`);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
//# sourceMappingURL=create-document.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/tools/create-document.ts"],"sourcesContent":["import { z } from 'zod'\nimport type { PayloadRequest } from 'payload'\nimport type { CollectionSchema } from '../types'\nimport {\n DRAFT_NOTE,\n errorMessage,\n getDocDisplayName,\n stampMcpContext,\n textResponse,\n} from './_helpers'\n\nconst MEDIA_SLUG = 'media'\n\n/**\n * Custom replacement for the official plugin's `create<Resource>` tools.\n *\n * The official plugin builds its create-tool input schema by spreading\n * `convertCollectionSchemaToZod(schema).shape`, then validates the request\n * with `additionalProperties: false`. For any collection whose JSON schema\n * trips `json-schema-to-zod` (richText, upload, blocks, relationship arrays\n * — i.e. virtually every real-world content collection), the converter\n * falls back to `z.record(z.any())`, `.shape` is undefined, and the spread\n * silently produces a metadata-only schema. The MCP SDK then strips every\n * content field before it reaches `payload.create()`, so creates end up\n * with empty `data` and fail required-field validation.\n *\n * `createDocument` sidesteps the whole pipeline: take a JSON `data` string,\n * call `payload.create()` directly via the local API.\n *\n * Defaults to `draft: true` for draft-enabled collections so newly created\n * documents land in the same draft-first workflow used by `updateDocument`.\n */\nexport function createCreateDocumentTool(\n collectionSchemas: Map<string, CollectionSchema>,\n draftCollections: Set<string>,\n) {\n const creatableSlugs: string[] = []\n const descriptionLines: string[] = []\n for (const [slug, schema] of collectionSchemas) {\n if (slug === MEDIA_SLUG) continue\n creatableSlugs.push(slug)\n descriptionLines.push(` - \"${slug}\": ${schema.fields.map((f) => f.name).join(', ')}`)\n }\n const collectionDescriptions = descriptionLines.join('\\n')\n\n return {\n name: 'createDocument',\n description:\n 'Create a new document in any collection. Pass the field values as a JSON string in `data`. ' +\n 'For draft-enabled collections, the document is created as a draft by default — use publishDraft to make it live, ' +\n 'or pass `draft: false` to publish immediately. ' +\n 'For relationship fields, pass the related document ID (use resolveReference to find IDs). ' +\n 'For upload fields, pass the media document ID (use uploadMedia to create one first).\\n\\n' +\n 'Available collections and their fields:\\n' +\n collectionDescriptions,\n parameters: {\n collection: z\n .string()\n .describe(`The collection slug. One of: ${creatableSlugs.join(', ')}`),\n data: z\n .string()\n .describe(\n 'JSON string of field names to values for the new document. ' +\n 'Examples: \\'{\"name\": \"Aria\", \"slug\": \"aria\"}\\', ' +\n '\\'{\"title\": \"First-Time Clients\", \"heroTitle\": \"Welcome\", \"slug\": \"first-time-clients\"}\\'',\n ),\n draft: z\n .boolean()\n .optional()\n .describe(\n 'Override draft status. Defaults to `true` for draft-enabled collections, `false` otherwise. ' +\n 'Set explicitly to `false` on a draft-enabled collection to publish immediately.',\n ),\n },\n handler: async (\n args: { collection: string; data: string; draft?: boolean },\n req: PayloadRequest,\n _extra: unknown,\n ) => {\n const { collection } = args\n\n let data: Record<string, unknown>\n try {\n data = JSON.parse(args.data)\n } catch {\n return textResponse(\n 'Error: \"data\" must be a valid JSON string. Example: \\'{\"name\": \"Aria\", \"slug\": \"aria\"}\\'',\n )\n }\n\n if (!collectionSchemas.has(collection)) {\n return textResponse(\n `Error: Unknown collection \"${collection}\". Available: ${creatableSlugs.join(', ')}`,\n )\n }\n\n if (collection === MEDIA_SLUG) {\n return textResponse('Error: Use the uploadMedia tool to create media files.')\n }\n\n if (!data || Object.keys(data).length === 0) {\n return textResponse(\n 'Error: No fields provided in \"data\". Pass an object with field names and values for the new document.',\n )\n }\n\n stampMcpContext(req)\n\n const isDraftCollection = draftCollections.has(collection)\n const asDraft = args.draft ?? isDraftCollection\n\n try {\n const doc = await req.payload.create({\n collection: collection as any,\n data: data as any,\n draft: asDraft,\n req,\n overrideAccess: false,\n user: req.user,\n })\n\n const displayName = getDocDisplayName(doc, String((doc as { id?: unknown }).id ?? ''))\n const newId = String((doc as { id?: unknown }).id ?? '')\n const draftNote = isDraftCollection && asDraft ? DRAFT_NOTE : ''\n\n return textResponse(\n `Created \"${displayName}\" in ${collection} (ID: ${newId}).${draftNote}`,\n )\n } catch (error) {\n return textResponse(\n `Error creating document in ${collection}: ${errorMessage(error)}`,\n )\n }\n },\n }\n}\n"],"names":["z","DRAFT_NOTE","errorMessage","getDocDisplayName","stampMcpContext","textResponse","MEDIA_SLUG","createCreateDocumentTool","collectionSchemas","draftCollections","creatableSlugs","descriptionLines","slug","schema","push","fields","map","f","name","join","collectionDescriptions","description","parameters","collection","string","describe","data","draft","boolean","optional","handler","args","req","_extra","JSON","parse","has","Object","keys","length","isDraftCollection","asDraft","doc","payload","create","overrideAccess","user","displayName","String","id","newId","draftNote","error"],"mappings":"AAAA,SAASA,CAAC,QAAQ,MAAK;AAGvB,SACEC,UAAU,EACVC,YAAY,EACZC,iBAAiB,EACjBC,eAAe,EACfC,YAAY,QACP,aAAY;AAEnB,MAAMC,aAAa;AAEnB;;;;;;;;;;;;;;;;;;CAkBC,GACD,OAAO,SAASC,yBACdC,iBAAgD,EAChDC,gBAA6B;IAE7B,MAAMC,iBAA2B,EAAE;IACnC,MAAMC,mBAA6B,EAAE;IACrC,KAAK,MAAM,CAACC,MAAMC,OAAO,IAAIL,kBAAmB;QAC9C,IAAII,SAASN,YAAY;QACzBI,eAAeI,IAAI,CAACF;QACpBD,iBAAiBG,IAAI,CAAC,CAAC,KAAK,EAAEF,KAAK,GAAG,EAAEC,OAAOE,MAAM,CAACC,GAAG,CAAC,CAACC,IAAMA,EAAEC,IAAI,EAAEC,IAAI,CAAC,OAAO;IACvF;IACA,MAAMC,yBAAyBT,iBAAiBQ,IAAI,CAAC;IAErD,OAAO;QACLD,MAAM;QACNG,aACE,gGACA,sHACA,oDACA,+FACA,6FACA,8CACAD;QACFE,YAAY;YACVC,YAAYvB,EACTwB,MAAM,GACNC,QAAQ,CAAC,CAAC,6BAA6B,EAAEf,eAAeS,IAAI,CAAC,OAAO;YACvEO,MAAM1B,EACHwB,MAAM,GACNC,QAAQ,CACP,gEACE,qDACA;YAENE,OAAO3B,EACJ4B,OAAO,GACPC,QAAQ,GACRJ,QAAQ,CACP,iGACE;QAER;QACAK,SAAS,OACPC,MACAC,KACAC;YAEA,MAAM,EAAEV,UAAU,EAAE,GAAGQ;YAEvB,IAAIL;YACJ,IAAI;gBACFA,OAAOQ,KAAKC,KAAK,CAACJ,KAAKL,IAAI;YAC7B,EAAE,OAAM;gBACN,OAAOrB,aACL;YAEJ;YAEA,IAAI,CAACG,kBAAkB4B,GAAG,CAACb,aAAa;gBACtC,OAAOlB,aACL,CAAC,2BAA2B,EAAEkB,WAAW,cAAc,EAAEb,eAAeS,IAAI,CAAC,OAAO;YAExF;YAEA,IAAII,eAAejB,YAAY;gBAC7B,OAAOD,aAAa;YACtB;YAEA,IAAI,CAACqB,QAAQW,OAAOC,IAAI,CAACZ,MAAMa,MAAM,KAAK,GAAG;gBAC3C,OAAOlC,aACL;YAEJ;YAEAD,gBAAgB4B;YAEhB,MAAMQ,oBAAoB/B,iBAAiB2B,GAAG,CAACb;YAC/C,MAAMkB,UAAUV,KAAKJ,KAAK,IAAIa;YAE9B,IAAI;gBACF,MAAME,MAAM,MAAMV,IAAIW,OAAO,CAACC,MAAM,CAAC;oBACnCrB,YAAYA;oBACZG,MAAMA;oBACNC,OAAOc;oBACPT;oBACAa,gBAAgB;oBAChBC,MAAMd,IAAIc,IAAI;gBAChB;gBAEA,MAAMC,cAAc5C,kBAAkBuC,KAAKM,OAAO,AAACN,IAAyBO,EAAE,IAAI;gBAClF,MAAMC,QAAQF,OAAO,AAACN,IAAyBO,EAAE,IAAI;gBACrD,MAAME,YAAYX,qBAAqBC,UAAUxC,aAAa;gBAE9D,OAAOI,aACL,CAAC,SAAS,EAAE0C,YAAY,KAAK,EAAExB,WAAW,MAAM,EAAE2B,MAAM,EAAE,EAAEC,WAAW;YAE3E,EAAE,OAAOC,OAAO;gBACd,OAAO/C,aACL,CAAC,2BAA2B,EAAEkB,WAAW,EAAE,EAAErB,aAAakD,QAAQ;YAEtE;QACF;IACF;AACF"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "payload-mcp-toolkit",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.4",
|
|
4
4
|
"description": "Schema-aware MCP toolkit for Payload CMS — wraps the official @payloadcms/plugin-mcp with introspected prompts, resources, draft workflow, and AI-friendly tools so non-technical editors can manage content via AI chat.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "jon8800",
|