@payloadcms/plugin-mcp 3.65.0-internal.d8c3085 → 3.65.0-internal.ef335bd
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/dist/endpoints/mcp.js.map +1 -1
- package/dist/mcp/getMcpHandler.d.ts.map +1 -1
- package/dist/mcp/getMcpHandler.js +14 -3
- package/dist/mcp/getMcpHandler.js.map +1 -1
- package/dist/mcp/helpers/fileValidation.js +22 -22
- package/dist/mcp/helpers/fileValidation.js.map +1 -1
- package/dist/types.d.ts +39 -4
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/utils/convertCollectionSchemaToZod.d.ts.map +1 -1
- package/dist/utils/convertCollectionSchemaToZod.js +1 -2
- package/dist/utils/convertCollectionSchemaToZod.js.map +1 -1
- package/package.json +3 -3
- package/src/endpoints/mcp.ts +1 -1
- package/src/mcp/getMcpHandler.ts +31 -4
- package/src/mcp/helpers/fileValidation.ts +22 -22
- package/src/types.ts +58 -9
- package/src/utils/convertCollectionSchemaToZod.ts +1 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/endpoints/mcp.ts"],"sourcesContent":["import crypto from 'crypto'\nimport { type PayloadHandler, UnauthorizedError, type Where } from 'payload'\n\nimport type { MCPAccessSettings, PluginMCPServerConfig } from '../types.js'\n\nimport { createRequestFromPayloadRequest } from '../mcp/createRequest.js'\nimport { getMCPHandler } from '../mcp/getMcpHandler.js'\n\nexport const initializeMCPHandler = (pluginOptions: PluginMCPServerConfig) => {\n const mcpHandler: PayloadHandler = async (req) => {\n const { payload } = req\n const MCPOptions = pluginOptions.mcp || {}\n const MCPHandlerOptions = MCPOptions.handlerOptions || {}\n const useVerboseLogs = MCPHandlerOptions.verboseLogs ?? false\n\n req.payloadAPI = 'MCP' as const\n\n const getDefaultMcpAccessSettings = async (overrideApiKey?: null | string) => {\n const apiKey =\n (overrideApiKey ?? req.headers.get('Authorization')?.startsWith('Bearer '))\n ? req.headers.get('Authorization')?.replace('Bearer ', '').trim()\n : null\n\n if (apiKey === null) {\n throw new UnauthorizedError()\n }\n\n const sha256APIKeyIndex = crypto\n .createHmac('sha256', payload.secret)\n .update(apiKey || '')\n .digest('hex')\n\n const apiKeyConstraints = [\n {\n apiKeyIndex: {\n equals: sha256APIKeyIndex,\n },\n },\n ]\n\n const where: Where = {\n or: apiKeyConstraints,\n }\n\n const { docs } = await payload.find({\n collection: 'payload-mcp-api-keys',\n limit: 1,\n pagination: false,\n where,\n })\n\n if (docs.length === 0) {\n throw new UnauthorizedError()\n }\n\n if (useVerboseLogs) {\n payload.logger.info('[payload-mcp] API Key is valid')\n }\n\n return docs[0] as MCPAccessSettings\n }\n\n const mcpAccessSettings = pluginOptions.overrideAuth\n ? await pluginOptions.overrideAuth(req, getDefaultMcpAccessSettings)\n : await getDefaultMcpAccessSettings()\n\n const handler = getMCPHandler(pluginOptions, mcpAccessSettings, req)\n const request = createRequestFromPayloadRequest(req)\n return await handler(request)\n }\n return mcpHandler\n}\n"],"names":["crypto","UnauthorizedError","createRequestFromPayloadRequest","getMCPHandler","initializeMCPHandler","pluginOptions","mcpHandler","req","payload","MCPOptions","mcp","MCPHandlerOptions","handlerOptions","useVerboseLogs","verboseLogs","payloadAPI","getDefaultMcpAccessSettings","overrideApiKey","apiKey","headers","get","startsWith","replace","trim","sha256APIKeyIndex","createHmac","secret","update","digest","apiKeyConstraints","apiKeyIndex","equals","where","or","docs","find","collection","limit","pagination","length","logger","info","mcpAccessSettings","overrideAuth","handler","request"],"mappings":"AAAA,OAAOA,YAAY,SAAQ;AAC3B,SAA8BC,iBAAiB,QAAoB,UAAS;AAI5E,SAASC,+BAA+B,QAAQ,0BAAyB;AACzE,SAASC,aAAa,QAAQ,0BAAyB;AAEvD,OAAO,MAAMC,uBAAuB,CAACC;IACnC,MAAMC,aAA6B,OAAOC;QACxC,MAAM,EAAEC,OAAO,EAAE,GAAGD;QACpB,MAAME,aAAaJ,cAAcK,GAAG,IAAI,CAAC;QACzC,MAAMC,oBAAoBF,WAAWG,cAAc,IAAI,CAAC;QACxD,MAAMC,iBAAiBF,kBAAkBG,WAAW,IAAI;QAExDP,IAAIQ,UAAU,GAAG;QAEjB,MAAMC,8BAA8B,OAAOC;YACzC,MAAMC,SACJ,AAACD,kBAAkBV,IAAIY,OAAO,CAACC,GAAG,CAAC,kBAAkBC,WAAW,aAC5Dd,IAAIY,OAAO,CAACC,GAAG,CAAC,kBAAkBE,QAAQ,WAAW,IAAIC,SACzD;YAEN,IAAIL,WAAW,MAAM;gBACnB,MAAM,IAAIjB;YACZ;YAEA,MAAMuB,oBAAoBxB,OACvByB,UAAU,CAAC,UAAUjB,QAAQkB,MAAM,EACnCC,MAAM,CAACT,UAAU,IACjBU,MAAM,CAAC;YAEV,MAAMC,oBAAoB;gBACxB;oBACEC,aAAa;wBACXC,QAAQP;oBACV;gBACF;aACD;YAED,MAAMQ,QAAe;gBACnBC,IAAIJ;YACN;YAEA,MAAM,EAAEK,IAAI,EAAE,GAAG,MAAM1B,QAAQ2B,IAAI,CAAC;gBAClCC,YAAY;gBACZC,OAAO;gBACPC,YAAY;gBACZN;YACF;YAEA,IAAIE,KAAKK,MAAM,KAAK,GAAG;gBACrB,MAAM,IAAItC;YACZ;YAEA,IAAIY,gBAAgB;gBAClBL,QAAQgC,MAAM,CAACC,IAAI,CAAC;YACtB;YAEA,OAAOP,IAAI,CAAC,EAAE;QAChB;QAEA,MAAMQ,oBAAoBrC,cAAcsC,YAAY,GAChD,MAAMtC,cAAcsC,YAAY,CAACpC,KAAKS,+BACtC,MAAMA;QAEV,MAAM4B,UAAUzC,cAAcE,eAAeqC,mBAAmBnC;QAChE,MAAMsC,UAAU3C,gCAAgCK;QAChD,OAAO,MAAMqC,QAAQC;IACvB;IACA,OAAOvC;AACT,EAAC"}
|
|
1
|
+
{"version":3,"sources":["../../src/endpoints/mcp.ts"],"sourcesContent":["import crypto from 'crypto'\nimport { type PayloadHandler, UnauthorizedError, type Where } from 'payload'\n\nimport type { MCPAccessSettings, PluginMCPServerConfig } from '../types.js'\n\nimport { createRequestFromPayloadRequest } from '../mcp/createRequest.js'\nimport { getMCPHandler } from '../mcp/getMcpHandler.js'\n\nexport const initializeMCPHandler = (pluginOptions: PluginMCPServerConfig) => {\n const mcpHandler: PayloadHandler = async (req) => {\n const { payload } = req\n const MCPOptions = pluginOptions.mcp || {}\n const MCPHandlerOptions = MCPOptions.handlerOptions || {}\n const useVerboseLogs = MCPHandlerOptions.verboseLogs ?? false\n\n req.payloadAPI = 'MCP' as const\n\n const getDefaultMcpAccessSettings = async (overrideApiKey?: null | string) => {\n const apiKey =\n (overrideApiKey ?? req.headers.get('Authorization')?.startsWith('Bearer '))\n ? req.headers.get('Authorization')?.replace('Bearer ', '').trim()\n : null\n\n if (apiKey === null) {\n throw new UnauthorizedError()\n }\n\n const sha256APIKeyIndex = crypto\n .createHmac('sha256', payload.secret)\n .update(apiKey || '')\n .digest('hex')\n\n const apiKeyConstraints = [\n {\n apiKeyIndex: {\n equals: sha256APIKeyIndex,\n },\n },\n ]\n\n const where: Where = {\n or: apiKeyConstraints,\n }\n\n const { docs } = await payload.find({\n collection: 'payload-mcp-api-keys',\n limit: 1,\n pagination: false,\n where,\n })\n\n if (docs.length === 0) {\n throw new UnauthorizedError()\n }\n\n if (useVerboseLogs) {\n payload.logger.info('[payload-mcp] API Key is valid')\n }\n\n return docs[0] as unknown as MCPAccessSettings\n }\n\n const mcpAccessSettings = pluginOptions.overrideAuth\n ? await pluginOptions.overrideAuth(req, getDefaultMcpAccessSettings)\n : await getDefaultMcpAccessSettings()\n\n const handler = getMCPHandler(pluginOptions, mcpAccessSettings, req)\n const request = createRequestFromPayloadRequest(req)\n return await handler(request)\n }\n return mcpHandler\n}\n"],"names":["crypto","UnauthorizedError","createRequestFromPayloadRequest","getMCPHandler","initializeMCPHandler","pluginOptions","mcpHandler","req","payload","MCPOptions","mcp","MCPHandlerOptions","handlerOptions","useVerboseLogs","verboseLogs","payloadAPI","getDefaultMcpAccessSettings","overrideApiKey","apiKey","headers","get","startsWith","replace","trim","sha256APIKeyIndex","createHmac","secret","update","digest","apiKeyConstraints","apiKeyIndex","equals","where","or","docs","find","collection","limit","pagination","length","logger","info","mcpAccessSettings","overrideAuth","handler","request"],"mappings":"AAAA,OAAOA,YAAY,SAAQ;AAC3B,SAA8BC,iBAAiB,QAAoB,UAAS;AAI5E,SAASC,+BAA+B,QAAQ,0BAAyB;AACzE,SAASC,aAAa,QAAQ,0BAAyB;AAEvD,OAAO,MAAMC,uBAAuB,CAACC;IACnC,MAAMC,aAA6B,OAAOC;QACxC,MAAM,EAAEC,OAAO,EAAE,GAAGD;QACpB,MAAME,aAAaJ,cAAcK,GAAG,IAAI,CAAC;QACzC,MAAMC,oBAAoBF,WAAWG,cAAc,IAAI,CAAC;QACxD,MAAMC,iBAAiBF,kBAAkBG,WAAW,IAAI;QAExDP,IAAIQ,UAAU,GAAG;QAEjB,MAAMC,8BAA8B,OAAOC;YACzC,MAAMC,SACJ,AAACD,kBAAkBV,IAAIY,OAAO,CAACC,GAAG,CAAC,kBAAkBC,WAAW,aAC5Dd,IAAIY,OAAO,CAACC,GAAG,CAAC,kBAAkBE,QAAQ,WAAW,IAAIC,SACzD;YAEN,IAAIL,WAAW,MAAM;gBACnB,MAAM,IAAIjB;YACZ;YAEA,MAAMuB,oBAAoBxB,OACvByB,UAAU,CAAC,UAAUjB,QAAQkB,MAAM,EACnCC,MAAM,CAACT,UAAU,IACjBU,MAAM,CAAC;YAEV,MAAMC,oBAAoB;gBACxB;oBACEC,aAAa;wBACXC,QAAQP;oBACV;gBACF;aACD;YAED,MAAMQ,QAAe;gBACnBC,IAAIJ;YACN;YAEA,MAAM,EAAEK,IAAI,EAAE,GAAG,MAAM1B,QAAQ2B,IAAI,CAAC;gBAClCC,YAAY;gBACZC,OAAO;gBACPC,YAAY;gBACZN;YACF;YAEA,IAAIE,KAAKK,MAAM,KAAK,GAAG;gBACrB,MAAM,IAAItC;YACZ;YAEA,IAAIY,gBAAgB;gBAClBL,QAAQgC,MAAM,CAACC,IAAI,CAAC;YACtB;YAEA,OAAOP,IAAI,CAAC,EAAE;QAChB;QAEA,MAAMQ,oBAAoBrC,cAAcsC,YAAY,GAChD,MAAMtC,cAAcsC,YAAY,CAACpC,KAAKS,+BACtC,MAAMA;QAEV,MAAM4B,UAAUzC,cAAcE,eAAeqC,mBAAmBnC;QAChE,MAAMsC,UAAU3C,gCAAgCK;QAChD,OAAO,MAAMqC,QAAQC;IACvB;IACA,OAAOvC;AACT,EAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getMcpHandler.d.ts","sourceRoot":"","sources":["../../src/mcp/getMcpHandler.ts"],"names":[],"mappings":"AAIA,OAAO,EAAgC,KAAK,cAAc,EAAkB,MAAM,SAAS,CAAA;AAE3F,OAAO,KAAK,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAA;AA+B3E,eAAO,MAAM,aAAa,kBACT,qBAAqB,qBACjB,iBAAiB,OAC/B,cAAc,
|
|
1
|
+
{"version":3,"file":"getMcpHandler.d.ts","sourceRoot":"","sources":["../../src/mcp/getMcpHandler.ts"],"names":[],"mappings":"AAIA,OAAO,EAAgC,KAAK,cAAc,EAAkB,MAAM,SAAS,CAAA;AAE3F,OAAO,KAAK,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAA;AA+B3E,eAAO,MAAM,aAAa,kBACT,qBAAqB,qBACjB,iBAAiB,OAC/B,cAAc,4CA0bpB,CAAA"}
|
|
@@ -29,6 +29,17 @@ import { updateJobTool } from './tools/job/update.js';
|
|
|
29
29
|
export const getMCPHandler = (pluginOptions, mcpAccessSettings, req)=>{
|
|
30
30
|
const { payload } = req;
|
|
31
31
|
const configSchema = configToJSONSchema(payload.config);
|
|
32
|
+
// Handler wrapper that injects req before the _extra argument
|
|
33
|
+
const wrapHandler = (handler)=>{
|
|
34
|
+
return async (...args)=>{
|
|
35
|
+
const _extra = args[args.length - 1];
|
|
36
|
+
const handlerArgs = args.slice(0, -1);
|
|
37
|
+
return await handler(...handlerArgs, req, _extra);
|
|
38
|
+
};
|
|
39
|
+
};
|
|
40
|
+
const payloadToolHandler = (handler)=>wrapHandler(handler);
|
|
41
|
+
const payloadPromptHandler = (handler)=>wrapHandler(handler);
|
|
42
|
+
const payloadResourceHandler = (handler)=>wrapHandler(handler);
|
|
32
43
|
// User
|
|
33
44
|
const user = mcpAccessSettings.user;
|
|
34
45
|
// MCP Server and Handler Options
|
|
@@ -87,7 +98,7 @@ export const getMCPHandler = (pluginOptions, mcpAccessSettings, req)=>{
|
|
|
87
98
|
customMCPTools.forEach((tool)=>{
|
|
88
99
|
const camelCasedToolName = toCamelCase(tool.name);
|
|
89
100
|
const isToolEnabled = mcpAccessSettings['payload-mcp-tool']?.[camelCasedToolName] ?? false;
|
|
90
|
-
registerTool(isToolEnabled, tool.name, ()=>server.tool(tool.name, tool.description, tool.parameters, tool.handler), payload, useVerboseLogs);
|
|
101
|
+
registerTool(isToolEnabled, tool.name, ()=>server.tool(tool.name, tool.description, tool.parameters, payloadToolHandler(tool.handler)), payload, useVerboseLogs);
|
|
91
102
|
});
|
|
92
103
|
// Custom prompts
|
|
93
104
|
customMCPPrompts.forEach((prompt)=>{
|
|
@@ -98,7 +109,7 @@ export const getMCPHandler = (pluginOptions, mcpAccessSettings, req)=>{
|
|
|
98
109
|
argsSchema: prompt.argsSchema,
|
|
99
110
|
description: prompt.description,
|
|
100
111
|
title: prompt.title
|
|
101
|
-
}, prompt.handler);
|
|
112
|
+
}, payloadPromptHandler(prompt.handler));
|
|
102
113
|
if (useVerboseLogs) {
|
|
103
114
|
payload.logger.info(`[payload-mcp] ✅ Prompt: ${prompt.title} Registered.`);
|
|
104
115
|
}
|
|
@@ -116,7 +127,7 @@ export const getMCPHandler = (pluginOptions, mcpAccessSettings, req)=>{
|
|
|
116
127
|
description: resource.description,
|
|
117
128
|
mimeType: resource.mimeType,
|
|
118
129
|
title: resource.title
|
|
119
|
-
}, resource.handler);
|
|
130
|
+
}, payloadResourceHandler(resource.handler));
|
|
120
131
|
if (useVerboseLogs) {
|
|
121
132
|
payload.logger.info(`[payload-mcp] ✅ Resource: ${resource.title} Registered.`);
|
|
122
133
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/mcp/getMcpHandler.ts"],"sourcesContent":["import type { JSONSchema4 } from 'json-schema'\n\nimport { createMcpHandler } from '@vercel/mcp-adapter'\nimport { join } from 'path'\nimport { APIError, configToJSONSchema, type PayloadRequest, type TypedUser } from 'payload'\n\nimport type { MCPAccessSettings, PluginMCPServerConfig } from '../types.js'\n\nimport { toCamelCase } from '../utils/camelCase.js'\nimport { registerTool } from './registerTool.js'\n\n// Tools\nimport { createResourceTool } from './tools/resource/create.js'\nimport { deleteResourceTool } from './tools/resource/delete.js'\nimport { findResourceTool } from './tools/resource/find.js'\nimport { updateResourceTool } from './tools/resource/update.js'\n\n// Experimental Tools\n/**\n * @experimental This tools are experimental and may change or be removed in the future.\n */\nimport { authTool } from './tools/auth/auth.js'\nimport { forgotPasswordTool } from './tools/auth/forgotPassword.js'\nimport { loginTool } from './tools/auth/login.js'\nimport { resetPasswordTool } from './tools/auth/resetPassword.js'\nimport { unlockTool } from './tools/auth/unlock.js'\nimport { verifyTool } from './tools/auth/verify.js'\nimport { createCollectionTool } from './tools/collection/create.js'\nimport { deleteCollectionTool } from './tools/collection/delete.js'\nimport { findCollectionTool } from './tools/collection/find.js'\nimport { updateCollectionTool } from './tools/collection/update.js'\nimport { findConfigTool } from './tools/config/find.js'\nimport { updateConfigTool } from './tools/config/update.js'\nimport { createJobTool } from './tools/job/create.js'\nimport { runJobTool } from './tools/job/run.js'\nimport { updateJobTool } from './tools/job/update.js'\n\nexport const getMCPHandler = (\n pluginOptions: PluginMCPServerConfig,\n mcpAccessSettings: MCPAccessSettings,\n req: PayloadRequest,\n) => {\n const { payload } = req\n const configSchema = configToJSONSchema(payload.config)\n\n // User\n const user = mcpAccessSettings.user as TypedUser\n\n // MCP Server and Handler Options\n const MCPOptions = pluginOptions.mcp || {}\n const customMCPTools = MCPOptions.tools || []\n const customMCPPrompts = MCPOptions.prompts || []\n const customMCPResources = MCPOptions.resources || []\n const MCPHandlerOptions = MCPOptions.handlerOptions || {}\n const serverOptions = MCPOptions.serverOptions || {}\n const useVerboseLogs = MCPHandlerOptions.verboseLogs ?? false\n\n // Experimental MCP Tool Requirements\n const isDevelopment = process.env.NODE_ENV === 'development'\n const experimentalTools: NonNullable<PluginMCPServerConfig['experimental']>['tools'] =\n pluginOptions?.experimental?.tools || {}\n const collectionsPluginConfig = pluginOptions.collections || {}\n const collectionsDirPath =\n experimentalTools && experimentalTools.collections?.collectionsDirPath\n ? experimentalTools.collections.collectionsDirPath\n : join(process.cwd(), 'src/collections')\n const configFilePath =\n experimentalTools && experimentalTools.config?.configFilePath\n ? experimentalTools.config.configFilePath\n : join(process.cwd(), 'src/payload.config.ts')\n const jobsDirPath =\n experimentalTools && experimentalTools.jobs?.jobsDirPath\n ? experimentalTools.jobs.jobsDirPath\n : join(process.cwd(), 'src/jobs')\n\n try {\n return createMcpHandler(\n (server) => {\n const enabledCollectionSlugs = Object.keys(collectionsPluginConfig || {}).filter(\n (collection) => {\n const fullyEnabled =\n typeof collectionsPluginConfig?.[collection]?.enabled === 'boolean' &&\n collectionsPluginConfig?.[collection]?.enabled\n\n if (fullyEnabled) {\n return true\n }\n\n const partiallyEnabled =\n typeof collectionsPluginConfig?.[collection]?.enabled !== 'boolean' &&\n ((typeof collectionsPluginConfig?.[collection]?.enabled?.find === 'boolean' &&\n collectionsPluginConfig?.[collection]?.enabled?.find === true) ||\n (typeof collectionsPluginConfig?.[collection]?.enabled?.create === 'boolean' &&\n collectionsPluginConfig?.[collection]?.enabled?.create === true) ||\n (typeof collectionsPluginConfig?.[collection]?.enabled?.update === 'boolean' &&\n collectionsPluginConfig?.[collection]?.enabled?.update === true) ||\n (typeof collectionsPluginConfig?.[collection]?.enabled?.delete === 'boolean' &&\n collectionsPluginConfig?.[collection]?.enabled?.delete === true))\n\n if (partiallyEnabled) {\n return true\n }\n },\n )\n\n // Collection Operation Tools\n enabledCollectionSlugs.forEach((enabledCollectionSlug) => {\n try {\n const schema = configSchema.definitions?.[enabledCollectionSlug] as JSONSchema4\n\n const toolCapabilities = mcpAccessSettings?.[\n `${toCamelCase(enabledCollectionSlug)}`\n ] as Record<string, unknown>\n const allowCreate: boolean | undefined = toolCapabilities?.create as boolean\n const allowUpdate: boolean | undefined = toolCapabilities?.update as boolean\n const allowFind: boolean | undefined = toolCapabilities?.find as boolean\n const allowDelete: boolean | undefined = toolCapabilities?.delete as boolean\n\n if (allowCreate) {\n registerTool(\n allowCreate,\n `Create ${enabledCollectionSlug}`,\n () =>\n createResourceTool(\n server,\n req,\n user,\n useVerboseLogs,\n enabledCollectionSlug,\n collectionsPluginConfig,\n schema,\n ),\n payload,\n useVerboseLogs,\n )\n }\n if (allowUpdate) {\n registerTool(\n allowUpdate,\n `Update ${enabledCollectionSlug}`,\n () =>\n updateResourceTool(\n server,\n req,\n user,\n useVerboseLogs,\n enabledCollectionSlug,\n collectionsPluginConfig,\n schema,\n ),\n payload,\n useVerboseLogs,\n )\n }\n if (allowFind) {\n registerTool(\n allowFind,\n `Find ${enabledCollectionSlug}`,\n () =>\n findResourceTool(\n server,\n req,\n user,\n useVerboseLogs,\n enabledCollectionSlug,\n collectionsPluginConfig,\n ),\n payload,\n useVerboseLogs,\n )\n }\n if (allowDelete) {\n registerTool(\n allowDelete,\n `Delete ${enabledCollectionSlug}`,\n () =>\n deleteResourceTool(\n server,\n req,\n user,\n useVerboseLogs,\n enabledCollectionSlug,\n collectionsPluginConfig,\n ),\n payload,\n useVerboseLogs,\n )\n }\n } catch (error) {\n throw new APIError(\n `Error registering tools for collection ${enabledCollectionSlug}: ${String(error)}`,\n 500,\n )\n }\n })\n\n // Custom tools\n customMCPTools.forEach((tool) => {\n const camelCasedToolName = toCamelCase(tool.name)\n const isToolEnabled = mcpAccessSettings['payload-mcp-tool']?.[camelCasedToolName] ?? false\n\n registerTool(\n isToolEnabled,\n tool.name,\n () => server.tool(tool.name, tool.description, tool.parameters, tool.handler),\n payload,\n useVerboseLogs,\n )\n })\n\n // Custom prompts\n customMCPPrompts.forEach((prompt) => {\n const camelCasedPromptName = toCamelCase(prompt.name)\n const isPromptEnabled =\n mcpAccessSettings['payload-mcp-prompt']?.[camelCasedPromptName] ?? false\n\n if (isPromptEnabled) {\n server.registerPrompt(\n prompt.name,\n {\n argsSchema: prompt.argsSchema,\n description: prompt.description,\n title: prompt.title,\n },\n prompt.handler,\n )\n if (useVerboseLogs) {\n payload.logger.info(`[payload-mcp] ✅ Prompt: ${prompt.title} Registered.`)\n }\n } else if (useVerboseLogs) {\n payload.logger.info(`[payload-mcp] ⏭️ Prompt: ${prompt.title} Skipped.`)\n }\n })\n\n // Custom resources\n customMCPResources.forEach((resource) => {\n const camelCasedResourceName = toCamelCase(resource.name)\n const isResourceEnabled =\n mcpAccessSettings['payload-mcp-resource']?.[camelCasedResourceName] ?? false\n\n if (isResourceEnabled) {\n server.registerResource(\n resource.name,\n // @ts-expect-error - Overload type is not working however -- ResourceTemplate OR String is a valid type\n resource.uri,\n {\n description: resource.description,\n mimeType: resource.mimeType,\n title: resource.title,\n },\n resource.handler,\n )\n\n if (useVerboseLogs) {\n payload.logger.info(`[payload-mcp] ✅ Resource: ${resource.title} Registered.`)\n }\n } else if (useVerboseLogs) {\n payload.logger.info(`[payload-mcp] ⏭️ Resource: ${resource.title} Skipped.`)\n }\n })\n\n // Experimental - Collection Schema Modfication Tools\n if (\n mcpAccessSettings.collections?.create &&\n experimentalTools.collections?.enabled &&\n isDevelopment\n ) {\n registerTool(\n mcpAccessSettings.collections.create,\n 'Create Collection',\n () =>\n createCollectionTool(server, req, useVerboseLogs, collectionsDirPath, configFilePath),\n payload,\n useVerboseLogs,\n )\n }\n if (\n mcpAccessSettings.collections?.delete &&\n experimentalTools.collections?.enabled &&\n isDevelopment\n ) {\n registerTool(\n mcpAccessSettings.collections.delete,\n 'Delete Collection',\n () =>\n deleteCollectionTool(server, req, useVerboseLogs, collectionsDirPath, configFilePath),\n payload,\n useVerboseLogs,\n )\n }\n\n if (\n mcpAccessSettings.collections?.find &&\n experimentalTools.collections?.enabled &&\n isDevelopment\n ) {\n registerTool(\n mcpAccessSettings.collections.find,\n 'Find Collection',\n () => findCollectionTool(server, req, useVerboseLogs, collectionsDirPath),\n payload,\n useVerboseLogs,\n )\n }\n\n if (\n mcpAccessSettings.collections?.update &&\n experimentalTools.collections?.enabled &&\n isDevelopment\n ) {\n registerTool(\n mcpAccessSettings.collections.update,\n 'Update Collection',\n () =>\n updateCollectionTool(server, req, useVerboseLogs, collectionsDirPath, configFilePath),\n payload,\n useVerboseLogs,\n )\n }\n\n // Experimental - Payload Config Modification Tools\n if (mcpAccessSettings.config?.find && experimentalTools.config?.enabled && isDevelopment) {\n registerTool(\n mcpAccessSettings.config.find,\n 'Find Config',\n () => findConfigTool(server, req, useVerboseLogs, configFilePath),\n payload,\n useVerboseLogs,\n )\n }\n\n if (\n mcpAccessSettings.config?.update &&\n experimentalTools.config?.enabled &&\n isDevelopment\n ) {\n registerTool(\n mcpAccessSettings.config.update,\n 'Update Config',\n () => updateConfigTool(server, req, useVerboseLogs, configFilePath),\n payload,\n useVerboseLogs,\n )\n }\n\n // Experimental - Job Modification Tools\n if (mcpAccessSettings.jobs?.create && experimentalTools.jobs?.enabled && isDevelopment) {\n registerTool(\n mcpAccessSettings.jobs.create,\n 'Create Job',\n () => createJobTool(server, req, useVerboseLogs, jobsDirPath),\n payload,\n useVerboseLogs,\n )\n }\n\n if (mcpAccessSettings.jobs?.update && experimentalTools.jobs?.enabled && isDevelopment) {\n registerTool(\n mcpAccessSettings.jobs.update,\n 'Update Job',\n () => updateJobTool(server, req, useVerboseLogs, jobsDirPath),\n payload,\n useVerboseLogs,\n )\n }\n\n if (mcpAccessSettings.jobs?.run && experimentalTools.jobs?.enabled && isDevelopment) {\n registerTool(\n mcpAccessSettings.jobs.run,\n 'Run Job',\n () => runJobTool(server, req, useVerboseLogs),\n payload,\n useVerboseLogs,\n )\n }\n\n // Experimental - Auth Modification Tools\n if (mcpAccessSettings.auth?.auth && experimentalTools.auth?.enabled && isDevelopment) {\n registerTool(\n mcpAccessSettings.auth.auth,\n 'Auth',\n () => authTool(server, req, useVerboseLogs),\n payload,\n useVerboseLogs,\n )\n }\n\n if (mcpAccessSettings.auth?.login && experimentalTools.auth?.enabled && isDevelopment) {\n registerTool(\n mcpAccessSettings.auth.login,\n 'Login',\n () => loginTool(server, req, useVerboseLogs),\n payload,\n useVerboseLogs,\n )\n }\n\n if (mcpAccessSettings.auth?.verify && experimentalTools.auth?.enabled && isDevelopment) {\n registerTool(\n mcpAccessSettings.auth.verify,\n 'Verify',\n () => verifyTool(server, req, useVerboseLogs),\n payload,\n useVerboseLogs,\n )\n }\n\n if (mcpAccessSettings.auth?.resetPassword && experimentalTools.auth?.enabled) {\n registerTool(\n mcpAccessSettings.auth.resetPassword,\n 'Reset Password',\n () => resetPasswordTool(server, req, useVerboseLogs),\n payload,\n useVerboseLogs,\n )\n }\n\n if (mcpAccessSettings.auth?.forgotPassword && experimentalTools.auth?.enabled) {\n registerTool(\n mcpAccessSettings.auth.forgotPassword,\n 'Forgot Password',\n () => forgotPasswordTool(server, req, useVerboseLogs),\n payload,\n useVerboseLogs,\n )\n }\n\n if (mcpAccessSettings.auth?.unlock && experimentalTools.auth?.enabled) {\n registerTool(\n mcpAccessSettings.auth.unlock,\n 'Unlock',\n () => unlockTool(server, req, useVerboseLogs),\n payload,\n useVerboseLogs,\n )\n }\n\n if (useVerboseLogs) {\n payload.logger.info('[payload-mcp] 🚀 MCP Server Ready.')\n }\n },\n {\n serverInfo: serverOptions.serverInfo,\n },\n {\n basePath: MCPHandlerOptions.basePath || '/api',\n maxDuration: MCPHandlerOptions.maxDuration || 60,\n // INFO: Disabled until developer clarity is reached for server side streaming and we have an auth pattern for all SSE patterns\n // redisUrl: MCPHandlerOptions.redisUrl || process.env.REDIS_URL,\n verboseLogs: useVerboseLogs,\n },\n )\n } catch (error) {\n throw new APIError(`Error initializing MCP handler: ${String(error)}`, 500)\n }\n}\n"],"names":["createMcpHandler","join","APIError","configToJSONSchema","toCamelCase","registerTool","createResourceTool","deleteResourceTool","findResourceTool","updateResourceTool","authTool","forgotPasswordTool","loginTool","resetPasswordTool","unlockTool","verifyTool","createCollectionTool","deleteCollectionTool","findCollectionTool","updateCollectionTool","findConfigTool","updateConfigTool","createJobTool","runJobTool","updateJobTool","getMCPHandler","pluginOptions","mcpAccessSettings","req","payload","configSchema","config","user","MCPOptions","mcp","customMCPTools","tools","customMCPPrompts","prompts","customMCPResources","resources","MCPHandlerOptions","handlerOptions","serverOptions","useVerboseLogs","verboseLogs","isDevelopment","process","env","NODE_ENV","experimentalTools","experimental","collectionsPluginConfig","collections","collectionsDirPath","cwd","configFilePath","jobsDirPath","jobs","server","enabledCollectionSlugs","Object","keys","filter","collection","fullyEnabled","enabled","partiallyEnabled","find","create","update","delete","forEach","enabledCollectionSlug","schema","definitions","toolCapabilities","allowCreate","allowUpdate","allowFind","allowDelete","error","String","tool","camelCasedToolName","name","isToolEnabled","description","parameters","handler","prompt","camelCasedPromptName","isPromptEnabled","registerPrompt","argsSchema","title","logger","info","resource","camelCasedResourceName","isResourceEnabled","registerResource","uri","mimeType","run","auth","login","verify","resetPassword","forgotPassword","unlock","serverInfo","basePath","maxDuration"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../src/mcp/getMcpHandler.ts"],"sourcesContent":["import type { JSONSchema4 } from 'json-schema'\n\nimport { createMcpHandler } from '@vercel/mcp-adapter'\nimport { join } from 'path'\nimport { APIError, configToJSONSchema, type PayloadRequest, type TypedUser } from 'payload'\n\nimport type { MCPAccessSettings, PluginMCPServerConfig } from '../types.js'\n\nimport { toCamelCase } from '../utils/camelCase.js'\nimport { registerTool } from './registerTool.js'\n\n// Tools\nimport { createResourceTool } from './tools/resource/create.js'\nimport { deleteResourceTool } from './tools/resource/delete.js'\nimport { findResourceTool } from './tools/resource/find.js'\nimport { updateResourceTool } from './tools/resource/update.js'\n\n// Experimental Tools\n/**\n * @experimental This tools are experimental and may change or be removed in the future.\n */\nimport { authTool } from './tools/auth/auth.js'\nimport { forgotPasswordTool } from './tools/auth/forgotPassword.js'\nimport { loginTool } from './tools/auth/login.js'\nimport { resetPasswordTool } from './tools/auth/resetPassword.js'\nimport { unlockTool } from './tools/auth/unlock.js'\nimport { verifyTool } from './tools/auth/verify.js'\nimport { createCollectionTool } from './tools/collection/create.js'\nimport { deleteCollectionTool } from './tools/collection/delete.js'\nimport { findCollectionTool } from './tools/collection/find.js'\nimport { updateCollectionTool } from './tools/collection/update.js'\nimport { findConfigTool } from './tools/config/find.js'\nimport { updateConfigTool } from './tools/config/update.js'\nimport { createJobTool } from './tools/job/create.js'\nimport { runJobTool } from './tools/job/run.js'\nimport { updateJobTool } from './tools/job/update.js'\n\nexport const getMCPHandler = (\n pluginOptions: PluginMCPServerConfig,\n mcpAccessSettings: MCPAccessSettings,\n req: PayloadRequest,\n) => {\n const { payload } = req\n const configSchema = configToJSONSchema(payload.config)\n\n // Handler wrapper that injects req before the _extra argument\n const wrapHandler = (handler: (...args: any[]) => any) => {\n return async (...args: any[]) => {\n const _extra = args[args.length - 1]\n const handlerArgs = args.slice(0, -1)\n return await handler(...handlerArgs, req, _extra)\n }\n }\n\n const payloadToolHandler = (\n handler: NonNullable<NonNullable<PluginMCPServerConfig['mcp']>['tools']>[number]['handler'],\n ) => wrapHandler(handler)\n\n const payloadPromptHandler = (\n handler: NonNullable<NonNullable<PluginMCPServerConfig['mcp']>['prompts']>[number]['handler'],\n ) => wrapHandler(handler)\n\n const payloadResourceHandler = (\n handler: NonNullable<NonNullable<PluginMCPServerConfig['mcp']>['resources']>[number]['handler'],\n ) => wrapHandler(handler)\n\n // User\n const user = mcpAccessSettings.user\n\n // MCP Server and Handler Options\n const MCPOptions = pluginOptions.mcp || {}\n const customMCPTools = MCPOptions.tools || []\n const customMCPPrompts = MCPOptions.prompts || []\n const customMCPResources = MCPOptions.resources || []\n const MCPHandlerOptions = MCPOptions.handlerOptions || {}\n const serverOptions = MCPOptions.serverOptions || {}\n const useVerboseLogs = MCPHandlerOptions.verboseLogs ?? false\n\n // Experimental MCP Tool Requirements\n const isDevelopment = process.env.NODE_ENV === 'development'\n const experimentalTools: NonNullable<PluginMCPServerConfig['experimental']>['tools'] =\n pluginOptions?.experimental?.tools || {}\n const collectionsPluginConfig = pluginOptions.collections || {}\n const collectionsDirPath =\n experimentalTools && experimentalTools.collections?.collectionsDirPath\n ? experimentalTools.collections.collectionsDirPath\n : join(process.cwd(), 'src/collections')\n const configFilePath =\n experimentalTools && experimentalTools.config?.configFilePath\n ? experimentalTools.config.configFilePath\n : join(process.cwd(), 'src/payload.config.ts')\n const jobsDirPath =\n experimentalTools && experimentalTools.jobs?.jobsDirPath\n ? experimentalTools.jobs.jobsDirPath\n : join(process.cwd(), 'src/jobs')\n\n try {\n return createMcpHandler(\n (server) => {\n const enabledCollectionSlugs = Object.keys(collectionsPluginConfig || {}).filter(\n (collection) => {\n const fullyEnabled =\n typeof collectionsPluginConfig?.[collection]?.enabled === 'boolean' &&\n collectionsPluginConfig?.[collection]?.enabled\n\n if (fullyEnabled) {\n return true\n }\n\n const partiallyEnabled =\n typeof collectionsPluginConfig?.[collection]?.enabled !== 'boolean' &&\n ((typeof collectionsPluginConfig?.[collection]?.enabled?.find === 'boolean' &&\n collectionsPluginConfig?.[collection]?.enabled?.find === true) ||\n (typeof collectionsPluginConfig?.[collection]?.enabled?.create === 'boolean' &&\n collectionsPluginConfig?.[collection]?.enabled?.create === true) ||\n (typeof collectionsPluginConfig?.[collection]?.enabled?.update === 'boolean' &&\n collectionsPluginConfig?.[collection]?.enabled?.update === true) ||\n (typeof collectionsPluginConfig?.[collection]?.enabled?.delete === 'boolean' &&\n collectionsPluginConfig?.[collection]?.enabled?.delete === true))\n\n if (partiallyEnabled) {\n return true\n }\n },\n )\n\n // Collection Operation Tools\n enabledCollectionSlugs.forEach((enabledCollectionSlug) => {\n try {\n const schema = configSchema.definitions?.[enabledCollectionSlug] as JSONSchema4\n\n const toolCapabilities = mcpAccessSettings?.[\n `${toCamelCase(enabledCollectionSlug)}`\n ] as Record<string, unknown>\n const allowCreate: boolean | undefined = toolCapabilities?.create as boolean\n const allowUpdate: boolean | undefined = toolCapabilities?.update as boolean\n const allowFind: boolean | undefined = toolCapabilities?.find as boolean\n const allowDelete: boolean | undefined = toolCapabilities?.delete as boolean\n\n if (allowCreate) {\n registerTool(\n allowCreate,\n `Create ${enabledCollectionSlug}`,\n () =>\n createResourceTool(\n server,\n req,\n user,\n useVerboseLogs,\n enabledCollectionSlug,\n collectionsPluginConfig,\n schema,\n ),\n payload,\n useVerboseLogs,\n )\n }\n if (allowUpdate) {\n registerTool(\n allowUpdate,\n `Update ${enabledCollectionSlug}`,\n () =>\n updateResourceTool(\n server,\n req,\n user,\n useVerboseLogs,\n enabledCollectionSlug,\n collectionsPluginConfig,\n schema,\n ),\n payload,\n useVerboseLogs,\n )\n }\n if (allowFind) {\n registerTool(\n allowFind,\n `Find ${enabledCollectionSlug}`,\n () =>\n findResourceTool(\n server,\n req,\n user,\n useVerboseLogs,\n enabledCollectionSlug,\n collectionsPluginConfig,\n ),\n payload,\n useVerboseLogs,\n )\n }\n if (allowDelete) {\n registerTool(\n allowDelete,\n `Delete ${enabledCollectionSlug}`,\n () =>\n deleteResourceTool(\n server,\n req,\n user,\n useVerboseLogs,\n enabledCollectionSlug,\n collectionsPluginConfig,\n ),\n payload,\n useVerboseLogs,\n )\n }\n } catch (error) {\n throw new APIError(\n `Error registering tools for collection ${enabledCollectionSlug}: ${String(error)}`,\n 500,\n )\n }\n })\n\n // Custom tools\n customMCPTools.forEach((tool) => {\n const camelCasedToolName = toCamelCase(tool.name)\n const isToolEnabled = mcpAccessSettings['payload-mcp-tool']?.[camelCasedToolName] ?? false\n\n registerTool(\n isToolEnabled,\n tool.name,\n () =>\n server.tool(\n tool.name,\n tool.description,\n tool.parameters,\n payloadToolHandler(tool.handler),\n ),\n payload,\n useVerboseLogs,\n )\n })\n\n // Custom prompts\n customMCPPrompts.forEach((prompt) => {\n const camelCasedPromptName = toCamelCase(prompt.name)\n const isPromptEnabled =\n mcpAccessSettings['payload-mcp-prompt']?.[camelCasedPromptName] ?? false\n\n if (isPromptEnabled) {\n server.registerPrompt(\n prompt.name,\n {\n argsSchema: prompt.argsSchema,\n description: prompt.description,\n title: prompt.title,\n },\n payloadPromptHandler(prompt.handler),\n )\n if (useVerboseLogs) {\n payload.logger.info(`[payload-mcp] ✅ Prompt: ${prompt.title} Registered.`)\n }\n } else if (useVerboseLogs) {\n payload.logger.info(`[payload-mcp] ⏭️ Prompt: ${prompt.title} Skipped.`)\n }\n })\n\n // Custom resources\n customMCPResources.forEach((resource) => {\n const camelCasedResourceName = toCamelCase(resource.name)\n const isResourceEnabled =\n mcpAccessSettings['payload-mcp-resource']?.[camelCasedResourceName] ?? false\n\n if (isResourceEnabled) {\n server.registerResource(\n resource.name,\n // @ts-expect-error - Overload type is not working however -- ResourceTemplate OR String is a valid type\n resource.uri,\n {\n description: resource.description,\n mimeType: resource.mimeType,\n title: resource.title,\n },\n payloadResourceHandler(resource.handler),\n )\n\n if (useVerboseLogs) {\n payload.logger.info(`[payload-mcp] ✅ Resource: ${resource.title} Registered.`)\n }\n } else if (useVerboseLogs) {\n payload.logger.info(`[payload-mcp] ⏭️ Resource: ${resource.title} Skipped.`)\n }\n })\n\n // Experimental - Collection Schema Modfication Tools\n if (\n mcpAccessSettings.collections?.create &&\n experimentalTools.collections?.enabled &&\n isDevelopment\n ) {\n registerTool(\n mcpAccessSettings.collections.create,\n 'Create Collection',\n () =>\n createCollectionTool(server, req, useVerboseLogs, collectionsDirPath, configFilePath),\n payload,\n useVerboseLogs,\n )\n }\n if (\n mcpAccessSettings.collections?.delete &&\n experimentalTools.collections?.enabled &&\n isDevelopment\n ) {\n registerTool(\n mcpAccessSettings.collections.delete,\n 'Delete Collection',\n () =>\n deleteCollectionTool(server, req, useVerboseLogs, collectionsDirPath, configFilePath),\n payload,\n useVerboseLogs,\n )\n }\n\n if (\n mcpAccessSettings.collections?.find &&\n experimentalTools.collections?.enabled &&\n isDevelopment\n ) {\n registerTool(\n mcpAccessSettings.collections.find,\n 'Find Collection',\n () => findCollectionTool(server, req, useVerboseLogs, collectionsDirPath),\n payload,\n useVerboseLogs,\n )\n }\n\n if (\n mcpAccessSettings.collections?.update &&\n experimentalTools.collections?.enabled &&\n isDevelopment\n ) {\n registerTool(\n mcpAccessSettings.collections.update,\n 'Update Collection',\n () =>\n updateCollectionTool(server, req, useVerboseLogs, collectionsDirPath, configFilePath),\n payload,\n useVerboseLogs,\n )\n }\n\n // Experimental - Payload Config Modification Tools\n if (mcpAccessSettings.config?.find && experimentalTools.config?.enabled && isDevelopment) {\n registerTool(\n mcpAccessSettings.config.find,\n 'Find Config',\n () => findConfigTool(server, req, useVerboseLogs, configFilePath),\n payload,\n useVerboseLogs,\n )\n }\n\n if (\n mcpAccessSettings.config?.update &&\n experimentalTools.config?.enabled &&\n isDevelopment\n ) {\n registerTool(\n mcpAccessSettings.config.update,\n 'Update Config',\n () => updateConfigTool(server, req, useVerboseLogs, configFilePath),\n payload,\n useVerboseLogs,\n )\n }\n\n // Experimental - Job Modification Tools\n if (mcpAccessSettings.jobs?.create && experimentalTools.jobs?.enabled && isDevelopment) {\n registerTool(\n mcpAccessSettings.jobs.create,\n 'Create Job',\n () => createJobTool(server, req, useVerboseLogs, jobsDirPath),\n payload,\n useVerboseLogs,\n )\n }\n\n if (mcpAccessSettings.jobs?.update && experimentalTools.jobs?.enabled && isDevelopment) {\n registerTool(\n mcpAccessSettings.jobs.update,\n 'Update Job',\n () => updateJobTool(server, req, useVerboseLogs, jobsDirPath),\n payload,\n useVerboseLogs,\n )\n }\n\n if (mcpAccessSettings.jobs?.run && experimentalTools.jobs?.enabled && isDevelopment) {\n registerTool(\n mcpAccessSettings.jobs.run,\n 'Run Job',\n () => runJobTool(server, req, useVerboseLogs),\n payload,\n useVerboseLogs,\n )\n }\n\n // Experimental - Auth Modification Tools\n if (mcpAccessSettings.auth?.auth && experimentalTools.auth?.enabled && isDevelopment) {\n registerTool(\n mcpAccessSettings.auth.auth,\n 'Auth',\n () => authTool(server, req, useVerboseLogs),\n payload,\n useVerboseLogs,\n )\n }\n\n if (mcpAccessSettings.auth?.login && experimentalTools.auth?.enabled && isDevelopment) {\n registerTool(\n mcpAccessSettings.auth.login,\n 'Login',\n () => loginTool(server, req, useVerboseLogs),\n payload,\n useVerboseLogs,\n )\n }\n\n if (mcpAccessSettings.auth?.verify && experimentalTools.auth?.enabled && isDevelopment) {\n registerTool(\n mcpAccessSettings.auth.verify,\n 'Verify',\n () => verifyTool(server, req, useVerboseLogs),\n payload,\n useVerboseLogs,\n )\n }\n\n if (mcpAccessSettings.auth?.resetPassword && experimentalTools.auth?.enabled) {\n registerTool(\n mcpAccessSettings.auth.resetPassword,\n 'Reset Password',\n () => resetPasswordTool(server, req, useVerboseLogs),\n payload,\n useVerboseLogs,\n )\n }\n\n if (mcpAccessSettings.auth?.forgotPassword && experimentalTools.auth?.enabled) {\n registerTool(\n mcpAccessSettings.auth.forgotPassword,\n 'Forgot Password',\n () => forgotPasswordTool(server, req, useVerboseLogs),\n payload,\n useVerboseLogs,\n )\n }\n\n if (mcpAccessSettings.auth?.unlock && experimentalTools.auth?.enabled) {\n registerTool(\n mcpAccessSettings.auth.unlock,\n 'Unlock',\n () => unlockTool(server, req, useVerboseLogs),\n payload,\n useVerboseLogs,\n )\n }\n\n if (useVerboseLogs) {\n payload.logger.info('[payload-mcp] 🚀 MCP Server Ready.')\n }\n },\n {\n serverInfo: serverOptions.serverInfo,\n },\n {\n basePath: MCPHandlerOptions.basePath || '/api',\n maxDuration: MCPHandlerOptions.maxDuration || 60,\n // INFO: Disabled until developer clarity is reached for server side streaming and we have an auth pattern for all SSE patterns\n // redisUrl: MCPHandlerOptions.redisUrl || process.env.REDIS_URL,\n verboseLogs: useVerboseLogs,\n },\n )\n } catch (error) {\n throw new APIError(`Error initializing MCP handler: ${String(error)}`, 500)\n }\n}\n"],"names":["createMcpHandler","join","APIError","configToJSONSchema","toCamelCase","registerTool","createResourceTool","deleteResourceTool","findResourceTool","updateResourceTool","authTool","forgotPasswordTool","loginTool","resetPasswordTool","unlockTool","verifyTool","createCollectionTool","deleteCollectionTool","findCollectionTool","updateCollectionTool","findConfigTool","updateConfigTool","createJobTool","runJobTool","updateJobTool","getMCPHandler","pluginOptions","mcpAccessSettings","req","payload","configSchema","config","wrapHandler","handler","args","_extra","length","handlerArgs","slice","payloadToolHandler","payloadPromptHandler","payloadResourceHandler","user","MCPOptions","mcp","customMCPTools","tools","customMCPPrompts","prompts","customMCPResources","resources","MCPHandlerOptions","handlerOptions","serverOptions","useVerboseLogs","verboseLogs","isDevelopment","process","env","NODE_ENV","experimentalTools","experimental","collectionsPluginConfig","collections","collectionsDirPath","cwd","configFilePath","jobsDirPath","jobs","server","enabledCollectionSlugs","Object","keys","filter","collection","fullyEnabled","enabled","partiallyEnabled","find","create","update","delete","forEach","enabledCollectionSlug","schema","definitions","toolCapabilities","allowCreate","allowUpdate","allowFind","allowDelete","error","String","tool","camelCasedToolName","name","isToolEnabled","description","parameters","prompt","camelCasedPromptName","isPromptEnabled","registerPrompt","argsSchema","title","logger","info","resource","camelCasedResourceName","isResourceEnabled","registerResource","uri","mimeType","run","auth","login","verify","resetPassword","forgotPassword","unlock","serverInfo","basePath","maxDuration"],"mappings":"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"}
|
|
@@ -112,13 +112,13 @@ import { join } from 'path';
|
|
|
112
112
|
/**
|
|
113
113
|
* Validate collection configuration structure
|
|
114
114
|
*/ function validateCollectionConfig(config) {
|
|
115
|
-
if (!config
|
|
115
|
+
if (!config) {
|
|
116
116
|
return {
|
|
117
117
|
error: 'Collection config is not a valid object',
|
|
118
118
|
success: false
|
|
119
119
|
};
|
|
120
120
|
}
|
|
121
|
-
if (!config.slug
|
|
121
|
+
if (!config.slug) {
|
|
122
122
|
return {
|
|
123
123
|
error: 'Collection config must have a valid slug property',
|
|
124
124
|
success: false
|
|
@@ -128,14 +128,14 @@ import { join } from 'path';
|
|
|
128
128
|
if (config.fields) {
|
|
129
129
|
for(let i = 0; i < config.fields.length; i++){
|
|
130
130
|
const field = config.fields[i];
|
|
131
|
-
if (!field
|
|
131
|
+
if (!field) {
|
|
132
132
|
return {
|
|
133
133
|
error: `Field at index ${i} is not a valid object`,
|
|
134
134
|
success: false
|
|
135
135
|
};
|
|
136
136
|
}
|
|
137
137
|
// Check if field has type property
|
|
138
|
-
if ('type' in field && field.type
|
|
138
|
+
if ('type' in field && field.type) {
|
|
139
139
|
return {
|
|
140
140
|
error: `Field at index ${i} has invalid type property`,
|
|
141
141
|
success: false
|
|
@@ -151,26 +151,26 @@ import { join } from 'path';
|
|
|
151
151
|
/**
|
|
152
152
|
* Validate task configuration structure
|
|
153
153
|
*/ function validateTaskConfig(config) {
|
|
154
|
-
if (!config
|
|
154
|
+
if (!config) {
|
|
155
155
|
return {
|
|
156
156
|
error: 'Task config is not a valid object',
|
|
157
157
|
success: false
|
|
158
158
|
};
|
|
159
159
|
}
|
|
160
|
-
if (!config.slug
|
|
160
|
+
if (!config.slug) {
|
|
161
161
|
return {
|
|
162
162
|
error: 'Task config must have a valid slug property',
|
|
163
163
|
success: false
|
|
164
164
|
};
|
|
165
165
|
}
|
|
166
|
-
if (!config.handler
|
|
166
|
+
if (!config.handler) {
|
|
167
167
|
return {
|
|
168
168
|
error: 'Task config must have a valid handler function',
|
|
169
169
|
success: false
|
|
170
170
|
};
|
|
171
171
|
}
|
|
172
172
|
// Validate optional properties
|
|
173
|
-
if (config.retries !== undefined &&
|
|
173
|
+
if (config.retries !== undefined && config.retries < 0) {
|
|
174
174
|
return {
|
|
175
175
|
error: 'Task config retries must be a non-negative number',
|
|
176
176
|
success: false
|
|
@@ -180,19 +180,19 @@ import { join } from 'path';
|
|
|
180
180
|
if (config.inputSchema && Array.isArray(config.inputSchema)) {
|
|
181
181
|
for(let i = 0; i < config.inputSchema.length; i++){
|
|
182
182
|
const field = config.inputSchema[i];
|
|
183
|
-
if (!field
|
|
183
|
+
if (!field) {
|
|
184
184
|
return {
|
|
185
185
|
error: `Input schema field at index ${i} is not a valid object`,
|
|
186
186
|
success: false
|
|
187
187
|
};
|
|
188
188
|
}
|
|
189
|
-
if (!field.name
|
|
189
|
+
if (!field.name) {
|
|
190
190
|
return {
|
|
191
191
|
error: `Input schema field at index ${i} must have a valid name property`,
|
|
192
192
|
success: false
|
|
193
193
|
};
|
|
194
194
|
}
|
|
195
|
-
if (!field.type
|
|
195
|
+
if (!field.type) {
|
|
196
196
|
return {
|
|
197
197
|
error: `Input schema field at index ${i} must have a valid type property`,
|
|
198
198
|
success: false
|
|
@@ -203,19 +203,19 @@ import { join } from 'path';
|
|
|
203
203
|
if (config.outputSchema && Array.isArray(config.outputSchema)) {
|
|
204
204
|
for(let i = 0; i < config.outputSchema.length; i++){
|
|
205
205
|
const field = config.outputSchema[i];
|
|
206
|
-
if (!field
|
|
206
|
+
if (!field) {
|
|
207
207
|
return {
|
|
208
208
|
error: `Output schema field at index ${i} is not a valid object`,
|
|
209
209
|
success: false
|
|
210
210
|
};
|
|
211
211
|
}
|
|
212
|
-
if (!field.name
|
|
212
|
+
if (!field.name) {
|
|
213
213
|
return {
|
|
214
214
|
error: `Output schema field at index ${i} must have a valid name property`,
|
|
215
215
|
success: false
|
|
216
216
|
};
|
|
217
217
|
}
|
|
218
|
-
if (!field.type
|
|
218
|
+
if (!field.type) {
|
|
219
219
|
return {
|
|
220
220
|
error: `Output schema field at index ${i} must have a valid type property`,
|
|
221
221
|
success: false
|
|
@@ -231,32 +231,32 @@ import { join } from 'path';
|
|
|
231
231
|
/**
|
|
232
232
|
* Validate workflow configuration structure
|
|
233
233
|
*/ function validateWorkflowConfig(config) {
|
|
234
|
-
if (!config
|
|
234
|
+
if (!config) {
|
|
235
235
|
return {
|
|
236
236
|
error: 'Workflow config is not a valid object',
|
|
237
237
|
success: false
|
|
238
238
|
};
|
|
239
239
|
}
|
|
240
|
-
if (!config.slug
|
|
240
|
+
if (!config.slug) {
|
|
241
241
|
return {
|
|
242
242
|
error: 'Workflow config must have a valid slug property',
|
|
243
243
|
success: false
|
|
244
244
|
};
|
|
245
245
|
}
|
|
246
|
-
if (!config.handler
|
|
246
|
+
if (!config.handler) {
|
|
247
247
|
return {
|
|
248
248
|
error: 'Workflow config must have a valid handler function',
|
|
249
249
|
success: false
|
|
250
250
|
};
|
|
251
251
|
}
|
|
252
252
|
// Validate optional properties
|
|
253
|
-
if (config.queue
|
|
253
|
+
if (config.queue) {
|
|
254
254
|
return {
|
|
255
255
|
error: 'Workflow config queue must be a string',
|
|
256
256
|
success: false
|
|
257
257
|
};
|
|
258
258
|
}
|
|
259
|
-
if (config.retries !== undefined &&
|
|
259
|
+
if (config.retries !== undefined && config.retries < 0) {
|
|
260
260
|
return {
|
|
261
261
|
error: 'Workflow config retries must be a non-negative number',
|
|
262
262
|
success: false
|
|
@@ -266,19 +266,19 @@ import { join } from 'path';
|
|
|
266
266
|
if (config.inputSchema && Array.isArray(config.inputSchema)) {
|
|
267
267
|
for(let i = 0; i < config.inputSchema.length; i++){
|
|
268
268
|
const field = config.inputSchema[i];
|
|
269
|
-
if (!field
|
|
269
|
+
if (!field) {
|
|
270
270
|
return {
|
|
271
271
|
error: `Input schema field at index ${i} is not a valid object`,
|
|
272
272
|
success: false
|
|
273
273
|
};
|
|
274
274
|
}
|
|
275
|
-
if (!field.name
|
|
275
|
+
if (!field.name) {
|
|
276
276
|
return {
|
|
277
277
|
error: `Input schema field at index ${i} must have a valid name property`,
|
|
278
278
|
success: false
|
|
279
279
|
};
|
|
280
280
|
}
|
|
281
|
-
if (!field.type
|
|
281
|
+
if (!field.type) {
|
|
282
282
|
return {
|
|
283
283
|
error: `Input schema field at index ${i} must have a valid type property`,
|
|
284
284
|
success: false
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/mcp/helpers/fileValidation.ts"],"sourcesContent":["import type { CollectionConfig } from 'payload'\n\nimport { existsSync } from 'fs'\nimport { join } from 'path'\n\nexport type ValidationType = 'collection' | 'task' | 'workflow'\n\nexport interface ValidationResult<T = unknown> {\n config?: T\n error?: string\n success: boolean\n}\n\n// Custom task config interface that matches what we're creating\nexport interface TaskConfig {\n handler: (args: {\n input: Record<string, unknown>\n job: Record<string, unknown>\n tasks: Record<string, unknown>\n }) => Record<string, unknown>\n inputSchema?: Array<{\n label?: string\n name: string\n options?: Array<{ label: string; value: string }>\n required?: boolean\n type: string\n }>\n label?: string\n outputSchema?: Array<{\n label?: string\n name: string\n options?: Array<{ label: string; value: string }>\n required?: boolean\n type: string\n }>\n retries?: number\n slug: string\n}\n\n// Custom workflow config interface that matches what we're creating\nexport interface WorkflowConfig {\n handler: (args: {\n input: Record<string, unknown>\n job: Record<string, unknown>\n tasks: Record<string, unknown>\n }) => void\n inputSchema?: Array<{\n label?: string\n name: string\n options?: Array<{ label: string; value: string }>\n required?: boolean\n type: string\n }>\n label?: string\n queue?: string\n retries?: number\n slug: string\n}\n\n/**\n * Generic validation function for Payload configuration files\n * @param fileName - The name of the file (e.g., 'Users.ts', 'my-task.ts')\n * @param type - The type of validation to perform ('collection', 'task', or 'workflow')\n * @returns Object containing success status and any error messages\n */\nexport const validatePayloadFile = async <T = CollectionConfig | TaskConfig | WorkflowConfig>(\n fileName: string,\n type: ValidationType,\n): Promise<ValidationResult<T>> => {\n try {\n const basePath = type === 'collection' ? 'collections' : type === 'task' ? 'tasks' : 'workflows'\n const fullPath = join(process.cwd(), 'src', basePath)\n const filePath = join(fullPath, fileName)\n\n // Check if file exists\n if (!existsSync(filePath)) {\n return {\n error: `${type} file does not exist: ${fileName}`,\n success: false,\n }\n }\n\n // Clear require cache to ensure fresh import\n delete require.cache[filePath]\n\n // Use relative path for webpack compatibility\n const moduleName = fileName.replace('.ts', '')\n const relativePath = `../${basePath}/${moduleName}`\n\n // Dynamic import with relative path\n const importedModule = await import(/* webpackIgnore: true */ relativePath)\n\n // Get the configuration based on type\n let config: T | undefined\n\n if (type === 'collection') {\n config = getCollectionConfig(importedModule, moduleName) as T\n } else if (type === 'task') {\n config = getTaskConfig(importedModule) as T\n } else if (type === 'workflow') {\n config = getWorkflowConfig(importedModule) as T\n }\n\n if (!config) {\n return {\n error: `${type} file does not export a valid ${type} config`,\n success: false,\n }\n }\n\n // Validate the configuration\n let validationResult: ValidationResult<unknown>\n if (type === 'collection') {\n validationResult = validateCollectionConfig(config as unknown as CollectionConfig)\n } else if (type === 'task') {\n validationResult = validateTaskConfig(config as unknown as TaskConfig)\n } else if (type === 'workflow') {\n validationResult = validateWorkflowConfig(config as unknown as WorkflowConfig)\n } else {\n return {\n error: `Unknown validation type: ${type}`,\n success: false,\n }\n }\n\n if (!validationResult.success) {\n return validationResult as ValidationResult<T>\n }\n\n return {\n config,\n success: true,\n }\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : 'Unknown error during validation'\n return {\n error: `Failed to validate ${type} file: ${errorMessage}`,\n success: false,\n }\n }\n}\n\n/**\n * Extract collection configuration from module exports\n */\nfunction getCollectionConfig(\n importedModule: Record<string, unknown>,\n moduleName: string,\n): CollectionConfig | undefined {\n if (importedModule.default) {\n return importedModule.default as CollectionConfig\n }\n\n if (importedModule[moduleName]) {\n return importedModule[moduleName] as CollectionConfig\n }\n\n return undefined\n}\n\n/**\n * Extract task configuration from module exports\n */\nfunction getTaskConfig(importedModule: Record<string, unknown>): TaskConfig | undefined {\n // First check for default export\n if (importedModule.default) {\n return importedModule.default as TaskConfig\n }\n\n // Look for named exports ending with \"Task\"\n const exportNames = Object.keys(importedModule)\n const taskExport = exportNames.find((name) => name.endsWith('Task'))\n\n if (taskExport) {\n return importedModule[taskExport] as TaskConfig\n }\n\n return undefined\n}\n\n/**\n * Extract workflow configuration from module exports\n */\nfunction getWorkflowConfig(importedModule: Record<string, unknown>): undefined | WorkflowConfig {\n // First check for default export\n if (importedModule.default) {\n return importedModule.default as WorkflowConfig\n }\n\n // Look for named exports ending with \"Workflow\"\n const exportNames = Object.keys(importedModule)\n const workflowExport = exportNames.find((name) => name.endsWith('Workflow'))\n\n if (workflowExport) {\n return importedModule[workflowExport] as WorkflowConfig\n }\n\n return undefined\n}\n\n/**\n * Validate collection configuration structure\n */\nfunction validateCollectionConfig(config: CollectionConfig): ValidationResult<CollectionConfig> {\n if (!config || typeof config !== 'object') {\n return {\n error: 'Collection config is not a valid object',\n success: false,\n }\n }\n\n if (!config.slug || typeof config.slug !== 'string') {\n return {\n error: 'Collection config must have a valid slug property',\n success: false,\n }\n }\n\n // Validate each field has required properties\n if (config.fields) {\n for (let i = 0; i < config.fields.length; i++) {\n const field = config.fields[i] as Record<string, unknown>\n if (!field || typeof field !== 'object') {\n return {\n error: `Field at index ${i} is not a valid object`,\n success: false,\n }\n }\n\n // Check if field has type property\n if ('type' in field && field.type && typeof field.type !== 'string') {\n return {\n error: `Field at index ${i} has invalid type property`,\n success: false,\n }\n }\n }\n }\n\n return { config, success: true }\n}\n\n/**\n * Validate task configuration structure\n */\nfunction validateTaskConfig(config: TaskConfig): ValidationResult<TaskConfig> {\n if (!config || typeof config !== 'object') {\n return {\n error: 'Task config is not a valid object',\n success: false,\n }\n }\n\n if (!config.slug || typeof config.slug !== 'string') {\n return {\n error: 'Task config must have a valid slug property',\n success: false,\n }\n }\n\n if (!config.handler || typeof config.handler !== 'function') {\n return {\n error: 'Task config must have a valid handler function',\n success: false,\n }\n }\n\n // Validate optional properties\n if (config.retries !== undefined && (typeof config.retries !== 'number' || config.retries < 0)) {\n return {\n error: 'Task config retries must be a non-negative number',\n success: false,\n }\n }\n\n // Validate schemas if present\n if (config.inputSchema && Array.isArray(config.inputSchema)) {\n for (let i = 0; i < config.inputSchema.length; i++) {\n const field = config.inputSchema[i]\n if (!field || typeof field !== 'object') {\n return {\n error: `Input schema field at index ${i} is not a valid object`,\n success: false,\n }\n }\n\n if (!field.name || typeof field.name !== 'string') {\n return {\n error: `Input schema field at index ${i} must have a valid name property`,\n success: false,\n }\n }\n\n if (!field.type || typeof field.type !== 'string') {\n return {\n error: `Input schema field at index ${i} must have a valid type property`,\n success: false,\n }\n }\n }\n }\n\n if (config.outputSchema && Array.isArray(config.outputSchema)) {\n for (let i = 0; i < config.outputSchema.length; i++) {\n const field = config.outputSchema[i]\n if (!field || typeof field !== 'object') {\n return {\n error: `Output schema field at index ${i} is not a valid object`,\n success: false,\n }\n }\n\n if (!field.name || typeof field.name !== 'string') {\n return {\n error: `Output schema field at index ${i} must have a valid name property`,\n success: false,\n }\n }\n\n if (!field.type || typeof field.type !== 'string') {\n return {\n error: `Output schema field at index ${i} must have a valid type property`,\n success: false,\n }\n }\n }\n }\n\n return { config, success: true }\n}\n\n/**\n * Validate workflow configuration structure\n */\nfunction validateWorkflowConfig(config: WorkflowConfig): ValidationResult<WorkflowConfig> {\n if (!config || typeof config !== 'object') {\n return {\n error: 'Workflow config is not a valid object',\n success: false,\n }\n }\n\n if (!config.slug || typeof config.slug !== 'string') {\n return {\n error: 'Workflow config must have a valid slug property',\n success: false,\n }\n }\n\n if (!config.handler || typeof config.handler !== 'function') {\n return {\n error: 'Workflow config must have a valid handler function',\n success: false,\n }\n }\n\n // Validate optional properties\n if (config.queue && typeof config.queue !== 'string') {\n return {\n error: 'Workflow config queue must be a string',\n success: false,\n }\n }\n\n if (config.retries !== undefined && (typeof config.retries !== 'number' || config.retries < 0)) {\n return {\n error: 'Workflow config retries must be a non-negative number',\n success: false,\n }\n }\n\n // Validate schema if present\n if (config.inputSchema && Array.isArray(config.inputSchema)) {\n for (let i = 0; i < config.inputSchema.length; i++) {\n const field = config.inputSchema[i]\n if (!field || typeof field !== 'object') {\n return {\n error: `Input schema field at index ${i} is not a valid object`,\n success: false,\n }\n }\n\n if (!field.name || typeof field.name !== 'string') {\n return {\n error: `Input schema field at index ${i} must have a valid name property`,\n success: false,\n }\n }\n\n if (!field.type || typeof field.type !== 'string') {\n return {\n error: `Input schema field at index ${i} must have a valid type property`,\n success: false,\n }\n }\n }\n }\n\n return { config, success: true }\n}\n\n// Convenience functions for backward compatibility\nexport const validateCollectionFile = async (\n fileName: string,\n): Promise<ValidationResult<CollectionConfig>> => {\n return validatePayloadFile<CollectionConfig>(fileName, 'collection')\n}\n\nexport const validateTaskFile = async (fileName: string): Promise<ValidationResult<TaskConfig>> => {\n return validatePayloadFile<TaskConfig>(fileName, 'task')\n}\n\nexport const validateWorkflowFile = async (\n fileName: string,\n): Promise<ValidationResult<WorkflowConfig>> => {\n return validatePayloadFile<WorkflowConfig>(fileName, 'workflow')\n}\n"],"names":["existsSync","join","validatePayloadFile","fileName","type","basePath","fullPath","process","cwd","filePath","error","success","require","cache","moduleName","replace","relativePath","importedModule","config","getCollectionConfig","getTaskConfig","getWorkflowConfig","validationResult","validateCollectionConfig","validateTaskConfig","validateWorkflowConfig","errorMessage","Error","message","default","undefined","exportNames","Object","keys","taskExport","find","name","endsWith","workflowExport","slug","fields","i","length","field","handler","retries","inputSchema","Array","isArray","outputSchema","queue","validateCollectionFile","validateTaskFile","validateWorkflowFile"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/mcp/helpers/fileValidation.ts"],"sourcesContent":["import type { CollectionConfig } from 'payload'\n\nimport { existsSync } from 'fs'\nimport { join } from 'path'\n\nexport type ValidationType = 'collection' | 'task' | 'workflow'\n\nexport interface ValidationResult<T = unknown> {\n config?: T\n error?: string\n success: boolean\n}\n\n// Custom task config interface that matches what we're creating\nexport interface TaskConfig {\n handler: (args: {\n input: Record<string, unknown>\n job: Record<string, unknown>\n tasks: Record<string, unknown>\n }) => Record<string, unknown>\n inputSchema?: Array<{\n label?: string\n name: string\n options?: Array<{ label: string; value: string }>\n required?: boolean\n type: string\n }>\n label?: string\n outputSchema?: Array<{\n label?: string\n name: string\n options?: Array<{ label: string; value: string }>\n required?: boolean\n type: string\n }>\n retries?: number\n slug: string\n}\n\n// Custom workflow config interface that matches what we're creating\nexport interface WorkflowConfig {\n handler: (args: {\n input: Record<string, unknown>\n job: Record<string, unknown>\n tasks: Record<string, unknown>\n }) => void\n inputSchema?: Array<{\n label?: string\n name: string\n options?: Array<{ label: string; value: string }>\n required?: boolean\n type: string\n }>\n label?: string\n queue?: string\n retries?: number\n slug: string\n}\n\n/**\n * Generic validation function for Payload configuration files\n * @param fileName - The name of the file (e.g., 'Users.ts', 'my-task.ts')\n * @param type - The type of validation to perform ('collection', 'task', or 'workflow')\n * @returns Object containing success status and any error messages\n */\nexport const validatePayloadFile = async <T = CollectionConfig | TaskConfig | WorkflowConfig>(\n fileName: string,\n type: ValidationType,\n): Promise<ValidationResult<T>> => {\n try {\n const basePath = type === 'collection' ? 'collections' : type === 'task' ? 'tasks' : 'workflows'\n const fullPath = join(process.cwd(), 'src', basePath)\n const filePath = join(fullPath, fileName)\n\n // Check if file exists\n if (!existsSync(filePath)) {\n return {\n error: `${type} file does not exist: ${fileName}`,\n success: false,\n }\n }\n\n // Clear require cache to ensure fresh import\n delete require.cache[filePath]\n\n // Use relative path for webpack compatibility\n const moduleName = fileName.replace('.ts', '')\n const relativePath = `../${basePath}/${moduleName}`\n\n // Dynamic import with relative path\n const importedModule = await import(/* webpackIgnore: true */ relativePath)\n\n // Get the configuration based on type\n let config: T | undefined\n\n if (type === 'collection') {\n config = getCollectionConfig(importedModule, moduleName) as T\n } else if (type === 'task') {\n config = getTaskConfig(importedModule) as T\n } else if (type === 'workflow') {\n config = getWorkflowConfig(importedModule) as T\n }\n\n if (!config) {\n return {\n error: `${type} file does not export a valid ${type} config`,\n success: false,\n }\n }\n\n // Validate the configuration\n let validationResult: ValidationResult<unknown>\n if (type === 'collection') {\n validationResult = validateCollectionConfig(config as unknown as CollectionConfig)\n } else if (type === 'task') {\n validationResult = validateTaskConfig(config as unknown as TaskConfig)\n } else if (type === 'workflow') {\n validationResult = validateWorkflowConfig(config as unknown as WorkflowConfig)\n } else {\n return {\n error: `Unknown validation type: ${type}`,\n success: false,\n }\n }\n\n if (!validationResult.success) {\n return validationResult as ValidationResult<T>\n }\n\n return {\n config,\n success: true,\n }\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : 'Unknown error during validation'\n return {\n error: `Failed to validate ${type} file: ${errorMessage}`,\n success: false,\n }\n }\n}\n\n/**\n * Extract collection configuration from module exports\n */\nfunction getCollectionConfig(\n importedModule: Record<string, unknown>,\n moduleName: string,\n): CollectionConfig | undefined {\n if (importedModule.default) {\n return importedModule.default as CollectionConfig\n }\n\n if (importedModule[moduleName]) {\n return importedModule[moduleName] as CollectionConfig\n }\n\n return undefined\n}\n\n/**\n * Extract task configuration from module exports\n */\nfunction getTaskConfig(importedModule: Record<string, unknown>): TaskConfig | undefined {\n // First check for default export\n if (importedModule.default) {\n return importedModule.default as TaskConfig\n }\n\n // Look for named exports ending with \"Task\"\n const exportNames = Object.keys(importedModule)\n const taskExport = exportNames.find((name) => name.endsWith('Task'))\n\n if (taskExport) {\n return importedModule[taskExport] as TaskConfig\n }\n\n return undefined\n}\n\n/**\n * Extract workflow configuration from module exports\n */\nfunction getWorkflowConfig(importedModule: Record<string, unknown>): undefined | WorkflowConfig {\n // First check for default export\n if (importedModule.default) {\n return importedModule.default as WorkflowConfig\n }\n\n // Look for named exports ending with \"Workflow\"\n const exportNames = Object.keys(importedModule)\n const workflowExport = exportNames.find((name) => name.endsWith('Workflow'))\n\n if (workflowExport) {\n return importedModule[workflowExport] as WorkflowConfig\n }\n\n return undefined\n}\n\n/**\n * Validate collection configuration structure\n */\nfunction validateCollectionConfig(config: CollectionConfig): ValidationResult<CollectionConfig> {\n if (!config) {\n return {\n error: 'Collection config is not a valid object',\n success: false,\n }\n }\n\n if (!config.slug) {\n return {\n error: 'Collection config must have a valid slug property',\n success: false,\n }\n }\n\n // Validate each field has required properties\n if (config.fields) {\n for (let i = 0; i < config.fields.length; i++) {\n const field = config.fields[i] as Record<string, unknown>\n if (!field) {\n return {\n error: `Field at index ${i} is not a valid object`,\n success: false,\n }\n }\n\n // Check if field has type property\n if ('type' in field && field.type) {\n return {\n error: `Field at index ${i} has invalid type property`,\n success: false,\n }\n }\n }\n }\n\n return { config, success: true }\n}\n\n/**\n * Validate task configuration structure\n */\nfunction validateTaskConfig(config: TaskConfig): ValidationResult<TaskConfig> {\n if (!config) {\n return {\n error: 'Task config is not a valid object',\n success: false,\n }\n }\n\n if (!config.slug) {\n return {\n error: 'Task config must have a valid slug property',\n success: false,\n }\n }\n\n if (!config.handler) {\n return {\n error: 'Task config must have a valid handler function',\n success: false,\n }\n }\n\n // Validate optional properties\n if (config.retries !== undefined && config.retries < 0) {\n return {\n error: 'Task config retries must be a non-negative number',\n success: false,\n }\n }\n\n // Validate schemas if present\n if (config.inputSchema && Array.isArray(config.inputSchema)) {\n for (let i = 0; i < config.inputSchema.length; i++) {\n const field = config.inputSchema[i]\n if (!field) {\n return {\n error: `Input schema field at index ${i} is not a valid object`,\n success: false,\n }\n }\n\n if (!field.name) {\n return {\n error: `Input schema field at index ${i} must have a valid name property`,\n success: false,\n }\n }\n\n if (!field.type) {\n return {\n error: `Input schema field at index ${i} must have a valid type property`,\n success: false,\n }\n }\n }\n }\n\n if (config.outputSchema && Array.isArray(config.outputSchema)) {\n for (let i = 0; i < config.outputSchema.length; i++) {\n const field = config.outputSchema[i]\n if (!field) {\n return {\n error: `Output schema field at index ${i} is not a valid object`,\n success: false,\n }\n }\n\n if (!field.name) {\n return {\n error: `Output schema field at index ${i} must have a valid name property`,\n success: false,\n }\n }\n\n if (!field.type) {\n return {\n error: `Output schema field at index ${i} must have a valid type property`,\n success: false,\n }\n }\n }\n }\n\n return { config, success: true }\n}\n\n/**\n * Validate workflow configuration structure\n */\nfunction validateWorkflowConfig(config: WorkflowConfig): ValidationResult<WorkflowConfig> {\n if (!config) {\n return {\n error: 'Workflow config is not a valid object',\n success: false,\n }\n }\n\n if (!config.slug) {\n return {\n error: 'Workflow config must have a valid slug property',\n success: false,\n }\n }\n\n if (!config.handler) {\n return {\n error: 'Workflow config must have a valid handler function',\n success: false,\n }\n }\n\n // Validate optional properties\n if (config.queue) {\n return {\n error: 'Workflow config queue must be a string',\n success: false,\n }\n }\n\n if (config.retries !== undefined && config.retries < 0) {\n return {\n error: 'Workflow config retries must be a non-negative number',\n success: false,\n }\n }\n\n // Validate schema if present\n if (config.inputSchema && Array.isArray(config.inputSchema)) {\n for (let i = 0; i < config.inputSchema.length; i++) {\n const field = config.inputSchema[i]\n if (!field) {\n return {\n error: `Input schema field at index ${i} is not a valid object`,\n success: false,\n }\n }\n\n if (!field.name) {\n return {\n error: `Input schema field at index ${i} must have a valid name property`,\n success: false,\n }\n }\n\n if (!field.type) {\n return {\n error: `Input schema field at index ${i} must have a valid type property`,\n success: false,\n }\n }\n }\n }\n\n return { config, success: true }\n}\n\n// Convenience functions for backward compatibility\nexport const validateCollectionFile = async (\n fileName: string,\n): Promise<ValidationResult<CollectionConfig>> => {\n return validatePayloadFile<CollectionConfig>(fileName, 'collection')\n}\n\nexport const validateTaskFile = async (fileName: string): Promise<ValidationResult<TaskConfig>> => {\n return validatePayloadFile<TaskConfig>(fileName, 'task')\n}\n\nexport const validateWorkflowFile = async (\n fileName: string,\n): Promise<ValidationResult<WorkflowConfig>> => {\n return validatePayloadFile<WorkflowConfig>(fileName, 'workflow')\n}\n"],"names":["existsSync","join","validatePayloadFile","fileName","type","basePath","fullPath","process","cwd","filePath","error","success","require","cache","moduleName","replace","relativePath","importedModule","config","getCollectionConfig","getTaskConfig","getWorkflowConfig","validationResult","validateCollectionConfig","validateTaskConfig","validateWorkflowConfig","errorMessage","Error","message","default","undefined","exportNames","Object","keys","taskExport","find","name","endsWith","workflowExport","slug","fields","i","length","field","handler","retries","inputSchema","Array","isArray","outputSchema","queue","validateCollectionFile","validateTaskFile","validateWorkflowFile"],"mappings":"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"}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { CollectionConfig, CollectionSlug, PayloadRequest } from 'payload';
|
|
1
|
+
import type { CollectionConfig, CollectionSlug, PayloadRequest, TypedUser } from 'payload';
|
|
2
2
|
import type { z } from 'zod';
|
|
3
3
|
import { type ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
4
4
|
export type PluginMCPServerConfig = {
|
|
@@ -121,7 +121,23 @@ export type PluginMCPServerConfig = {
|
|
|
121
121
|
/**
|
|
122
122
|
* Set the handler of the prompt. This is the function that will be called when the prompt is used.
|
|
123
123
|
*/
|
|
124
|
-
handler: (
|
|
124
|
+
handler: (args: Record<string, unknown>, req: PayloadRequest, _extra: unknown) => {
|
|
125
|
+
messages: Array<{
|
|
126
|
+
content: {
|
|
127
|
+
text: string;
|
|
128
|
+
type: 'text';
|
|
129
|
+
};
|
|
130
|
+
role: 'assistant' | 'user';
|
|
131
|
+
}>;
|
|
132
|
+
} | Promise<{
|
|
133
|
+
messages: Array<{
|
|
134
|
+
content: {
|
|
135
|
+
text: string;
|
|
136
|
+
type: 'text';
|
|
137
|
+
};
|
|
138
|
+
role: 'assistant' | 'user';
|
|
139
|
+
}>;
|
|
140
|
+
}>;
|
|
125
141
|
/**
|
|
126
142
|
* Set the function name of the prompt.
|
|
127
143
|
*/
|
|
@@ -142,8 +158,19 @@ export type PluginMCPServerConfig = {
|
|
|
142
158
|
description: string;
|
|
143
159
|
/**
|
|
144
160
|
* Set the handler of the resource. This is the function that will be called when the resource is used.
|
|
161
|
+
* The handler can have either 3 arguments (when no args are passed) or 4 arguments (when args are passed).
|
|
145
162
|
*/
|
|
146
|
-
handler: (...args: any) =>
|
|
163
|
+
handler: (...args: any[]) => {
|
|
164
|
+
contents: Array<{
|
|
165
|
+
text: string;
|
|
166
|
+
uri: string;
|
|
167
|
+
}>;
|
|
168
|
+
} | Promise<{
|
|
169
|
+
contents: Array<{
|
|
170
|
+
text: string;
|
|
171
|
+
uri: string;
|
|
172
|
+
}>;
|
|
173
|
+
}>;
|
|
147
174
|
/**
|
|
148
175
|
* Set the mime type of the resource.
|
|
149
176
|
* example: 'text/plain'
|
|
@@ -177,11 +204,18 @@ export type PluginMCPServerConfig = {
|
|
|
177
204
|
/**
|
|
178
205
|
* Set the handler of the tool. This is the function that will be called when the tool is used.
|
|
179
206
|
*/
|
|
180
|
-
handler: (args: Record<string, unknown
|
|
207
|
+
handler: (args: Record<string, unknown>, req: PayloadRequest, _extra: unknown) => {
|
|
208
|
+
content: Array<{
|
|
209
|
+
text: string;
|
|
210
|
+
type: 'text';
|
|
211
|
+
}>;
|
|
212
|
+
role?: string;
|
|
213
|
+
} | Promise<{
|
|
181
214
|
content: Array<{
|
|
182
215
|
text: string;
|
|
183
216
|
type: 'text';
|
|
184
217
|
}>;
|
|
218
|
+
role?: string;
|
|
185
219
|
}>;
|
|
186
220
|
/**
|
|
187
221
|
* Set the name of the tool. This is the name that will be used to identify the tool. LLMs will interperate the name to determine when to use the tool.
|
|
@@ -284,6 +318,7 @@ export type MCPAccessSettings = {
|
|
|
284
318
|
'payload-mcp-prompt'?: Record<string, boolean>;
|
|
285
319
|
'payload-mcp-resource'?: Record<string, boolean>;
|
|
286
320
|
'payload-mcp-tool'?: Record<string, boolean>;
|
|
321
|
+
user: TypedUser;
|
|
287
322
|
} & Record<string, unknown>;
|
|
288
323
|
export type FieldDefinition = {
|
|
289
324
|
description?: string;
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/types.ts"],"sourcesContent":["import type { CollectionConfig, CollectionSlug, PayloadRequest } from 'payload'\nimport type { z } from 'zod'\n\nimport { type ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js'\n\nexport type PluginMCPServerConfig = {\n /**\n * Set the collections that should be available as resources via MCP.\n */\n collections?: Partial<\n Record<\n CollectionSlug,\n {\n /**\n * Set the description of the collection. This is used by MCP clients to determine when to use the collecton as a resource.\n */\n description?: string\n /**\n * Set the enabled capabilities of the collection. Admins can then allow or disallow the use of the capability by MCP clients.\n */\n enabled:\n | {\n create?: boolean\n delete?: boolean\n find?: boolean\n update?: boolean\n }\n | boolean\n\n /**\n * Override the response generated by the MCP client. This allows you to modify the response that is sent to the MCP client. This is useful for adding additional data to the response, data normalization, or verifying data.\n */\n overrideResponse?: (\n response: {\n content: Array<{\n text: string\n type: string\n }>\n },\n doc: Record<string, unknown>,\n req: PayloadRequest,\n ) => {\n content: Array<{\n text: string\n type: string\n }>\n }\n }\n >\n >\n /**\n * Disable the MCP plugin.\n */\n disabled?: boolean\n /**\n * Experimental features\n * **These features are for experimental purposes -- They are Disabled in Production by Default**\n */\n experimental?: {\n /**\n * These are MCP tools that can be used by a client to modify Payload.\n */\n tools: {\n /**\n * **Experimental** -- Auth MCP tools allow a client to change authentication priviliages for users. This is for developing ideas that help Admins with authentication tasks.\n */\n auth?: {\n /**\n * Enable the auth MCP tools. This allows Admins to enable or disable the auth capabilities.\n * @default false\n */\n enabled: boolean\n }\n /**\n * **Experimental** -- Collection MCP tools allow for the creation, modification, and deletion of Payload collections. This is for developing ideas that help Developers with collection tasks.\n */\n collections?: {\n /**\n * Set the directory path to the collections directory. This can be a directory outside of your default directory, or another Payload project.\n */\n collectionsDirPath: string\n /**\n * Enable the collection MCP tools. This allows Admins to enable or disable the Collection modification capabilities.\n * @default false\n */\n enabled: boolean\n }\n /**\n * **Experimental** -- Config MCP tools allow for the modification of a Payload Config. This is for developing ideas that help Developers with config tasks.\n */\n config?: {\n /**\n * Set the directory path to the config directory. This can be a directory outside of your default directory, or another Payload project.\n */\n configFilePath: string\n /**\n * Enable the config MCP tools. This allows Admins to enable or disable the Payload Config modification capabilities.\n * @default false\n */\n enabled: boolean\n }\n /**\n * **Experimental** -- Jobs MCP tools allow for the modification of Payload jobs. This is for developing ideas that help Developers with job tasks.\n */\n jobs?: {\n /**\n * Enable the jobs MCP tools. This allows Admins to enable or disable the Job modification capabilities.\n * @default false\n */\n enabled: boolean\n /**\n * Set the directory path to the jobs directory. This can be a directory outside of your default directory, or another Payload project.\n */\n jobsDirPath: string\n }\n }\n }\n /**\n * MCP Server options.\n */\n mcp?: {\n handlerOptions?: MCPHandlerOptions\n /**\n * Add custom MCP Prompts.\n */\n prompts?: {\n /**\n * Set the args schema of the prompt. This is the args schema that will be passed to the prompt. This is used by MCP clients to determine the arguments that will be passed to the prompt.\n */\n argsSchema: z.ZodRawShape\n /**\n * Set the description of the prompt. This is used by MCP clients to determine when to use the prompt.\n */\n description: string\n /**\n * Set the handler of the prompt. This is the function that will be called when the prompt is used.\n */\n handler: (...args: any) => any\n /**\n * Set the function name of the prompt.\n */\n name: string\n /**\n * Set the title of the prompt. LLMs will interperate the title to determine when to use the prompt.\n */\n title: string\n }[]\n\n /**\n * Add custom MCP Resource.\n */\n resources?: {\n /**\n * Set the description of the resource. This is used by MCP clients to determine when to use the resource.\n * example: 'Data is a resource that contains special data.'\n */\n description: string\n /**\n * Set the handler of the resource. This is the function that will be called when the resource is used.\n */\n handler: (...args: any) => any\n /**\n * Set the mime type of the resource.\n * example: 'text/plain'\n */\n mimeType: string\n /**\n * Set the function name of the resource.\n * example: 'data'\n */\n name: string\n /**\n * Set the title of the resource. LLMs will interperate the title to determine when to use the resource.\n * example: 'Data'\n */\n title: string\n /**\n * Set the uri of the resource.\n * example: 'data://app'\n */\n uri: ResourceTemplate | string\n }[]\n serverOptions?: MCPServerOptions\n /**\n * Add custom MCP Tools.\n */\n tools?: {\n /**\n * Set the description of the tool. This is used by MCP clients to determine when to use the tool.\n */\n description: string\n /**\n * Set the handler of the tool. This is the function that will be called when the tool is used.\n */\n handler: (args: Record<string, unknown>) => Promise<{\n content: Array<{\n text: string\n type: 'text'\n }>\n }>\n /**\n * Set the name of the tool. This is the name that will be used to identify the tool. LLMs will interperate the name to determine when to use the tool.\n */\n name: string\n /**\n * Set the parameters of the tool. This is the parameters that will be passed to the tool.\n */\n parameters: z.ZodRawShape\n }[]\n }\n\n /**\n * Override the API key collection.\n * This allows you to add fields to the API key collection or modify the collection in any way you want.\n * @param collection - The API key collection.\n * @returns The modified API key collection.\n */\n overrideApiKeyCollection?: (collection: CollectionConfig) => CollectionConfig\n\n /**\n * Override the authentication method.\n * This allows you to use a custom authentication method instead of the default API key authentication.\n * @param req - The request object.\n * @returns The MCP access settings.\n */\n overrideAuth?: (\n req: PayloadRequest,\n getDefaultMcpAccessSettings: (overrideApiKey?: null | string) => Promise<MCPAccessSettings>,\n ) => MCPAccessSettings | Promise<MCPAccessSettings>\n\n /**\n * Set the users collection that API keys should be associated with.\n */\n userCollection?: CollectionConfig | string\n}\n\n/**\n * MCP Handler options.\n */\nexport type MCPHandlerOptions = {\n /**\n * Set the base path of the MCP handler. This is the path that will be used to access the MCP handler.\n * @default /api\n */\n basePath?: string\n /**\n * Set the maximum duration of the MCP handler. This is the maximum duration that the MCP handler will run for.\n * @default 60\n */\n maxDuration?: number\n /**\n * Set the Redis URL for the MCP handler. This is the URL that will be used to access the Redis server.\n * @default process.env.REDIS_URL\n * INFO: Disabled until developer clarity is reached for server side streaming and we have an auth pattern for all SSE patterns\n */\n // redisUrl?: string\n /**\n * Set verbose logging.\n * @default false\n */\n verboseLogs?: boolean\n}\n\n/**\n * MCP Server options.\n */\nexport type MCPServerOptions = {\n /**\n * Set the server info of the MCP server.\n */\n serverInfo?: {\n /**\n * Set the name of the MCP server.\n * @default 'Payload MCP Server'\n */\n name: string\n /**\n * Set the version of the MCP server.\n * @default '1.0.0'\n */\n version: string\n }\n}\n\nexport type MCPAccessSettings = {\n auth?: {\n auth?: boolean\n forgotPassword?: boolean\n login?: boolean\n resetPassword?: boolean\n unlock?: boolean\n verify?: boolean\n }\n collections?: {\n create?: boolean\n delete?: boolean\n find?: boolean\n update?: boolean\n }\n config?: {\n find?: boolean\n update?: boolean\n }\n jobs?: {\n create?: boolean\n run?: boolean\n update?: boolean\n }\n 'payload-mcp-prompt'?: Record<string, boolean>\n 'payload-mcp-resource'?: Record<string, boolean>\n 'payload-mcp-tool'?: Record<string, boolean>\n} & Record<string, unknown>\n\nexport type FieldDefinition = {\n description?: string\n name: string\n options?: { label: string; value: string }[]\n position?: 'main' | 'sidebar'\n required?: boolean\n type: string\n}\n\nexport type FieldModification = {\n changes: {\n description?: string\n options?: { label: string; value: string }[]\n position?: 'main' | 'sidebar'\n required?: boolean\n type?: string\n }\n fieldName: string\n}\n\nexport type CollectionConfigUpdates = {\n access?: {\n create?: string\n delete?: string\n read?: string\n update?: string\n }\n description?: string\n slug?: string\n timestamps?: boolean\n versioning?: boolean\n}\n\nexport type AdminConfig = {\n avatar?: string\n css?: string\n dateFormat?: string\n inactivityRoute?: string\n livePreview?: {\n breakpoints?: Array<{\n height: number\n label: string\n name: string\n width: number\n }>\n }\n logoutRoute?: string\n meta?: {\n favicon?: string\n ogImage?: string\n titleSuffix?: string\n }\n user?: string\n}\n\nexport type DatabaseConfig = {\n connectOptions?: string\n type?: 'mongodb' | 'postgres'\n url?: string\n}\n\nexport type PluginUpdates = {\n add?: string[]\n remove?: string[]\n}\n\nexport type GeneralConfig = {\n cookiePrefix?: string\n cors?: string\n csrf?: string\n graphQL?: {\n disable?: boolean\n schemaOutputFile?: string\n }\n rateLimit?: {\n max?: number\n skip?: string\n window?: number\n }\n secret?: string\n serverURL?: string\n typescript?: {\n declare?: boolean\n outputFile?: string\n }\n}\n\nexport interface SchemaField {\n description?: string\n name: string\n options?: string[]\n required?: boolean\n type: string\n}\n\nexport interface TaskSequenceItem {\n description?: string\n retries?: number\n taskId: string\n taskSlug: string\n timeout?: number\n}\n\nexport interface JobConfigUpdate {\n description?: string\n queue?: string\n retries?: number\n timeout?: number\n}\n"],"names":[],"mappings":"AAgaA,WAKC"}
|
|
1
|
+
{"version":3,"sources":["../src/types.ts"],"sourcesContent":["import type { CollectionConfig, CollectionSlug, PayloadRequest, TypedUser } from 'payload'\nimport type { z } from 'zod'\n\nimport { type ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js'\n\nexport type PluginMCPServerConfig = {\n /**\n * Set the collections that should be available as resources via MCP.\n */\n collections?: Partial<\n Record<\n CollectionSlug,\n {\n /**\n * Set the description of the collection. This is used by MCP clients to determine when to use the collecton as a resource.\n */\n description?: string\n /**\n * Set the enabled capabilities of the collection. Admins can then allow or disallow the use of the capability by MCP clients.\n */\n enabled:\n | {\n create?: boolean\n delete?: boolean\n find?: boolean\n update?: boolean\n }\n | boolean\n\n /**\n * Override the response generated by the MCP client. This allows you to modify the response that is sent to the MCP client. This is useful for adding additional data to the response, data normalization, or verifying data.\n */\n overrideResponse?: (\n response: {\n content: Array<{\n text: string\n type: string\n }>\n },\n doc: Record<string, unknown>,\n req: PayloadRequest,\n ) => {\n content: Array<{\n text: string\n type: string\n }>\n }\n }\n >\n >\n /**\n * Disable the MCP plugin.\n */\n disabled?: boolean\n /**\n * Experimental features\n * **These features are for experimental purposes -- They are Disabled in Production by Default**\n */\n experimental?: {\n /**\n * These are MCP tools that can be used by a client to modify Payload.\n */\n tools: {\n /**\n * **Experimental** -- Auth MCP tools allow a client to change authentication priviliages for users. This is for developing ideas that help Admins with authentication tasks.\n */\n auth?: {\n /**\n * Enable the auth MCP tools. This allows Admins to enable or disable the auth capabilities.\n * @default false\n */\n enabled: boolean\n }\n /**\n * **Experimental** -- Collection MCP tools allow for the creation, modification, and deletion of Payload collections. This is for developing ideas that help Developers with collection tasks.\n */\n collections?: {\n /**\n * Set the directory path to the collections directory. This can be a directory outside of your default directory, or another Payload project.\n */\n collectionsDirPath: string\n /**\n * Enable the collection MCP tools. This allows Admins to enable or disable the Collection modification capabilities.\n * @default false\n */\n enabled: boolean\n }\n /**\n * **Experimental** -- Config MCP tools allow for the modification of a Payload Config. This is for developing ideas that help Developers with config tasks.\n */\n config?: {\n /**\n * Set the directory path to the config directory. This can be a directory outside of your default directory, or another Payload project.\n */\n configFilePath: string\n /**\n * Enable the config MCP tools. This allows Admins to enable or disable the Payload Config modification capabilities.\n * @default false\n */\n enabled: boolean\n }\n /**\n * **Experimental** -- Jobs MCP tools allow for the modification of Payload jobs. This is for developing ideas that help Developers with job tasks.\n */\n jobs?: {\n /**\n * Enable the jobs MCP tools. This allows Admins to enable or disable the Job modification capabilities.\n * @default false\n */\n enabled: boolean\n /**\n * Set the directory path to the jobs directory. This can be a directory outside of your default directory, or another Payload project.\n */\n jobsDirPath: string\n }\n }\n }\n /**\n * MCP Server options.\n */\n mcp?: {\n handlerOptions?: MCPHandlerOptions\n /**\n * Add custom MCP Prompts.\n */\n prompts?: {\n /**\n * Set the args schema of the prompt. This is the args schema that will be passed to the prompt. This is used by MCP clients to determine the arguments that will be passed to the prompt.\n */\n argsSchema: z.ZodRawShape\n /**\n * Set the description of the prompt. This is used by MCP clients to determine when to use the prompt.\n */\n description: string\n /**\n * Set the handler of the prompt. This is the function that will be called when the prompt is used.\n */\n handler: (\n args: Record<string, unknown>,\n req: PayloadRequest,\n _extra: unknown,\n ) =>\n | {\n messages: Array<{\n content: {\n text: string\n type: 'text'\n }\n role: 'assistant' | 'user'\n }>\n }\n | Promise<{\n messages: Array<{\n content: {\n text: string\n type: 'text'\n }\n role: 'assistant' | 'user'\n }>\n }>\n /**\n * Set the function name of the prompt.\n */\n name: string\n /**\n * Set the title of the prompt. LLMs will interperate the title to determine when to use the prompt.\n */\n title: string\n }[]\n\n /**\n * Add custom MCP Resource.\n */\n resources?: {\n /**\n * Set the description of the resource. This is used by MCP clients to determine when to use the resource.\n * example: 'Data is a resource that contains special data.'\n */\n description: string\n /**\n * Set the handler of the resource. This is the function that will be called when the resource is used.\n * The handler can have either 3 arguments (when no args are passed) or 4 arguments (when args are passed).\n */\n handler: (...args: any[]) =>\n | {\n contents: Array<{\n text: string\n uri: string\n }>\n }\n | Promise<{\n contents: Array<{\n text: string\n uri: string\n }>\n }>\n /**\n * Set the mime type of the resource.\n * example: 'text/plain'\n */\n mimeType: string\n /**\n * Set the function name of the resource.\n * example: 'data'\n */\n name: string\n /**\n * Set the title of the resource. LLMs will interperate the title to determine when to use the resource.\n * example: 'Data'\n */\n title: string\n /**\n * Set the uri of the resource.\n * example: 'data://app'\n */\n uri: ResourceTemplate | string\n }[]\n serverOptions?: MCPServerOptions\n /**\n * Add custom MCP Tools.\n */\n tools?: {\n /**\n * Set the description of the tool. This is used by MCP clients to determine when to use the tool.\n */\n description: string\n /**\n * Set the handler of the tool. This is the function that will be called when the tool is used.\n */\n handler: (\n args: Record<string, unknown>,\n req: PayloadRequest,\n _extra: unknown,\n ) =>\n | {\n content: Array<{\n text: string\n type: 'text'\n }>\n role?: string\n }\n | Promise<{\n content: Array<{\n text: string\n type: 'text'\n }>\n role?: string\n }>\n /**\n * Set the name of the tool. This is the name that will be used to identify the tool. LLMs will interperate the name to determine when to use the tool.\n */\n name: string\n /**\n * Set the parameters of the tool. This is the parameters that will be passed to the tool.\n */\n parameters: z.ZodRawShape\n }[]\n }\n\n /**\n * Override the API key collection.\n * This allows you to add fields to the API key collection or modify the collection in any way you want.\n * @param collection - The API key collection.\n * @returns The modified API key collection.\n */\n overrideApiKeyCollection?: (collection: CollectionConfig) => CollectionConfig\n\n /**\n * Override the authentication method.\n * This allows you to use a custom authentication method instead of the default API key authentication.\n * @param req - The request object.\n * @returns The MCP access settings.\n */\n overrideAuth?: (\n req: PayloadRequest,\n getDefaultMcpAccessSettings: (overrideApiKey?: null | string) => Promise<MCPAccessSettings>,\n ) => MCPAccessSettings | Promise<MCPAccessSettings>\n\n /**\n * Set the users collection that API keys should be associated with.\n */\n userCollection?: CollectionConfig | string\n}\n\n/**\n * MCP Handler options.\n */\nexport type MCPHandlerOptions = {\n /**\n * Set the base path of the MCP handler. This is the path that will be used to access the MCP handler.\n * @default /api\n */\n basePath?: string\n /**\n * Set the maximum duration of the MCP handler. This is the maximum duration that the MCP handler will run for.\n * @default 60\n */\n maxDuration?: number\n /**\n * Set the Redis URL for the MCP handler. This is the URL that will be used to access the Redis server.\n * @default process.env.REDIS_URL\n * INFO: Disabled until developer clarity is reached for server side streaming and we have an auth pattern for all SSE patterns\n */\n // redisUrl?: string\n /**\n * Set verbose logging.\n * @default false\n */\n verboseLogs?: boolean\n}\n\n/**\n * MCP Server options.\n */\nexport type MCPServerOptions = {\n /**\n * Set the server info of the MCP server.\n */\n serverInfo?: {\n /**\n * Set the name of the MCP server.\n * @default 'Payload MCP Server'\n */\n name: string\n /**\n * Set the version of the MCP server.\n * @default '1.0.0'\n */\n version: string\n }\n}\n\nexport type MCPAccessSettings = {\n auth?: {\n auth?: boolean\n forgotPassword?: boolean\n login?: boolean\n resetPassword?: boolean\n unlock?: boolean\n verify?: boolean\n }\n collections?: {\n create?: boolean\n delete?: boolean\n find?: boolean\n update?: boolean\n }\n config?: {\n find?: boolean\n update?: boolean\n }\n jobs?: {\n create?: boolean\n run?: boolean\n update?: boolean\n }\n 'payload-mcp-prompt'?: Record<string, boolean>\n 'payload-mcp-resource'?: Record<string, boolean>\n 'payload-mcp-tool'?: Record<string, boolean>\n user: TypedUser\n} & Record<string, unknown>\n\nexport type FieldDefinition = {\n description?: string\n name: string\n options?: { label: string; value: string }[]\n position?: 'main' | 'sidebar'\n required?: boolean\n type: string\n}\n\nexport type FieldModification = {\n changes: {\n description?: string\n options?: { label: string; value: string }[]\n position?: 'main' | 'sidebar'\n required?: boolean\n type?: string\n }\n fieldName: string\n}\n\nexport type CollectionConfigUpdates = {\n access?: {\n create?: string\n delete?: string\n read?: string\n update?: string\n }\n description?: string\n slug?: string\n timestamps?: boolean\n versioning?: boolean\n}\n\nexport type AdminConfig = {\n avatar?: string\n css?: string\n dateFormat?: string\n inactivityRoute?: string\n livePreview?: {\n breakpoints?: Array<{\n height: number\n label: string\n name: string\n width: number\n }>\n }\n logoutRoute?: string\n meta?: {\n favicon?: string\n ogImage?: string\n titleSuffix?: string\n }\n user?: string\n}\n\nexport type DatabaseConfig = {\n connectOptions?: string\n type?: 'mongodb' | 'postgres'\n url?: string\n}\n\nexport type PluginUpdates = {\n add?: string[]\n remove?: string[]\n}\n\nexport type GeneralConfig = {\n cookiePrefix?: string\n cors?: string\n csrf?: string\n graphQL?: {\n disable?: boolean\n schemaOutputFile?: string\n }\n rateLimit?: {\n max?: number\n skip?: string\n window?: number\n }\n secret?: string\n serverURL?: string\n typescript?: {\n declare?: boolean\n outputFile?: string\n }\n}\n\nexport interface SchemaField {\n description?: string\n name: string\n options?: string[]\n required?: boolean\n type: string\n}\n\nexport interface TaskSequenceItem {\n description?: string\n retries?: number\n taskId: string\n taskSlug: string\n timeout?: number\n}\n\nexport interface JobConfigUpdate {\n description?: string\n queue?: string\n retries?: number\n timeout?: number\n}\n"],"names":[],"mappings":"AAidA,WAKC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"convertCollectionSchemaToZod.d.ts","sourceRoot":"","sources":["../../src/utils/convertCollectionSchemaToZod.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAM9C,eAAO,MAAM,4BAA4B,WAAY,WAAW,
|
|
1
|
+
{"version":3,"file":"convertCollectionSchemaToZod.d.ts","sourceRoot":"","sources":["../../src/utils/convertCollectionSchemaToZod.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAM9C,eAAO,MAAM,4BAA4B,WAAY,WAAW,QA2B/D,CAAA"}
|
|
@@ -23,8 +23,7 @@ export const convertCollectionSchemaToZod = (schema)=>{
|
|
|
23
23
|
* 4. The resulting Zod schema is used only for parameter validation in MCP tools, not for data processing
|
|
24
24
|
* 5. No user input or external data is involved in the schema generation process
|
|
25
25
|
*/ // eslint-disable-next-line @typescript-eslint/no-implied-eval
|
|
26
|
-
|
|
27
|
-
return zodSchema;
|
|
26
|
+
return new Function('z', `return ${transpileResult.outputText}`)(z);
|
|
28
27
|
};
|
|
29
28
|
|
|
30
29
|
//# sourceMappingURL=convertCollectionSchemaToZod.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/utils/convertCollectionSchemaToZod.ts"],"sourcesContent":["import type { JSONSchema4 } from 'json-schema'\n\nimport { jsonSchemaToZod } from 'json-schema-to-zod'\nimport * as ts from 'typescript'\nimport { z } from 'zod'\n\nexport const convertCollectionSchemaToZod = (schema: JSONSchema4) => {\n // Remove properties that should not be included in the Zod schema\n delete schema?.properties?.createdAt\n delete schema?.properties?.updatedAt\n\n const zodSchemaAsString = jsonSchemaToZod(schema)\n\n // Transpile TypeScript to JavaScript\n const transpileResult = ts.transpileModule(zodSchemaAsString, {\n compilerOptions: {\n module: ts.ModuleKind.CommonJS,\n removeComments: true,\n strict: false,\n target: ts.ScriptTarget.ES2018,\n },\n })\n\n /**\n * This Function evaluation is safe because:\n * 1. The input schema comes from Payload's collection configuration, which is controlled by the application developer\n * 2. The jsonSchemaToZod library converts JSON Schema to Zod schema definitions, producing only type validation code\n * 3. The transpiled output contains only Zod schema definitions (z.string(), z.number(), etc.) - no executable logic\n * 4. The resulting Zod schema is used only for parameter validation in MCP tools, not for data processing\n * 5. No user input or external data is involved in the schema generation process\n */\n // eslint-disable-next-line @typescript-eslint/no-implied-eval\n
|
|
1
|
+
{"version":3,"sources":["../../src/utils/convertCollectionSchemaToZod.ts"],"sourcesContent":["import type { JSONSchema4 } from 'json-schema'\n\nimport { jsonSchemaToZod } from 'json-schema-to-zod'\nimport * as ts from 'typescript'\nimport { z } from 'zod'\n\nexport const convertCollectionSchemaToZod = (schema: JSONSchema4) => {\n // Remove properties that should not be included in the Zod schema\n delete schema?.properties?.createdAt\n delete schema?.properties?.updatedAt\n\n const zodSchemaAsString = jsonSchemaToZod(schema)\n\n // Transpile TypeScript to JavaScript\n const transpileResult = ts.transpileModule(zodSchemaAsString, {\n compilerOptions: {\n module: ts.ModuleKind.CommonJS,\n removeComments: true,\n strict: false,\n target: ts.ScriptTarget.ES2018,\n },\n })\n\n /**\n * This Function evaluation is safe because:\n * 1. The input schema comes from Payload's collection configuration, which is controlled by the application developer\n * 2. The jsonSchemaToZod library converts JSON Schema to Zod schema definitions, producing only type validation code\n * 3. The transpiled output contains only Zod schema definitions (z.string(), z.number(), etc.) - no executable logic\n * 4. The resulting Zod schema is used only for parameter validation in MCP tools, not for data processing\n * 5. No user input or external data is involved in the schema generation process\n */\n // eslint-disable-next-line @typescript-eslint/no-implied-eval\n return new Function('z', `return ${transpileResult.outputText}`)(z)\n}\n"],"names":["jsonSchemaToZod","ts","z","convertCollectionSchemaToZod","schema","properties","createdAt","updatedAt","zodSchemaAsString","transpileResult","transpileModule","compilerOptions","module","ModuleKind","CommonJS","removeComments","strict","target","ScriptTarget","ES2018","Function","outputText"],"mappings":"AAEA,SAASA,eAAe,QAAQ,qBAAoB;AACpD,YAAYC,QAAQ,aAAY;AAChC,SAASC,CAAC,QAAQ,MAAK;AAEvB,OAAO,MAAMC,+BAA+B,CAACC;IAC3C,kEAAkE;IAClE,OAAOA,QAAQC,YAAYC;IAC3B,OAAOF,QAAQC,YAAYE;IAE3B,MAAMC,oBAAoBR,gBAAgBI;IAE1C,qCAAqC;IACrC,MAAMK,kBAAkBR,GAAGS,eAAe,CAACF,mBAAmB;QAC5DG,iBAAiB;YACfC,QAAQX,GAAGY,UAAU,CAACC,QAAQ;YAC9BC,gBAAgB;YAChBC,QAAQ;YACRC,QAAQhB,GAAGiB,YAAY,CAACC,MAAM;QAChC;IACF;IAEA;;;;;;;GAOC,GACD,8DAA8D;IAC9D,OAAO,IAAIC,SAAS,KAAK,CAAC,OAAO,EAAEX,gBAAgBY,UAAU,EAAE,EAAEnB;AACnE,EAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@payloadcms/plugin-mcp",
|
|
3
|
-
"version": "3.65.0-internal.
|
|
3
|
+
"version": "3.65.0-internal.ef335bd",
|
|
4
4
|
"description": "MCP (Model Context Protocol) capabilities with Payload",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"plugin",
|
|
@@ -45,10 +45,10 @@
|
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
47
|
"@payloadcms/eslint-config": "3.28.0",
|
|
48
|
-
"payload": "3.65.0-internal.
|
|
48
|
+
"payload": "3.65.0-internal.ef335bd"
|
|
49
49
|
},
|
|
50
50
|
"peerDependencies": {
|
|
51
|
-
"payload": "3.65.0-internal.
|
|
51
|
+
"payload": "3.65.0-internal.ef335bd"
|
|
52
52
|
},
|
|
53
53
|
"homepage:": "https://payloadcms.com",
|
|
54
54
|
"scripts": {
|
package/src/endpoints/mcp.ts
CHANGED
|
@@ -57,7 +57,7 @@ export const initializeMCPHandler = (pluginOptions: PluginMCPServerConfig) => {
|
|
|
57
57
|
payload.logger.info('[payload-mcp] API Key is valid')
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
-
return docs[0] as MCPAccessSettings
|
|
60
|
+
return docs[0] as unknown as MCPAccessSettings
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
const mcpAccessSettings = pluginOptions.overrideAuth
|
package/src/mcp/getMcpHandler.ts
CHANGED
|
@@ -43,8 +43,29 @@ export const getMCPHandler = (
|
|
|
43
43
|
const { payload } = req
|
|
44
44
|
const configSchema = configToJSONSchema(payload.config)
|
|
45
45
|
|
|
46
|
+
// Handler wrapper that injects req before the _extra argument
|
|
47
|
+
const wrapHandler = (handler: (...args: any[]) => any) => {
|
|
48
|
+
return async (...args: any[]) => {
|
|
49
|
+
const _extra = args[args.length - 1]
|
|
50
|
+
const handlerArgs = args.slice(0, -1)
|
|
51
|
+
return await handler(...handlerArgs, req, _extra)
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const payloadToolHandler = (
|
|
56
|
+
handler: NonNullable<NonNullable<PluginMCPServerConfig['mcp']>['tools']>[number]['handler'],
|
|
57
|
+
) => wrapHandler(handler)
|
|
58
|
+
|
|
59
|
+
const payloadPromptHandler = (
|
|
60
|
+
handler: NonNullable<NonNullable<PluginMCPServerConfig['mcp']>['prompts']>[number]['handler'],
|
|
61
|
+
) => wrapHandler(handler)
|
|
62
|
+
|
|
63
|
+
const payloadResourceHandler = (
|
|
64
|
+
handler: NonNullable<NonNullable<PluginMCPServerConfig['mcp']>['resources']>[number]['handler'],
|
|
65
|
+
) => wrapHandler(handler)
|
|
66
|
+
|
|
46
67
|
// User
|
|
47
|
-
const user = mcpAccessSettings.user
|
|
68
|
+
const user = mcpAccessSettings.user
|
|
48
69
|
|
|
49
70
|
// MCP Server and Handler Options
|
|
50
71
|
const MCPOptions = pluginOptions.mcp || {}
|
|
@@ -202,7 +223,13 @@ export const getMCPHandler = (
|
|
|
202
223
|
registerTool(
|
|
203
224
|
isToolEnabled,
|
|
204
225
|
tool.name,
|
|
205
|
-
() =>
|
|
226
|
+
() =>
|
|
227
|
+
server.tool(
|
|
228
|
+
tool.name,
|
|
229
|
+
tool.description,
|
|
230
|
+
tool.parameters,
|
|
231
|
+
payloadToolHandler(tool.handler),
|
|
232
|
+
),
|
|
206
233
|
payload,
|
|
207
234
|
useVerboseLogs,
|
|
208
235
|
)
|
|
@@ -222,7 +249,7 @@ export const getMCPHandler = (
|
|
|
222
249
|
description: prompt.description,
|
|
223
250
|
title: prompt.title,
|
|
224
251
|
},
|
|
225
|
-
prompt.handler,
|
|
252
|
+
payloadPromptHandler(prompt.handler),
|
|
226
253
|
)
|
|
227
254
|
if (useVerboseLogs) {
|
|
228
255
|
payload.logger.info(`[payload-mcp] ✅ Prompt: ${prompt.title} Registered.`)
|
|
@@ -248,7 +275,7 @@ export const getMCPHandler = (
|
|
|
248
275
|
mimeType: resource.mimeType,
|
|
249
276
|
title: resource.title,
|
|
250
277
|
},
|
|
251
|
-
resource.handler,
|
|
278
|
+
payloadResourceHandler(resource.handler),
|
|
252
279
|
)
|
|
253
280
|
|
|
254
281
|
if (useVerboseLogs) {
|
|
@@ -202,14 +202,14 @@ function getWorkflowConfig(importedModule: Record<string, unknown>): undefined |
|
|
|
202
202
|
* Validate collection configuration structure
|
|
203
203
|
*/
|
|
204
204
|
function validateCollectionConfig(config: CollectionConfig): ValidationResult<CollectionConfig> {
|
|
205
|
-
if (!config
|
|
205
|
+
if (!config) {
|
|
206
206
|
return {
|
|
207
207
|
error: 'Collection config is not a valid object',
|
|
208
208
|
success: false,
|
|
209
209
|
}
|
|
210
210
|
}
|
|
211
211
|
|
|
212
|
-
if (!config.slug
|
|
212
|
+
if (!config.slug) {
|
|
213
213
|
return {
|
|
214
214
|
error: 'Collection config must have a valid slug property',
|
|
215
215
|
success: false,
|
|
@@ -220,7 +220,7 @@ function validateCollectionConfig(config: CollectionConfig): ValidationResult<Co
|
|
|
220
220
|
if (config.fields) {
|
|
221
221
|
for (let i = 0; i < config.fields.length; i++) {
|
|
222
222
|
const field = config.fields[i] as Record<string, unknown>
|
|
223
|
-
if (!field
|
|
223
|
+
if (!field) {
|
|
224
224
|
return {
|
|
225
225
|
error: `Field at index ${i} is not a valid object`,
|
|
226
226
|
success: false,
|
|
@@ -228,7 +228,7 @@ function validateCollectionConfig(config: CollectionConfig): ValidationResult<Co
|
|
|
228
228
|
}
|
|
229
229
|
|
|
230
230
|
// Check if field has type property
|
|
231
|
-
if ('type' in field && field.type
|
|
231
|
+
if ('type' in field && field.type) {
|
|
232
232
|
return {
|
|
233
233
|
error: `Field at index ${i} has invalid type property`,
|
|
234
234
|
success: false,
|
|
@@ -244,21 +244,21 @@ function validateCollectionConfig(config: CollectionConfig): ValidationResult<Co
|
|
|
244
244
|
* Validate task configuration structure
|
|
245
245
|
*/
|
|
246
246
|
function validateTaskConfig(config: TaskConfig): ValidationResult<TaskConfig> {
|
|
247
|
-
if (!config
|
|
247
|
+
if (!config) {
|
|
248
248
|
return {
|
|
249
249
|
error: 'Task config is not a valid object',
|
|
250
250
|
success: false,
|
|
251
251
|
}
|
|
252
252
|
}
|
|
253
253
|
|
|
254
|
-
if (!config.slug
|
|
254
|
+
if (!config.slug) {
|
|
255
255
|
return {
|
|
256
256
|
error: 'Task config must have a valid slug property',
|
|
257
257
|
success: false,
|
|
258
258
|
}
|
|
259
259
|
}
|
|
260
260
|
|
|
261
|
-
if (!config.handler
|
|
261
|
+
if (!config.handler) {
|
|
262
262
|
return {
|
|
263
263
|
error: 'Task config must have a valid handler function',
|
|
264
264
|
success: false,
|
|
@@ -266,7 +266,7 @@ function validateTaskConfig(config: TaskConfig): ValidationResult<TaskConfig> {
|
|
|
266
266
|
}
|
|
267
267
|
|
|
268
268
|
// Validate optional properties
|
|
269
|
-
if (config.retries !== undefined &&
|
|
269
|
+
if (config.retries !== undefined && config.retries < 0) {
|
|
270
270
|
return {
|
|
271
271
|
error: 'Task config retries must be a non-negative number',
|
|
272
272
|
success: false,
|
|
@@ -277,21 +277,21 @@ function validateTaskConfig(config: TaskConfig): ValidationResult<TaskConfig> {
|
|
|
277
277
|
if (config.inputSchema && Array.isArray(config.inputSchema)) {
|
|
278
278
|
for (let i = 0; i < config.inputSchema.length; i++) {
|
|
279
279
|
const field = config.inputSchema[i]
|
|
280
|
-
if (!field
|
|
280
|
+
if (!field) {
|
|
281
281
|
return {
|
|
282
282
|
error: `Input schema field at index ${i} is not a valid object`,
|
|
283
283
|
success: false,
|
|
284
284
|
}
|
|
285
285
|
}
|
|
286
286
|
|
|
287
|
-
if (!field.name
|
|
287
|
+
if (!field.name) {
|
|
288
288
|
return {
|
|
289
289
|
error: `Input schema field at index ${i} must have a valid name property`,
|
|
290
290
|
success: false,
|
|
291
291
|
}
|
|
292
292
|
}
|
|
293
293
|
|
|
294
|
-
if (!field.type
|
|
294
|
+
if (!field.type) {
|
|
295
295
|
return {
|
|
296
296
|
error: `Input schema field at index ${i} must have a valid type property`,
|
|
297
297
|
success: false,
|
|
@@ -303,21 +303,21 @@ function validateTaskConfig(config: TaskConfig): ValidationResult<TaskConfig> {
|
|
|
303
303
|
if (config.outputSchema && Array.isArray(config.outputSchema)) {
|
|
304
304
|
for (let i = 0; i < config.outputSchema.length; i++) {
|
|
305
305
|
const field = config.outputSchema[i]
|
|
306
|
-
if (!field
|
|
306
|
+
if (!field) {
|
|
307
307
|
return {
|
|
308
308
|
error: `Output schema field at index ${i} is not a valid object`,
|
|
309
309
|
success: false,
|
|
310
310
|
}
|
|
311
311
|
}
|
|
312
312
|
|
|
313
|
-
if (!field.name
|
|
313
|
+
if (!field.name) {
|
|
314
314
|
return {
|
|
315
315
|
error: `Output schema field at index ${i} must have a valid name property`,
|
|
316
316
|
success: false,
|
|
317
317
|
}
|
|
318
318
|
}
|
|
319
319
|
|
|
320
|
-
if (!field.type
|
|
320
|
+
if (!field.type) {
|
|
321
321
|
return {
|
|
322
322
|
error: `Output schema field at index ${i} must have a valid type property`,
|
|
323
323
|
success: false,
|
|
@@ -333,21 +333,21 @@ function validateTaskConfig(config: TaskConfig): ValidationResult<TaskConfig> {
|
|
|
333
333
|
* Validate workflow configuration structure
|
|
334
334
|
*/
|
|
335
335
|
function validateWorkflowConfig(config: WorkflowConfig): ValidationResult<WorkflowConfig> {
|
|
336
|
-
if (!config
|
|
336
|
+
if (!config) {
|
|
337
337
|
return {
|
|
338
338
|
error: 'Workflow config is not a valid object',
|
|
339
339
|
success: false,
|
|
340
340
|
}
|
|
341
341
|
}
|
|
342
342
|
|
|
343
|
-
if (!config.slug
|
|
343
|
+
if (!config.slug) {
|
|
344
344
|
return {
|
|
345
345
|
error: 'Workflow config must have a valid slug property',
|
|
346
346
|
success: false,
|
|
347
347
|
}
|
|
348
348
|
}
|
|
349
349
|
|
|
350
|
-
if (!config.handler
|
|
350
|
+
if (!config.handler) {
|
|
351
351
|
return {
|
|
352
352
|
error: 'Workflow config must have a valid handler function',
|
|
353
353
|
success: false,
|
|
@@ -355,14 +355,14 @@ function validateWorkflowConfig(config: WorkflowConfig): ValidationResult<Workfl
|
|
|
355
355
|
}
|
|
356
356
|
|
|
357
357
|
// Validate optional properties
|
|
358
|
-
if (config.queue
|
|
358
|
+
if (config.queue) {
|
|
359
359
|
return {
|
|
360
360
|
error: 'Workflow config queue must be a string',
|
|
361
361
|
success: false,
|
|
362
362
|
}
|
|
363
363
|
}
|
|
364
364
|
|
|
365
|
-
if (config.retries !== undefined &&
|
|
365
|
+
if (config.retries !== undefined && config.retries < 0) {
|
|
366
366
|
return {
|
|
367
367
|
error: 'Workflow config retries must be a non-negative number',
|
|
368
368
|
success: false,
|
|
@@ -373,21 +373,21 @@ function validateWorkflowConfig(config: WorkflowConfig): ValidationResult<Workfl
|
|
|
373
373
|
if (config.inputSchema && Array.isArray(config.inputSchema)) {
|
|
374
374
|
for (let i = 0; i < config.inputSchema.length; i++) {
|
|
375
375
|
const field = config.inputSchema[i]
|
|
376
|
-
if (!field
|
|
376
|
+
if (!field) {
|
|
377
377
|
return {
|
|
378
378
|
error: `Input schema field at index ${i} is not a valid object`,
|
|
379
379
|
success: false,
|
|
380
380
|
}
|
|
381
381
|
}
|
|
382
382
|
|
|
383
|
-
if (!field.name
|
|
383
|
+
if (!field.name) {
|
|
384
384
|
return {
|
|
385
385
|
error: `Input schema field at index ${i} must have a valid name property`,
|
|
386
386
|
success: false,
|
|
387
387
|
}
|
|
388
388
|
}
|
|
389
389
|
|
|
390
|
-
if (!field.type
|
|
390
|
+
if (!field.type) {
|
|
391
391
|
return {
|
|
392
392
|
error: `Input schema field at index ${i} must have a valid type property`,
|
|
393
393
|
success: false,
|
package/src/types.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { CollectionConfig, CollectionSlug, PayloadRequest } from 'payload'
|
|
1
|
+
import type { CollectionConfig, CollectionSlug, PayloadRequest, TypedUser } from 'payload'
|
|
2
2
|
import type { z } from 'zod'
|
|
3
3
|
|
|
4
4
|
import { type ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js'
|
|
@@ -135,7 +135,29 @@ export type PluginMCPServerConfig = {
|
|
|
135
135
|
/**
|
|
136
136
|
* Set the handler of the prompt. This is the function that will be called when the prompt is used.
|
|
137
137
|
*/
|
|
138
|
-
handler: (
|
|
138
|
+
handler: (
|
|
139
|
+
args: Record<string, unknown>,
|
|
140
|
+
req: PayloadRequest,
|
|
141
|
+
_extra: unknown,
|
|
142
|
+
) =>
|
|
143
|
+
| {
|
|
144
|
+
messages: Array<{
|
|
145
|
+
content: {
|
|
146
|
+
text: string
|
|
147
|
+
type: 'text'
|
|
148
|
+
}
|
|
149
|
+
role: 'assistant' | 'user'
|
|
150
|
+
}>
|
|
151
|
+
}
|
|
152
|
+
| Promise<{
|
|
153
|
+
messages: Array<{
|
|
154
|
+
content: {
|
|
155
|
+
text: string
|
|
156
|
+
type: 'text'
|
|
157
|
+
}
|
|
158
|
+
role: 'assistant' | 'user'
|
|
159
|
+
}>
|
|
160
|
+
}>
|
|
139
161
|
/**
|
|
140
162
|
* Set the function name of the prompt.
|
|
141
163
|
*/
|
|
@@ -157,8 +179,21 @@ export type PluginMCPServerConfig = {
|
|
|
157
179
|
description: string
|
|
158
180
|
/**
|
|
159
181
|
* Set the handler of the resource. This is the function that will be called when the resource is used.
|
|
182
|
+
* The handler can have either 3 arguments (when no args are passed) or 4 arguments (when args are passed).
|
|
160
183
|
*/
|
|
161
|
-
handler: (...args: any) =>
|
|
184
|
+
handler: (...args: any[]) =>
|
|
185
|
+
| {
|
|
186
|
+
contents: Array<{
|
|
187
|
+
text: string
|
|
188
|
+
uri: string
|
|
189
|
+
}>
|
|
190
|
+
}
|
|
191
|
+
| Promise<{
|
|
192
|
+
contents: Array<{
|
|
193
|
+
text: string
|
|
194
|
+
uri: string
|
|
195
|
+
}>
|
|
196
|
+
}>
|
|
162
197
|
/**
|
|
163
198
|
* Set the mime type of the resource.
|
|
164
199
|
* example: 'text/plain'
|
|
@@ -192,12 +227,25 @@ export type PluginMCPServerConfig = {
|
|
|
192
227
|
/**
|
|
193
228
|
* Set the handler of the tool. This is the function that will be called when the tool is used.
|
|
194
229
|
*/
|
|
195
|
-
handler: (
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
230
|
+
handler: (
|
|
231
|
+
args: Record<string, unknown>,
|
|
232
|
+
req: PayloadRequest,
|
|
233
|
+
_extra: unknown,
|
|
234
|
+
) =>
|
|
235
|
+
| {
|
|
236
|
+
content: Array<{
|
|
237
|
+
text: string
|
|
238
|
+
type: 'text'
|
|
239
|
+
}>
|
|
240
|
+
role?: string
|
|
241
|
+
}
|
|
242
|
+
| Promise<{
|
|
243
|
+
content: Array<{
|
|
244
|
+
text: string
|
|
245
|
+
type: 'text'
|
|
246
|
+
}>
|
|
247
|
+
role?: string
|
|
248
|
+
}>
|
|
201
249
|
/**
|
|
202
250
|
* Set the name of the tool. This is the name that will be used to identify the tool. LLMs will interperate the name to determine when to use the tool.
|
|
203
251
|
*/
|
|
@@ -309,6 +357,7 @@ export type MCPAccessSettings = {
|
|
|
309
357
|
'payload-mcp-prompt'?: Record<string, boolean>
|
|
310
358
|
'payload-mcp-resource'?: Record<string, boolean>
|
|
311
359
|
'payload-mcp-tool'?: Record<string, boolean>
|
|
360
|
+
user: TypedUser
|
|
312
361
|
} & Record<string, unknown>
|
|
313
362
|
|
|
314
363
|
export type FieldDefinition = {
|
|
@@ -30,6 +30,5 @@ export const convertCollectionSchemaToZod = (schema: JSONSchema4) => {
|
|
|
30
30
|
* 5. No user input or external data is involved in the schema generation process
|
|
31
31
|
*/
|
|
32
32
|
// eslint-disable-next-line @typescript-eslint/no-implied-eval
|
|
33
|
-
|
|
34
|
-
return zodSchema
|
|
33
|
+
return new Function('z', `return ${transpileResult.outputText}`)(z)
|
|
35
34
|
}
|