@payloadcms/plugin-mcp 4.0.0-internal.e7d4ebc → 4.0.0-internal.ee5d8bd
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/bin.js +0 -7
- package/dist/endpoint/access.d.ts.map +1 -1
- package/dist/endpoint/access.js +17 -5
- package/dist/endpoint/access.js.map +1 -1
- package/dist/endpoint/index.d.ts.map +1 -1
- package/dist/endpoint/index.js +46 -4
- package/dist/endpoint/index.js.map +1 -1
- package/dist/endpoint/oauth.d.ts +39 -0
- package/dist/endpoint/oauth.d.ts.map +1 -0
- package/dist/endpoint/oauth.js +94 -0
- package/dist/endpoint/oauth.js.map +1 -0
- package/dist/endpoint/oauthLoginToken.d.ts +15 -0
- package/dist/endpoint/oauthLoginToken.d.ts.map +1 -0
- package/dist/endpoint/oauthLoginToken.js +45 -0
- package/dist/endpoint/oauthLoginToken.js.map +1 -0
- package/dist/endpoint/oauthServer.d.ts +12 -0
- package/dist/endpoint/oauthServer.d.ts.map +1 -0
- package/dist/endpoint/oauthServer.js +386 -0
- package/dist/endpoint/oauthServer.js.map +1 -0
- package/dist/index.d.ts +10 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +15 -2
- package/dist/index.js.map +1 -1
- package/dist/mcp/buildMcpServer.d.ts +2 -2
- package/dist/mcp/buildMcpServer.d.ts.map +1 -1
- package/dist/mcp/buildMcpServer.js +36 -24
- package/dist/mcp/buildMcpServer.js.map +1 -1
- package/dist/mcp/builtin/collections/authTools.d.ts.map +1 -1
- package/dist/mcp/builtin/collections/authTools.js +80 -56
- package/dist/mcp/builtin/collections/authTools.js.map +1 -1
- package/dist/mcp/builtin/collections/countTool.d.ts.map +1 -1
- package/dist/mcp/builtin/collections/countTool.js +9 -14
- package/dist/mcp/builtin/collections/countTool.js.map +1 -1
- package/dist/mcp/builtin/collections/countVersionsTool.d.ts.map +1 -1
- package/dist/mcp/builtin/collections/countVersionsTool.js +9 -13
- package/dist/mcp/builtin/collections/countVersionsTool.js.map +1 -1
- package/dist/mcp/builtin/collections/createTool.d.ts +1 -1
- package/dist/mcp/builtin/collections/createTool.d.ts.map +1 -1
- package/dist/mcp/builtin/collections/createTool.js +103 -62
- package/dist/mcp/builtin/collections/createTool.js.map +1 -1
- package/dist/mcp/builtin/collections/deleteTool.d.ts.map +1 -1
- package/dist/mcp/builtin/collections/deleteTool.js +44 -43
- package/dist/mcp/builtin/collections/deleteTool.js.map +1 -1
- package/dist/mcp/builtin/collections/duplicateTool.d.ts.map +1 -1
- package/dist/mcp/builtin/collections/duplicateTool.js +31 -37
- package/dist/mcp/builtin/collections/duplicateTool.js.map +1 -1
- package/dist/mcp/builtin/collections/fileInput.d.ts +21 -21
- package/dist/mcp/builtin/collections/fileInput.d.ts.map +1 -1
- package/dist/mcp/builtin/collections/fileInput.js +43 -72
- package/dist/mcp/builtin/collections/fileInput.js.map +1 -1
- package/dist/mcp/builtin/collections/findDistinctTool.d.ts.map +1 -1
- package/dist/mcp/builtin/collections/findDistinctTool.js +11 -26
- package/dist/mcp/builtin/collections/findDistinctTool.js.map +1 -1
- package/dist/mcp/builtin/collections/findTool.d.ts.map +1 -1
- package/dist/mcp/builtin/collections/findTool.js +28 -46
- package/dist/mcp/builtin/collections/findTool.js.map +1 -1
- package/dist/mcp/builtin/collections/findVersionByIDTool.d.ts.map +1 -1
- package/dist/mcp/builtin/collections/findVersionByIDTool.js +17 -26
- package/dist/mcp/builtin/collections/findVersionByIDTool.js.map +1 -1
- package/dist/mcp/builtin/collections/findVersionsTool.d.ts.map +1 -1
- package/dist/mcp/builtin/collections/findVersionsTool.js +16 -30
- package/dist/mcp/builtin/collections/findVersionsTool.js.map +1 -1
- package/dist/mcp/builtin/collections/getCollectionSchemaTool.d.ts.map +1 -1
- package/dist/mcp/builtin/collections/getCollectionSchemaTool.js +30 -14
- package/dist/mcp/builtin/collections/getCollectionSchemaTool.js.map +1 -1
- package/dist/mcp/builtin/collections/restoreVersionTool.d.ts.map +1 -1
- package/dist/mcp/builtin/collections/restoreVersionTool.js +14 -26
- package/dist/mcp/builtin/collections/restoreVersionTool.js.map +1 -1
- package/dist/mcp/builtin/collections/updateTool.d.ts.map +1 -1
- package/dist/mcp/builtin/collections/updateTool.js +56 -88
- package/dist/mcp/builtin/collections/updateTool.js.map +1 -1
- package/dist/mcp/builtin/collections/uploadInstructionsTool.js +13 -13
- package/dist/mcp/builtin/collections/uploadInstructionsTool.js.map +1 -1
- package/dist/mcp/builtin/formatEntityError.d.ts +16 -0
- package/dist/mcp/builtin/formatEntityError.d.ts.map +1 -0
- package/dist/mcp/builtin/formatEntityError.js +55 -0
- package/dist/mcp/builtin/formatEntityError.js.map +1 -0
- package/dist/mcp/builtin/getConfigInfoTool.d.ts.map +1 -1
- package/dist/mcp/builtin/getConfigInfoTool.js +3 -2
- package/dist/mcp/builtin/getConfigInfoTool.js.map +1 -1
- package/dist/mcp/builtin/globals/countVersionsTool.d.ts.map +1 -1
- package/dist/mcp/builtin/globals/countVersionsTool.js +9 -13
- package/dist/mcp/builtin/globals/countVersionsTool.js.map +1 -1
- package/dist/mcp/builtin/globals/findTool.d.ts.map +1 -1
- package/dist/mcp/builtin/globals/findTool.js +10 -16
- package/dist/mcp/builtin/globals/findTool.js.map +1 -1
- package/dist/mcp/builtin/globals/findVersionByIDTool.d.ts.map +1 -1
- package/dist/mcp/builtin/globals/findVersionByIDTool.js +13 -24
- package/dist/mcp/builtin/globals/findVersionByIDTool.js.map +1 -1
- package/dist/mcp/builtin/globals/findVersionsTool.d.ts.map +1 -1
- package/dist/mcp/builtin/globals/findVersionsTool.js +13 -29
- package/dist/mcp/builtin/globals/findVersionsTool.js.map +1 -1
- package/dist/mcp/builtin/globals/getGlobalSchemaTool.d.ts.map +1 -1
- package/dist/mcp/builtin/globals/getGlobalSchemaTool.js +29 -13
- package/dist/mcp/builtin/globals/getGlobalSchemaTool.js.map +1 -1
- package/dist/mcp/builtin/globals/restoreVersionTool.d.ts.map +1 -1
- package/dist/mcp/builtin/globals/restoreVersionTool.js +15 -22
- package/dist/mcp/builtin/globals/restoreVersionTool.js.map +1 -1
- package/dist/mcp/builtin/globals/updateTool.d.ts.map +1 -1
- package/dist/mcp/builtin/globals/updateTool.js +27 -36
- package/dist/mcp/builtin/globals/updateTool.js.map +1 -1
- package/dist/mcp/builtinTools.d.ts.map +1 -1
- package/dist/mcp/builtinTools.js +3 -3
- package/dist/mcp/builtinTools.js.map +1 -1
- package/dist/mcp/sanitizeMCPConfig.d.ts.map +1 -1
- package/dist/mcp/sanitizeMCPConfig.js +3 -0
- package/dist/mcp/sanitizeMCPConfig.js.map +1 -1
- package/dist/stdio.js +4 -3
- package/dist/stdio.js.map +1 -1
- package/dist/types.d.ts +95 -7
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/utils/toStandardSchema.js.map +1 -1
- package/package.json +23 -28
- package/src/endpoint/access.ts +14 -6
- package/src/endpoint/index.ts +41 -3
- package/src/endpoint/oauth.ts +92 -0
- package/src/endpoint/oauthLoginToken.ts +59 -0
- package/src/endpoint/oauthServer.ts +440 -0
- package/src/index.ts +40 -5
- package/src/mcp/buildMcpServer.ts +40 -30
- package/src/mcp/builtin/collections/authTools.ts +82 -71
- package/src/mcp/builtin/collections/countTool.ts +9 -21
- package/src/mcp/builtin/collections/countVersionsTool.ts +9 -18
- package/src/mcp/builtin/collections/createTool.ts +107 -85
- package/src/mcp/builtin/collections/deleteTool.ts +37 -65
- package/src/mcp/builtin/collections/duplicateTool.ts +36 -86
- package/src/mcp/builtin/collections/fileInput.spec.ts +2 -2
- package/src/mcp/builtin/collections/fileInput.ts +54 -81
- package/src/mcp/builtin/collections/findDistinctTool.ts +11 -63
- package/src/mcp/builtin/collections/findTool.ts +24 -106
- package/src/mcp/builtin/collections/findVersionByIDTool.ts +15 -58
- package/src/mcp/builtin/collections/findVersionsTool.ts +14 -85
- package/src/mcp/builtin/collections/getCollectionSchemaTool.ts +23 -12
- package/src/mcp/builtin/collections/restoreVersionTool.ts +15 -57
- package/src/mcp/builtin/collections/updateTool.ts +56 -110
- package/src/mcp/builtin/collections/uploadInstructionsTool.ts +15 -15
- package/src/mcp/builtin/formatEntityError.ts +77 -0
- package/src/mcp/builtin/getConfigInfoTool.ts +2 -1
- package/src/mcp/builtin/globals/countVersionsTool.ts +9 -17
- package/src/mcp/builtin/globals/findTool.ts +13 -52
- package/src/mcp/builtin/globals/findVersionByIDTool.ts +13 -52
- package/src/mcp/builtin/globals/findVersionsTool.ts +14 -92
- package/src/mcp/builtin/globals/getGlobalSchemaTool.ts +21 -11
- package/src/mcp/builtin/globals/restoreVersionTool.ts +14 -45
- package/src/mcp/builtin/globals/updateTool.ts +38 -61
- package/src/mcp/builtinTools.ts +2 -2
- package/src/mcp/sanitizeMCPConfig.ts +1 -0
- package/src/stdio.ts +2 -2
- package/src/types.ts +97 -7
- package/src/utils/toStandardSchema.ts +1 -1
- package/dist/mcp/builtin/collections/fileInput.spec.js +0 -86
- package/dist/mcp/builtin/collections/fileInput.spec.js.map +0 -1
- package/dist/mcp/builtin/collections/formatCollectionError.d.ts +0 -9
- package/dist/mcp/builtin/collections/formatCollectionError.d.ts.map +0 -1
- package/dist/mcp/builtin/collections/formatCollectionError.js +0 -60
- package/dist/mcp/builtin/collections/formatCollectionError.js.map +0 -1
- package/dist/mcp/builtin/validateEntityData.d.ts +0 -14
- package/dist/mcp/builtin/validateEntityData.d.ts.map +0 -1
- package/dist/mcp/builtin/validateEntityData.js +0 -82
- package/dist/mcp/builtin/validateEntityData.js.map +0 -1
- package/dist/utils/getVirtualFieldNames.d.ts +0 -14
- package/dist/utils/getVirtualFieldNames.d.ts.map +0 -1
- package/dist/utils/getVirtualFieldNames.js +0 -35
- package/dist/utils/getVirtualFieldNames.js.map +0 -1
- package/dist/utils/schemaConversion/filterFieldsByAccess.d.ts +0 -28
- package/dist/utils/schemaConversion/filterFieldsByAccess.d.ts.map +0 -1
- package/dist/utils/schemaConversion/filterFieldsByAccess.js +0 -71
- package/dist/utils/schemaConversion/filterFieldsByAccess.js.map +0 -1
- package/dist/utils/schemaConversion/getEntityInputSchema.d.ts +0 -13
- package/dist/utils/schemaConversion/getEntityInputSchema.d.ts.map +0 -1
- package/dist/utils/schemaConversion/getEntityInputSchema.js +0 -66
- package/dist/utils/schemaConversion/getEntityInputSchema.js.map +0 -1
- package/dist/utils/schemaConversion/sanitizeEntitySchema.d.ts +0 -10
- package/dist/utils/schemaConversion/sanitizeEntitySchema.d.ts.map +0 -1
- package/dist/utils/schemaConversion/sanitizeEntitySchema.js +0 -384
- package/dist/utils/schemaConversion/sanitizeEntitySchema.js.map +0 -1
- package/dist/utils/schemaConversion/sanitizeEntitySchema.spec.js +0 -133
- package/dist/utils/schemaConversion/sanitizeEntitySchema.spec.js.map +0 -1
- package/dist/utils/transformPointDataToPayload.d.ts +0 -7
- package/dist/utils/transformPointDataToPayload.d.ts.map +0 -1
- package/dist/utils/transformPointDataToPayload.js +0 -28
- package/dist/utils/transformPointDataToPayload.js.map +0 -1
- package/dist/utils/whereSchema.d.ts +0 -9
- package/dist/utils/whereSchema.d.ts.map +0 -1
- package/dist/utils/whereSchema.js +0 -13
- package/dist/utils/whereSchema.js.map +0 -1
- package/src/mcp/builtin/collections/formatCollectionError.ts +0 -84
- package/src/mcp/builtin/validateEntityData.ts +0 -132
- package/src/utils/getVirtualFieldNames.ts +0 -53
- package/src/utils/schemaConversion/filterFieldsByAccess.ts +0 -123
- package/src/utils/schemaConversion/getEntityInputSchema.ts +0 -96
- package/src/utils/schemaConversion/sanitizeEntitySchema.spec.ts +0 -96
- package/src/utils/schemaConversion/sanitizeEntitySchema.ts +0 -432
- package/src/utils/transformPointDataToPayload.ts +0 -40
- package/src/utils/whereSchema.ts +0 -24
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { getAccessResults } from 'payload'
|
|
1
|
+
import { getAccessResults, getGlobalInputSchema, getGlobalSchemaInputSchema } from 'payload'
|
|
2
|
+
import { getLLMInstructions } from 'payload/internal'
|
|
2
3
|
|
|
3
4
|
import { defaultAccess } from '../../../defaultAccess.js'
|
|
4
5
|
import { defineGlobalTool } from '../../../defineTool.js'
|
|
5
|
-
import { getGlobalInputSchema } from '../../../utils/schemaConversion/getEntityInputSchema.js'
|
|
6
6
|
|
|
7
7
|
export const getGlobalSchemaTool = defineGlobalTool({
|
|
8
8
|
access: (args) => {
|
|
9
|
-
const permissions = args.permissions?.globals?.[args.
|
|
9
|
+
const permissions = args.permissions?.globals?.[args.slug]
|
|
10
10
|
|
|
11
11
|
return defaultAccess(args) && Boolean(permissions?.update)
|
|
12
12
|
},
|
|
@@ -17,18 +17,19 @@ export const getGlobalSchemaTool = defineGlobalTool({
|
|
|
17
17
|
readOnlyHint: true,
|
|
18
18
|
title: 'Get Global Schema',
|
|
19
19
|
},
|
|
20
|
-
description: 'Get the input schema
|
|
21
|
-
|
|
20
|
+
description: 'Get the input schema and LLM instructions before updating a global.',
|
|
21
|
+
input: getGlobalSchemaInputSchema,
|
|
22
|
+
}).handler(async ({ slug, authorizedMCP, req }) => {
|
|
22
23
|
const permissions = authorizedMCP.overrideAccess
|
|
23
24
|
? null
|
|
24
|
-
: (await getAccessResults({ req })).globals?.[
|
|
25
|
+
: (await getAccessResults({ req })).globals?.[slug]
|
|
25
26
|
|
|
26
27
|
if (!authorizedMCP.overrideAccess && !permissions?.update) {
|
|
27
28
|
return {
|
|
28
29
|
content: [
|
|
29
30
|
{
|
|
30
31
|
type: 'text',
|
|
31
|
-
text: `Error: MCP access to "getGlobalSchema" is not enabled for global "${
|
|
32
|
+
text: `Error: MCP access to "getGlobalSchema" is not enabled for global "${slug}"`,
|
|
32
33
|
},
|
|
33
34
|
],
|
|
34
35
|
isError: true,
|
|
@@ -36,28 +37,37 @@ export const getGlobalSchemaTool = defineGlobalTool({
|
|
|
36
37
|
}
|
|
37
38
|
|
|
38
39
|
const inputSchema = getGlobalInputSchema({
|
|
39
|
-
globalSlug,
|
|
40
|
+
globalSlug: slug,
|
|
40
41
|
req,
|
|
41
42
|
...(permissions ? { permissions } : {}),
|
|
42
43
|
})
|
|
43
44
|
|
|
44
45
|
if (!inputSchema) {
|
|
45
46
|
return {
|
|
46
|
-
content: [{ type: 'text', text: `Error: Global "${
|
|
47
|
+
content: [{ type: 'text', text: `Error: Global "${slug}" not found` }],
|
|
47
48
|
isError: true,
|
|
48
49
|
}
|
|
49
50
|
}
|
|
50
51
|
|
|
52
|
+
const instructions = await getLLMInstructions({
|
|
53
|
+
slug,
|
|
54
|
+
type: 'global',
|
|
55
|
+
overrideAccess: authorizedMCP.overrideAccess,
|
|
56
|
+
req,
|
|
57
|
+
})
|
|
58
|
+
|
|
51
59
|
return {
|
|
52
60
|
content: [
|
|
53
61
|
{
|
|
54
62
|
type: 'text',
|
|
55
|
-
text: `Schema for global "${
|
|
63
|
+
text: `Schema for global "${slug}":\n\`\`\`json\n${JSON.stringify(inputSchema)}\n\`\`\``,
|
|
56
64
|
},
|
|
65
|
+
...(instructions ? [{ type: 'text' as const, text: instructions }] : []),
|
|
57
66
|
],
|
|
58
67
|
structuredContent: {
|
|
59
|
-
|
|
68
|
+
slug,
|
|
60
69
|
schema: inputSchema,
|
|
70
|
+
...(instructions ? { instructions } : {}),
|
|
61
71
|
},
|
|
62
72
|
}
|
|
63
73
|
})
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
import { z } from 'zod'
|
|
1
|
+
import { restoreGlobalVersionInputSchema } from 'payload'
|
|
4
2
|
|
|
5
3
|
import { defaultAccess } from '../../../defaultAccess.js'
|
|
6
4
|
import { defineGlobalTool } from '../../../defineTool.js'
|
|
@@ -10,8 +8,7 @@ const DEFAULT_DESCRIPTION =
|
|
|
10
8
|
'Restore a global from a previous version in any version-enabled global.'
|
|
11
9
|
|
|
12
10
|
export const restoreGlobalVersionTool = defineGlobalTool({
|
|
13
|
-
access: (args) =>
|
|
14
|
-
defaultAccess(args) && Boolean(args.permissions?.globals?.[args.globalSlug]?.update),
|
|
11
|
+
access: (args) => defaultAccess(args) && Boolean(args.permissions?.globals?.[args.slug]?.update),
|
|
15
12
|
annotations: {
|
|
16
13
|
destructiveHint: true,
|
|
17
14
|
idempotentHint: false,
|
|
@@ -20,53 +17,25 @@ export const restoreGlobalVersionTool = defineGlobalTool({
|
|
|
20
17
|
title: 'Restore Global Version',
|
|
21
18
|
},
|
|
22
19
|
description: DEFAULT_DESCRIPTION,
|
|
23
|
-
input:
|
|
24
|
-
|
|
25
|
-
depth: z
|
|
26
|
-
.number()
|
|
27
|
-
.int()
|
|
28
|
-
.min(0)
|
|
29
|
-
.max(10)
|
|
30
|
-
.describe('How many levels deep to populate relationships in response')
|
|
31
|
-
.optional()
|
|
32
|
-
.default(0),
|
|
33
|
-
fallbackLocale: z
|
|
34
|
-
.string()
|
|
35
|
-
.describe('Optional: fallback locale code to use when requested locale is not available')
|
|
36
|
-
.optional(),
|
|
37
|
-
locale: z
|
|
38
|
-
.string()
|
|
39
|
-
.describe('Optional: locale code to restore in (e.g., "en", "es")')
|
|
40
|
-
.optional(),
|
|
41
|
-
populate: z
|
|
42
|
-
.record(z.string(), z.unknown())
|
|
43
|
-
.describe(
|
|
44
|
-
'Optional: control which fields to include from populated relationship or upload documents.',
|
|
45
|
-
)
|
|
46
|
-
.optional(),
|
|
47
|
-
showHiddenFields: z
|
|
48
|
-
.boolean()
|
|
49
|
-
.describe('Optional: include hidden fields in the restored global response')
|
|
50
|
-
.optional(),
|
|
51
|
-
}),
|
|
52
|
-
}).handler(async ({ authorizedMCP, globalSlug, input, req }) => {
|
|
20
|
+
input: restoreGlobalVersionInputSchema,
|
|
21
|
+
}).handler(async ({ slug, authorizedMCP, input, req }) => {
|
|
53
22
|
const payload = req.payload
|
|
54
23
|
const logger = getLogger({ payload })
|
|
55
|
-
const { id, depth, fallbackLocale, locale, populate,
|
|
24
|
+
const { id, depth, fallbackLocale, locale, populate, select } = input
|
|
56
25
|
|
|
57
|
-
logger.info(`Restoring version for global: ${
|
|
26
|
+
logger.info(`Restoring version for global: ${slug} with ID: ${id}`)
|
|
58
27
|
|
|
59
28
|
try {
|
|
60
29
|
const result = await payload.restoreGlobalVersion({
|
|
61
|
-
id,
|
|
62
|
-
slug
|
|
30
|
+
id: String(id),
|
|
31
|
+
slug,
|
|
63
32
|
depth,
|
|
64
33
|
overrideAccess: authorizedMCP.overrideAccess,
|
|
65
34
|
req,
|
|
66
|
-
...(fallbackLocale ? { fallbackLocale } : {}),
|
|
35
|
+
...(fallbackLocale !== undefined ? { fallbackLocale } : {}),
|
|
67
36
|
...(locale ? { locale } : {}),
|
|
68
|
-
...(populate ? { populate
|
|
69
|
-
...(
|
|
37
|
+
...(populate ? { populate } : {}),
|
|
38
|
+
...(select ? { select } : {}),
|
|
70
39
|
})
|
|
71
40
|
const resultObject = result as Record<string, unknown>
|
|
72
41
|
const restoredGlobal =
|
|
@@ -78,19 +47,19 @@ export const restoreGlobalVersionTool = defineGlobalTool({
|
|
|
78
47
|
content: [
|
|
79
48
|
{
|
|
80
49
|
type: 'text',
|
|
81
|
-
text: `Version "${id}" restored successfully for global "${
|
|
50
|
+
text: `Version "${id}" restored successfully for global "${slug}"!\nRestored global:\n\`\`\`json\n${JSON.stringify(restoredGlobal)}\n\`\`\``,
|
|
82
51
|
},
|
|
83
52
|
],
|
|
84
53
|
doc: restoredGlobal,
|
|
85
54
|
}
|
|
86
55
|
} catch (error) {
|
|
87
56
|
const errorMessage = error instanceof Error ? error.message : 'Unknown error'
|
|
88
|
-
logger.error(`Error restoring version ${id} for global ${
|
|
57
|
+
logger.error(`Error restoring version ${id} for global ${slug}: ${errorMessage}`)
|
|
89
58
|
return {
|
|
90
59
|
content: [
|
|
91
60
|
{
|
|
92
61
|
type: 'text',
|
|
93
|
-
text: `❌ **Error restoring version "${id}" for global "${
|
|
62
|
+
text: `❌ **Error restoring version "${id}" for global "${slug}":** ${errorMessage}`,
|
|
94
63
|
},
|
|
95
64
|
],
|
|
96
65
|
isError: true,
|
|
@@ -1,22 +1,20 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import {
|
|
2
|
+
getGlobalVirtualFieldNames,
|
|
3
|
+
stripVirtualFields,
|
|
4
|
+
transformPointDataToPayload,
|
|
5
|
+
updateGlobalInputSchema,
|
|
6
|
+
validateGlobalData,
|
|
7
|
+
} from 'payload'
|
|
4
8
|
|
|
5
9
|
import { defaultAccess } from '../../../defaultAccess.js'
|
|
6
10
|
import { defineGlobalTool } from '../../../defineTool.js'
|
|
7
11
|
import { getLogger } from '../../../utils/getLogger.js'
|
|
8
|
-
import {
|
|
9
|
-
getGlobalVirtualFieldNames,
|
|
10
|
-
stripVirtualFields,
|
|
11
|
-
} from '../../../utils/getVirtualFieldNames.js'
|
|
12
|
-
import { transformPointDataToPayload } from '../../../utils/transformPointDataToPayload.js'
|
|
13
|
-
import { validateGlobalData } from '../validateEntityData.js'
|
|
12
|
+
import { formatEntityError } from '../formatEntityError.js'
|
|
14
13
|
|
|
15
14
|
const DEFAULT_DESCRIPTION = 'Update any Payload global by passing the global slug and data.'
|
|
16
15
|
|
|
17
16
|
export const updateGlobalTool = defineGlobalTool({
|
|
18
|
-
access: (args) =>
|
|
19
|
-
defaultAccess(args) && Boolean(args.permissions?.globals?.[args.globalSlug]?.update),
|
|
17
|
+
access: (args) => defaultAccess(args) && Boolean(args.permissions?.globals?.[args.slug]?.update),
|
|
20
18
|
annotations: {
|
|
21
19
|
destructiveHint: true,
|
|
22
20
|
idempotentHint: false,
|
|
@@ -25,73 +23,54 @@ export const updateGlobalTool = defineGlobalTool({
|
|
|
25
23
|
title: 'Update Global',
|
|
26
24
|
},
|
|
27
25
|
description: DEFAULT_DESCRIPTION,
|
|
28
|
-
input:
|
|
29
|
-
|
|
30
|
-
depth: z
|
|
31
|
-
.number()
|
|
32
|
-
.describe('Optional: Depth of relationships to populate')
|
|
33
|
-
.optional()
|
|
34
|
-
.default(0),
|
|
35
|
-
draft: z
|
|
36
|
-
.boolean()
|
|
37
|
-
.describe('Optional: Whether to save as draft (default: false)')
|
|
38
|
-
.optional()
|
|
39
|
-
.default(false),
|
|
40
|
-
fallbackLocale: z
|
|
41
|
-
.string()
|
|
42
|
-
.describe('Optional: fallback locale code to use when requested locale is not available')
|
|
43
|
-
.optional(),
|
|
44
|
-
locale: z
|
|
45
|
-
.string()
|
|
46
|
-
.describe(
|
|
47
|
-
'Optional: locale code to update data in (e.g., "en", "es"). Use "all" to update all locales for localized fields',
|
|
48
|
-
)
|
|
49
|
-
.optional(),
|
|
50
|
-
select: z
|
|
51
|
-
.record(z.string(), z.unknown())
|
|
52
|
-
.describe(
|
|
53
|
-
'Optional: define exactly which fields you\'d like to return in the response, e.g., {"siteName": true}',
|
|
54
|
-
)
|
|
55
|
-
.optional(),
|
|
56
|
-
}),
|
|
57
|
-
}).handler(async ({ authorizedMCP, globalSlug, input, req }) => {
|
|
26
|
+
input: updateGlobalInputSchema,
|
|
27
|
+
}).handler(async ({ slug, authorizedMCP, input, req }) => {
|
|
58
28
|
const payload = req.payload
|
|
59
29
|
const logger = getLogger({ payload })
|
|
60
30
|
|
|
61
|
-
const {
|
|
31
|
+
const {
|
|
32
|
+
data,
|
|
33
|
+
depth,
|
|
34
|
+
draft,
|
|
35
|
+
fallbackLocale,
|
|
36
|
+
locale,
|
|
37
|
+
overrideLock,
|
|
38
|
+
populate,
|
|
39
|
+
publishAllLocales,
|
|
40
|
+
select,
|
|
41
|
+
unpublishAllLocales,
|
|
42
|
+
} = input
|
|
62
43
|
|
|
63
|
-
logger.info(
|
|
64
|
-
`Updating global: ${globalSlug}, draft: ${draft}${locale ? `, locale: ${locale}` : ''}`,
|
|
65
|
-
)
|
|
44
|
+
logger.info(`Updating global: ${slug}, draft: ${draft}${locale ? `, locale: ${locale}` : ''}`)
|
|
66
45
|
|
|
67
46
|
try {
|
|
68
|
-
const virtualFieldNames = getGlobalVirtualFieldNames(payload.config,
|
|
47
|
+
const virtualFieldNames = getGlobalVirtualFieldNames(payload.config, slug)
|
|
69
48
|
const inputData = stripVirtualFields(data, virtualFieldNames)
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
if (validationError) {
|
|
73
|
-
return validationError
|
|
74
|
-
}
|
|
49
|
+
validateGlobalData({ slug, data: inputData, req })
|
|
75
50
|
|
|
76
51
|
const parsedData = transformPointDataToPayload(inputData)
|
|
77
52
|
|
|
78
53
|
const updateOptions: Parameters<typeof payload.updateGlobal>[0] = {
|
|
79
|
-
slug
|
|
54
|
+
slug,
|
|
80
55
|
data: parsedData,
|
|
81
56
|
depth,
|
|
82
57
|
draft,
|
|
83
58
|
overrideAccess: authorizedMCP.overrideAccess,
|
|
59
|
+
overrideLock,
|
|
60
|
+
populate,
|
|
61
|
+
publishAllLocales,
|
|
84
62
|
req,
|
|
63
|
+
unpublishAllLocales,
|
|
85
64
|
}
|
|
86
65
|
|
|
87
66
|
if (locale) {
|
|
88
67
|
updateOptions.locale = locale
|
|
89
68
|
}
|
|
90
|
-
if (fallbackLocale) {
|
|
69
|
+
if (fallbackLocale !== undefined) {
|
|
91
70
|
updateOptions.fallbackLocale = fallbackLocale
|
|
92
71
|
}
|
|
93
72
|
if (select) {
|
|
94
|
-
updateOptions.select = select
|
|
73
|
+
updateOptions.select = select
|
|
95
74
|
}
|
|
96
75
|
|
|
97
76
|
const result = await payload.updateGlobal(updateOptions)
|
|
@@ -100,16 +79,14 @@ export const updateGlobalTool = defineGlobalTool({
|
|
|
100
79
|
content: [
|
|
101
80
|
{
|
|
102
81
|
type: 'text',
|
|
103
|
-
text: `Global "${
|
|
82
|
+
text: `Global "${slug}" updated successfully!\n\`\`\`json\n${JSON.stringify(result)}\n\`\`\``,
|
|
104
83
|
},
|
|
105
84
|
],
|
|
106
|
-
doc: result
|
|
85
|
+
doc: result,
|
|
107
86
|
}
|
|
108
87
|
} catch (error) {
|
|
109
|
-
const
|
|
110
|
-
logger.error(`Error updating global ${
|
|
111
|
-
return {
|
|
112
|
-
content: [{ type: 'text', text: `Error updating global "${globalSlug}": ${errorMessage}` }],
|
|
113
|
-
}
|
|
88
|
+
const message = error instanceof Error ? error.message : 'Unknown error'
|
|
89
|
+
logger.error(`Error updating global ${slug}: ${message}`)
|
|
90
|
+
return formatEntityError({ slug, action: 'updating', entity: 'global', error, req })
|
|
114
91
|
}
|
|
115
92
|
})
|
package/src/mcp/builtinTools.ts
CHANGED
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
} from './builtin/collections/authTools.js'
|
|
11
11
|
import { countDocumentsTool } from './builtin/collections/countTool.js'
|
|
12
12
|
import { countVersionsTool } from './builtin/collections/countVersionsTool.js'
|
|
13
|
-
import {
|
|
13
|
+
import { createDocumentsTool } from './builtin/collections/createTool.js'
|
|
14
14
|
import { deleteDocumentsTool } from './builtin/collections/deleteTool.js'
|
|
15
15
|
import { duplicateDocumentTool } from './builtin/collections/duplicateTool.js'
|
|
16
16
|
import { findDistinctTool } from './builtin/collections/findDistinctTool.js'
|
|
@@ -56,7 +56,7 @@ export const TOOL_BUILTINS = {
|
|
|
56
56
|
export const COLLECTION_BUILTINS = {
|
|
57
57
|
count: { mcpName: 'countDocuments', tool: countDocumentsTool },
|
|
58
58
|
countVersions: { mcpName: 'countVersions', requiresVersions: true, tool: countVersionsTool },
|
|
59
|
-
create: { mcpName: '
|
|
59
|
+
create: { mcpName: 'createDocuments', tool: createDocumentsTool },
|
|
60
60
|
delete: { mcpName: 'deleteDocuments', tool: deleteDocumentsTool },
|
|
61
61
|
duplicate: {
|
|
62
62
|
mcpName: 'duplicateDocument',
|
|
@@ -103,6 +103,7 @@ export const sanitizeMCPConfig = ({
|
|
|
103
103
|
hooks: pluginConfig.hooks,
|
|
104
104
|
items,
|
|
105
105
|
mcp: pluginConfig.mcp,
|
|
106
|
+
oauth: pluginConfig.oauth === false ? undefined : (pluginConfig.oauth ?? { type: 'builtin' }),
|
|
106
107
|
overrideGetAuthorizedMCP: pluginConfig.overrideGetAuthorizedMCP,
|
|
107
108
|
}
|
|
108
109
|
}
|
package/src/stdio.ts
CHANGED
|
@@ -3,7 +3,7 @@ import type { Config, Plugin, SanitizedConfig } from 'payload'
|
|
|
3
3
|
/* eslint-disable no-console */
|
|
4
4
|
import { serveStdio } from '@modelcontextprotocol/server/stdio'
|
|
5
5
|
import { fileURLToPath, pathToFileURL } from 'node:url'
|
|
6
|
-
import {
|
|
6
|
+
import { createPayloadRequest, getPayload } from 'payload'
|
|
7
7
|
import { findConfig, loadEnv } from 'payload/node'
|
|
8
8
|
|
|
9
9
|
import type { SanitizedMCPPluginConfig } from './types.js'
|
|
@@ -91,7 +91,7 @@ export const runMcpStdio = async (): Promise<void> => {
|
|
|
91
91
|
headers.set('Authorization', process.env.PAYLOAD_MCP_AUTHORIZATION)
|
|
92
92
|
}
|
|
93
93
|
|
|
94
|
-
const req = await
|
|
94
|
+
const req = await createPayloadRequest({ payload, req: { headers } })
|
|
95
95
|
req.payloadAPI = 'MCP' as const
|
|
96
96
|
const authorizedMCP = await getAuthorizedMCP({ overrideAccess, req })
|
|
97
97
|
|
package/src/types.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import type {
|
|
2
2
|
CallToolResult,
|
|
3
3
|
ContentBlock,
|
|
4
|
+
Implementation,
|
|
4
5
|
JsonSchemaType,
|
|
5
|
-
|
|
6
|
+
McpServerOptions,
|
|
6
7
|
ResourceTemplate,
|
|
7
8
|
ServerContext,
|
|
8
9
|
StandardSchemaWithJSON,
|
|
@@ -75,11 +76,11 @@ export type MCPAccessArgs = {
|
|
|
75
76
|
}
|
|
76
77
|
|
|
77
78
|
export type CollectionMCPAccessArgs = {
|
|
78
|
-
|
|
79
|
+
slug: CollectionSlug
|
|
79
80
|
} & MCPAccessArgs
|
|
80
81
|
|
|
81
82
|
export type GlobalMCPAccessArgs = {
|
|
82
|
-
|
|
83
|
+
slug: GlobalSlug
|
|
83
84
|
} & MCPAccessArgs
|
|
84
85
|
|
|
85
86
|
export type ToolHandlerArgs<TSchema = undefined> = {
|
|
@@ -90,11 +91,11 @@ export type ToolHandlerArgs<TSchema = undefined> = {
|
|
|
90
91
|
}
|
|
91
92
|
|
|
92
93
|
export type CollectionToolHandlerArgs<TSchema = undefined> = {
|
|
93
|
-
|
|
94
|
+
slug: CollectionSlug
|
|
94
95
|
} & ToolHandlerArgs<TSchema>
|
|
95
96
|
|
|
96
97
|
export type GlobalToolHandlerArgs<TSchema = undefined> = {
|
|
97
|
-
|
|
98
|
+
slug: GlobalSlug
|
|
98
99
|
} & ToolHandlerArgs<TSchema>
|
|
99
100
|
|
|
100
101
|
export type Tool<TSchema extends ToolInputSchema | undefined = ToolInputSchema | undefined> = {
|
|
@@ -279,9 +280,24 @@ export type MCPPluginConfig = {
|
|
|
279
280
|
afterToolCall?: MCPAfterToolCallHook[]
|
|
280
281
|
}
|
|
281
282
|
mcp?: {
|
|
283
|
+
/**
|
|
284
|
+
* Largest HTTP request body, in bytes, that the MCP endpoint accepts. Larger requests
|
|
285
|
+
* are answered with `413`. Base64 file uploads count toward this limit.
|
|
286
|
+
*
|
|
287
|
+
* @default 4194304 (4 MiB, the MCP SDK default)
|
|
288
|
+
*/
|
|
289
|
+
maxRequestBodySize?: number
|
|
282
290
|
serverOptions?: MCPServerOptions
|
|
283
291
|
verboseLogs?: boolean
|
|
284
292
|
}
|
|
293
|
+
/**
|
|
294
|
+
* How MCP clients sign in. MCP requests without an authenticated user get a `401` that points
|
|
295
|
+
* to the protected resource metadata (RFC 9728). Set to `false` to only accept API keys and
|
|
296
|
+
* anonymous requests.
|
|
297
|
+
*
|
|
298
|
+
* @default { type: 'builtin' }
|
|
299
|
+
*/
|
|
300
|
+
oauth?: false | MCPOAuthConfig
|
|
285
301
|
/**
|
|
286
302
|
* Replace the default MCP authorization resolver.
|
|
287
303
|
*
|
|
@@ -299,13 +315,87 @@ export type MCPPluginConfig = {
|
|
|
299
315
|
tools?: MCPTopLevelToolsMap
|
|
300
316
|
}
|
|
301
317
|
|
|
318
|
+
export type MCPOAuthConfig = MCPBuiltinOAuthConfig | MCPExternalOAuthConfig
|
|
319
|
+
|
|
320
|
+
/**
|
|
321
|
+
* This Payload app is the authorization server. Users sign in to the admin panel and allow the
|
|
322
|
+
* MCP client, which then gets an access token for them.
|
|
323
|
+
*/
|
|
324
|
+
export type MCPBuiltinOAuthConfig = {
|
|
325
|
+
/**
|
|
326
|
+
* Creates the tokens the MCP client gets when the user clicks Allow. `req` is the user's own
|
|
327
|
+
* browser request, so `req.user` is the user who allowed it. Pass `authenticate` too if
|
|
328
|
+
* Payload's auth strategies don't accept the access token.
|
|
329
|
+
*
|
|
330
|
+
* @default a Payload login token for that user, with a refresh token when the collection uses sessions
|
|
331
|
+
*/
|
|
332
|
+
issueToken?: (args: { req: PayloadRequest }) => MaybePromise<MCPOAuthTokens>
|
|
333
|
+
/**
|
|
334
|
+
* Trades a refresh token from `issueToken`, or from an earlier refresh, for new tokens. Return
|
|
335
|
+
* `null` when it's no longer valid, and the client sends the user through sign-in again. `req`
|
|
336
|
+
* is the MCP client's request, without a user. Only used together with `issueToken`.
|
|
337
|
+
*
|
|
338
|
+
* OAuth requires noticing copied refresh tokens: return a new refresh token every time, and
|
|
339
|
+
* revoke the tokens when an already used refresh token comes back.
|
|
340
|
+
*/
|
|
341
|
+
refreshToken?: (args: {
|
|
342
|
+
refreshToken: string
|
|
343
|
+
req: PayloadRequest
|
|
344
|
+
}) => MaybePromise<MCPOAuthTokens | null>
|
|
345
|
+
type: 'builtin'
|
|
346
|
+
} & MCPOAuthSharedConfig
|
|
347
|
+
|
|
348
|
+
export type MCPOAuthTokens = {
|
|
349
|
+
accessToken: string
|
|
350
|
+
/** Seconds until the access token expires. */
|
|
351
|
+
expiresIn?: number
|
|
352
|
+
/** Lets the client get new tokens without the user, through `refreshToken`. */
|
|
353
|
+
refreshToken?: string
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
/** Another service, e.g. your identity provider, is the authorization server. */
|
|
357
|
+
export type MCPExternalOAuthConfig = {
|
|
358
|
+
/**
|
|
359
|
+
* The authorization servers that issue access tokens for MCP clients. Clients require each one
|
|
360
|
+
* to exactly match the `issuer` in that server's metadata, so pass a function when the exact
|
|
361
|
+
* value is only known at runtime, e.g. from the server's OpenID configuration or per host.
|
|
362
|
+
*/
|
|
363
|
+
authorizationServers: ((args: { req: PayloadRequest }) => MaybePromise<string[]>) | string[]
|
|
364
|
+
/**
|
|
365
|
+
* Scopes MCP clients should request, e.g. `['openid', 'email', 'profile']`. Without them,
|
|
366
|
+
* clients request none, which some authorization servers reject or answer with a token that
|
|
367
|
+
* doesn't identify the user.
|
|
368
|
+
*/
|
|
369
|
+
scopes?: string[]
|
|
370
|
+
type: 'external'
|
|
371
|
+
} & MCPOAuthSharedConfig
|
|
372
|
+
|
|
373
|
+
type MCPOAuthSharedConfig = {
|
|
374
|
+
/**
|
|
375
|
+
* Called on MCP requests with a bearer token that Payload's auth strategies didn't accept.
|
|
376
|
+
* Return the Payload user, including its `collection`, or `null` to answer with the OAuth challenge.
|
|
377
|
+
*/
|
|
378
|
+
authenticate?: (args: {
|
|
379
|
+
req: PayloadRequest
|
|
380
|
+
token: string
|
|
381
|
+
}) => MaybePromise<PayloadRequest['user']>
|
|
382
|
+
/**
|
|
383
|
+
* The URL clients call to reach the MCP endpoint.
|
|
384
|
+
*
|
|
385
|
+
* @default the absolute URL of `/api/mcp`, based on `serverURL` or the request URL
|
|
386
|
+
*/
|
|
387
|
+
resource?: string
|
|
388
|
+
}
|
|
389
|
+
|
|
302
390
|
export type SanitizedMCPPluginConfig = {
|
|
303
391
|
items: MCPItem[]
|
|
392
|
+
/** `undefined` when OAuth is turned off. */
|
|
393
|
+
oauth?: MCPOAuthConfig
|
|
304
394
|
} & Pick<MCPPluginConfig, 'disabled' | 'hooks' | 'mcp' | 'overrideGetAuthorizedMCP'>
|
|
305
395
|
|
|
306
396
|
export type MCPServerOptions = {
|
|
307
|
-
options?:
|
|
308
|
-
serverInfo?: Partial<
|
|
397
|
+
options?: McpServerOptions
|
|
398
|
+
serverInfo?: Partial<Implementation>
|
|
309
399
|
}
|
|
310
400
|
|
|
311
401
|
/**
|
|
@@ -5,5 +5,5 @@ import type { ToolInputSchema } from '../types.js'
|
|
|
5
5
|
/** Normalize a tool/prompt input to a Standard Schema. Raw JSON Schema gets wrapped; Standard Schema instances pass through. */
|
|
6
6
|
export const toStandardSchema = (schema: ToolInputSchema): StandardSchemaWithJSON =>
|
|
7
7
|
typeof schema === 'object' && schema !== null && '~standard' in schema
|
|
8
|
-
?
|
|
8
|
+
? schema
|
|
9
9
|
: fromJsonSchema(schema)
|
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest';
|
|
2
|
-
import { fileInputSchema, resolveFile } from './fileInput.js';
|
|
3
|
-
describe('MCP file input', ()=>{
|
|
4
|
-
it('should reject malformed MIME types', ()=>{
|
|
5
|
-
const result = fileInputSchema.safeParse({
|
|
6
|
-
data: 'aGVsbG8=',
|
|
7
|
-
mimeType: 'text/plain\r\nx-test: value',
|
|
8
|
-
name: 'hello.txt',
|
|
9
|
-
source: 'base64'
|
|
10
|
-
});
|
|
11
|
-
expect(result.success).toBe(false);
|
|
12
|
-
});
|
|
13
|
-
it('should accept a prepared upload', ()=>{
|
|
14
|
-
const result = fileInputSchema.safeParse({
|
|
15
|
-
file: {
|
|
16
|
-
filename: 'image.png',
|
|
17
|
-
mimeType: 'image/png',
|
|
18
|
-
size: 123,
|
|
19
|
-
uploadReference: {
|
|
20
|
-
uploadId: 'upload-id'
|
|
21
|
-
}
|
|
22
|
-
},
|
|
23
|
-
source: 'uploadReference'
|
|
24
|
-
});
|
|
25
|
-
expect(result.success).toBe(true);
|
|
26
|
-
});
|
|
27
|
-
it('should reject oversized base64 files', async ()=>{
|
|
28
|
-
const req = createRequest({
|
|
29
|
-
maxFileSize: 4
|
|
30
|
-
});
|
|
31
|
-
await expect(resolveFile({
|
|
32
|
-
collectionSlug: 'media',
|
|
33
|
-
input: {
|
|
34
|
-
data: Buffer.from('hello').toString('base64'),
|
|
35
|
-
mimeType: 'text/plain',
|
|
36
|
-
name: 'hello.txt',
|
|
37
|
-
source: 'base64'
|
|
38
|
-
},
|
|
39
|
-
req
|
|
40
|
-
})).rejects.toThrow('File exceeds the 4 byte upload limit.');
|
|
41
|
-
});
|
|
42
|
-
it('should reject URLs outside the collection allowlist', async ()=>{
|
|
43
|
-
const req = createRequest({
|
|
44
|
-
allowList: [
|
|
45
|
-
{
|
|
46
|
-
hostname: 'assets.example.com',
|
|
47
|
-
protocol: 'https'
|
|
48
|
-
}
|
|
49
|
-
]
|
|
50
|
-
});
|
|
51
|
-
await expect(resolveFile({
|
|
52
|
-
collectionSlug: 'media',
|
|
53
|
-
input: {
|
|
54
|
-
source: 'externalURL',
|
|
55
|
-
url: 'https://example.com/image.png'
|
|
56
|
-
},
|
|
57
|
-
req
|
|
58
|
-
})).rejects.toThrow('The provided file URL is not allowed.');
|
|
59
|
-
});
|
|
60
|
-
});
|
|
61
|
-
function createRequest({ allowList, maxFileSize }) {
|
|
62
|
-
return {
|
|
63
|
-
payload: {
|
|
64
|
-
collections: {
|
|
65
|
-
media: {
|
|
66
|
-
config: {
|
|
67
|
-
upload: allowList ? {
|
|
68
|
-
pasteURL: {
|
|
69
|
-
allowList
|
|
70
|
-
}
|
|
71
|
-
} : {}
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
},
|
|
75
|
-
config: {
|
|
76
|
-
upload: {
|
|
77
|
-
limits: {
|
|
78
|
-
fileSize: maxFileSize
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
};
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
//# sourceMappingURL=fileInput.spec.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/mcp/builtin/collections/fileInput.spec.ts"],"sourcesContent":["import type { PayloadRequest } from 'payload'\n\nimport { describe, expect, it } from 'vitest'\n\nimport { fileInputSchema, resolveFile } from './fileInput.js'\n\ndescribe('MCP file input', () => {\n it('should reject malformed MIME types', () => {\n const result = fileInputSchema.safeParse({\n data: 'aGVsbG8=',\n mimeType: 'text/plain\\r\\nx-test: value',\n name: 'hello.txt',\n source: 'base64',\n })\n\n expect(result.success).toBe(false)\n })\n\n it('should accept a prepared upload', () => {\n const result = fileInputSchema.safeParse({\n file: {\n filename: 'image.png',\n mimeType: 'image/png',\n size: 123,\n uploadReference: { uploadId: 'upload-id' },\n },\n source: 'uploadReference',\n })\n\n expect(result.success).toBe(true)\n })\n\n it('should reject oversized base64 files', async () => {\n const req = createRequest({ maxFileSize: 4 })\n\n await expect(\n resolveFile({\n collectionSlug: 'media',\n input: {\n data: Buffer.from('hello').toString('base64'),\n mimeType: 'text/plain',\n name: 'hello.txt',\n source: 'base64',\n },\n req,\n }),\n ).rejects.toThrow('File exceeds the 4 byte upload limit.')\n })\n\n it('should reject URLs outside the collection allowlist', async () => {\n const req = createRequest({\n allowList: [{ hostname: 'assets.example.com', protocol: 'https' }],\n })\n\n await expect(\n resolveFile({\n collectionSlug: 'media',\n input: {\n source: 'externalURL',\n url: 'https://example.com/image.png',\n },\n req,\n }),\n ).rejects.toThrow('The provided file URL is not allowed.')\n })\n})\n\nfunction createRequest({\n allowList,\n maxFileSize,\n}: {\n allowList?: Array<{ hostname: string; protocol: 'http' | 'https' }>\n maxFileSize?: number\n}): PayloadRequest {\n return {\n payload: {\n collections: {\n media: {\n config: {\n upload: allowList ? { pasteURL: { allowList } } : {},\n },\n },\n },\n config: {\n upload: {\n limits: {\n fileSize: maxFileSize,\n },\n },\n },\n },\n } as unknown as PayloadRequest\n}\n"],"names":["describe","expect","it","fileInputSchema","resolveFile","result","safeParse","data","mimeType","name","source","success","toBe","file","filename","size","uploadReference","uploadId","req","createRequest","maxFileSize","collectionSlug","input","Buffer","from","toString","rejects","toThrow","allowList","hostname","protocol","url","payload","collections","media","config","upload","pasteURL","limits","fileSize"],"mappings":"AAEA,SAASA,QAAQ,EAAEC,MAAM,EAAEC,EAAE,QAAQ,SAAQ;AAE7C,SAASC,eAAe,EAAEC,WAAW,QAAQ,iBAAgB;AAE7DJ,SAAS,kBAAkB;IACzBE,GAAG,sCAAsC;QACvC,MAAMG,SAASF,gBAAgBG,SAAS,CAAC;YACvCC,MAAM;YACNC,UAAU;YACVC,MAAM;YACNC,QAAQ;QACV;QAEAT,OAAOI,OAAOM,OAAO,EAAEC,IAAI,CAAC;IAC9B;IAEAV,GAAG,mCAAmC;QACpC,MAAMG,SAASF,gBAAgBG,SAAS,CAAC;YACvCO,MAAM;gBACJC,UAAU;gBACVN,UAAU;gBACVO,MAAM;gBACNC,iBAAiB;oBAAEC,UAAU;gBAAY;YAC3C;YACAP,QAAQ;QACV;QAEAT,OAAOI,OAAOM,OAAO,EAAEC,IAAI,CAAC;IAC9B;IAEAV,GAAG,wCAAwC;QACzC,MAAMgB,MAAMC,cAAc;YAAEC,aAAa;QAAE;QAE3C,MAAMnB,OACJG,YAAY;YACViB,gBAAgB;YAChBC,OAAO;gBACLf,MAAMgB,OAAOC,IAAI,CAAC,SAASC,QAAQ,CAAC;gBACpCjB,UAAU;gBACVC,MAAM;gBACNC,QAAQ;YACV;YACAQ;QACF,IACAQ,OAAO,CAACC,OAAO,CAAC;IACpB;IAEAzB,GAAG,uDAAuD;QACxD,MAAMgB,MAAMC,cAAc;YACxBS,WAAW;gBAAC;oBAAEC,UAAU;oBAAsBC,UAAU;gBAAQ;aAAE;QACpE;QAEA,MAAM7B,OACJG,YAAY;YACViB,gBAAgB;YAChBC,OAAO;gBACLZ,QAAQ;gBACRqB,KAAK;YACP;YACAb;QACF,IACAQ,OAAO,CAACC,OAAO,CAAC;IACpB;AACF;AAEA,SAASR,cAAc,EACrBS,SAAS,EACTR,WAAW,EAIZ;IACC,OAAO;QACLY,SAAS;YACPC,aAAa;gBACXC,OAAO;oBACLC,QAAQ;wBACNC,QAAQR,YAAY;4BAAES,UAAU;gCAAET;4BAAU;wBAAE,IAAI,CAAC;oBACrD;gBACF;YACF;YACAO,QAAQ;gBACNC,QAAQ;oBACNE,QAAQ;wBACNC,UAAUnB;oBACZ;gBACF;YACF;QACF;IACF;AACF"}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import type { CollectionSlug, PayloadRequest } from 'payload';
|
|
2
|
-
import type { MCPToolResponse } from '../../../types.js';
|
|
3
|
-
export declare const formatCollectionError: ({ action, collectionSlug, error, req, }: {
|
|
4
|
-
action: 'creating' | 'duplicating' | 'updating';
|
|
5
|
-
collectionSlug: CollectionSlug;
|
|
6
|
-
error: unknown;
|
|
7
|
-
req: PayloadRequest;
|
|
8
|
-
}) => MCPToolResponse;
|
|
9
|
-
//# sourceMappingURL=formatCollectionError.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"formatCollectionError.d.ts","sourceRoot":"","sources":["../../../../src/mcp/builtin/collections/formatCollectionError.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAE7D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AAgCxD,eAAO,MAAM,qBAAqB,4CAK/B;IACD,MAAM,EAAE,UAAU,GAAG,aAAa,GAAG,UAAU,CAAA;IAC/C,cAAc,EAAE,cAAc,CAAA;IAC9B,KAAK,EAAE,OAAO,CAAA;IACd,GAAG,EAAE,cAAc,CAAA;CACpB,KAAG,eAuCH,CAAA"}
|