@payloadcms/plugin-mcp 4.0.0-internal.2fddfc0 → 4.0.0-internal.3aa3d85
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/LICENSE.md +1 -1
- package/dist/endpoint/access.d.ts +2 -7
- package/dist/endpoint/access.d.ts.map +1 -1
- package/dist/endpoint/access.js +4 -11
- package/dist/endpoint/access.js.map +1 -1
- package/dist/endpoint/index.d.ts +1 -1
- package/dist/endpoint/index.d.ts.map +1 -1
- package/dist/endpoint/index.js +57 -17
- package/dist/endpoint/index.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/mcp/buildMcpServer.d.ts +4 -4
- package/dist/mcp/buildMcpServer.d.ts.map +1 -1
- package/dist/mcp/buildMcpServer.js +32 -10
- package/dist/mcp/buildMcpServer.js.map +1 -1
- package/dist/mcp/builtin/collections/countTool.d.ts.map +1 -1
- package/dist/mcp/builtin/collections/countTool.js +1 -2
- 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 +1 -2
- package/dist/mcp/builtin/collections/countVersionsTool.js.map +1 -1
- package/dist/mcp/builtin/collections/createTool.d.ts.map +1 -1
- package/dist/mcp/builtin/collections/createTool.js +1 -2
- 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 +1 -2
- 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 +1 -2
- package/dist/mcp/builtin/collections/duplicateTool.js.map +1 -1
- package/dist/mcp/builtin/collections/findDistinctTool.d.ts.map +1 -1
- package/dist/mcp/builtin/collections/findDistinctTool.js +1 -2
- 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 +2 -3
- 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 +1 -2
- 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 +1 -2
- 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 +21 -3
- 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 +1 -2
- 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 +2 -3
- package/dist/mcp/builtin/collections/updateTool.js.map +1 -1
- package/dist/mcp/builtin/getConfigInfoTool.d.ts.map +1 -1
- package/dist/mcp/builtin/getConfigInfoTool.js +2 -5
- 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 +1 -2
- 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 +2 -2
- 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 +1 -2
- 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 +1 -2
- 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 +21 -3
- 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 +1 -2
- 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 +2 -2
- package/dist/mcp/builtin/globals/updateTool.js.map +1 -1
- package/dist/mcp/builtin/validateEntityData.js +1 -1
- package/dist/mcp/builtin/validateEntityData.js.map +1 -1
- package/dist/mcp/sanitizeMCPConfig.d.ts.map +1 -1
- package/dist/mcp/sanitizeMCPConfig.js +1 -0
- package/dist/mcp/sanitizeMCPConfig.js.map +1 -1
- package/dist/stdio.d.ts +3 -4
- package/dist/stdio.d.ts.map +1 -1
- package/dist/stdio.js +59 -41
- package/dist/stdio.js.map +1 -1
- package/dist/types.d.ts +57 -9
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +2 -4
- package/dist/types.js.map +1 -1
- package/dist/utils/schemaConversion/filterFieldsByAccess.d.ts +28 -0
- package/dist/utils/schemaConversion/filterFieldsByAccess.d.ts.map +1 -0
- package/dist/utils/schemaConversion/filterFieldsByAccess.js +71 -0
- package/dist/utils/schemaConversion/filterFieldsByAccess.js.map +1 -0
- package/dist/utils/schemaConversion/getEntityInputSchema.d.ts +5 -3
- package/dist/utils/schemaConversion/getEntityInputSchema.d.ts.map +1 -1
- package/dist/utils/schemaConversion/getEntityInputSchema.js +44 -12
- package/dist/utils/schemaConversion/getEntityInputSchema.js.map +1 -1
- package/dist/utils/schemaConversion/sanitizeEntitySchema.d.ts +5 -10
- package/dist/utils/schemaConversion/sanitizeEntitySchema.d.ts.map +1 -1
- package/dist/utils/schemaConversion/sanitizeEntitySchema.js +15 -95
- package/dist/utils/schemaConversion/sanitizeEntitySchema.js.map +1 -1
- package/dist/utils/schemaConversion/sanitizeEntitySchema.spec.js +15 -40
- package/dist/utils/schemaConversion/sanitizeEntitySchema.spec.js.map +1 -1
- package/package.json +8 -10
- package/src/endpoint/access.ts +3 -10
- package/src/endpoint/index.ts +45 -16
- package/src/index.ts +4 -4
- package/src/mcp/buildMcpServer.ts +40 -20
- package/src/mcp/builtin/collections/countTool.ts +1 -2
- package/src/mcp/builtin/collections/countVersionsTool.ts +1 -2
- package/src/mcp/builtin/collections/createTool.ts +1 -2
- package/src/mcp/builtin/collections/deleteTool.ts +1 -2
- package/src/mcp/builtin/collections/duplicateTool.ts +1 -2
- package/src/mcp/builtin/collections/findDistinctTool.ts +1 -2
- package/src/mcp/builtin/collections/findTool.ts +2 -3
- package/src/mcp/builtin/collections/findVersionByIDTool.ts +1 -2
- package/src/mcp/builtin/collections/findVersionsTool.ts +1 -2
- package/src/mcp/builtin/collections/getCollectionSchemaTool.ts +25 -8
- package/src/mcp/builtin/collections/restoreVersionTool.ts +1 -2
- package/src/mcp/builtin/collections/updateTool.ts +2 -3
- package/src/mcp/builtin/getConfigInfoTool.ts +2 -4
- package/src/mcp/builtin/globals/countVersionsTool.ts +1 -2
- package/src/mcp/builtin/globals/findTool.ts +2 -2
- package/src/mcp/builtin/globals/findVersionByIDTool.ts +1 -2
- package/src/mcp/builtin/globals/findVersionsTool.ts +1 -2
- package/src/mcp/builtin/globals/getGlobalSchemaTool.ts +25 -3
- package/src/mcp/builtin/globals/restoreVersionTool.ts +1 -2
- package/src/mcp/builtin/globals/updateTool.ts +2 -2
- package/src/mcp/builtin/validateEntityData.ts +1 -1
- package/src/mcp/sanitizeMCPConfig.ts +1 -0
- package/src/stdio.ts +59 -42
- package/src/types.ts +57 -9
- package/src/utils/schemaConversion/filterFieldsByAccess.ts +123 -0
- package/src/utils/schemaConversion/getEntityInputSchema.ts +45 -27
- package/src/utils/schemaConversion/sanitizeEntitySchema.spec.ts +12 -19
- package/src/utils/schemaConversion/sanitizeEntitySchema.ts +17 -114
- package/dist/@types/assets.d.js +0 -2
- package/dist/@types/assets.d.js.map +0 -1
- package/dist/utils/localAPIDefaults.d.ts +0 -20
- package/dist/utils/localAPIDefaults.d.ts.map +0 -1
- package/dist/utils/localAPIDefaults.js +0 -19
- package/dist/utils/localAPIDefaults.js.map +0 -1
- package/dist/utils/schemaConversion/removeVirtualFieldsFromSchema.d.ts +0 -7
- package/dist/utils/schemaConversion/removeVirtualFieldsFromSchema.d.ts.map +0 -1
- package/dist/utils/schemaConversion/removeVirtualFieldsFromSchema.js +0 -20
- package/dist/utils/schemaConversion/removeVirtualFieldsFromSchema.js.map +0 -1
- package/src/@types/assets.d.ts +0 -3
- package/src/utils/localAPIDefaults.ts +0 -22
- package/src/utils/schemaConversion/removeVirtualFieldsFromSchema.ts +0 -27
|
@@ -3,7 +3,6 @@ import { z } from 'zod'
|
|
|
3
3
|
import { defaultAccess } from '../../../defaultAccess.js'
|
|
4
4
|
import { defineCollectionTool } from '../../../defineTool.js'
|
|
5
5
|
import { getLogger } from '../../../utils/getLogger.js'
|
|
6
|
-
import { localAPIDefaults } from '../../../utils/localAPIDefaults.js'
|
|
7
6
|
import { whereSchema } from '../../../utils/whereSchema.js'
|
|
8
7
|
|
|
9
8
|
const DEFAULT_DESCRIPTION =
|
|
@@ -69,8 +68,8 @@ export const deleteDocumentsTool = defineCollectionTool({
|
|
|
69
68
|
const deleteOptions: Record<string, unknown> = {
|
|
70
69
|
collection: collectionSlug,
|
|
71
70
|
depth,
|
|
71
|
+
overrideAccess: authorizedMCP.overrideAccess,
|
|
72
72
|
req,
|
|
73
|
-
...localAPIDefaults(authorizedMCP),
|
|
74
73
|
...(locale && { locale }),
|
|
75
74
|
...(fallbackLocale && { fallbackLocale }),
|
|
76
75
|
}
|
|
@@ -9,7 +9,6 @@ import {
|
|
|
9
9
|
getCollectionVirtualFieldNames,
|
|
10
10
|
stripVirtualFields,
|
|
11
11
|
} from '../../../utils/getVirtualFieldNames.js'
|
|
12
|
-
import { localAPIDefaults } from '../../../utils/localAPIDefaults.js'
|
|
13
12
|
import { transformPointDataToPayload } from '../../../utils/transformPointDataToPayload.js'
|
|
14
13
|
import { formatCollectionError } from './formatCollectionError.js'
|
|
15
14
|
|
|
@@ -105,8 +104,8 @@ export const duplicateDocumentTool = defineCollectionTool({
|
|
|
105
104
|
collection: collectionSlug,
|
|
106
105
|
depth,
|
|
107
106
|
draft,
|
|
107
|
+
overrideAccess: authorizedMCP.overrideAccess,
|
|
108
108
|
req,
|
|
109
|
-
...localAPIDefaults(authorizedMCP),
|
|
110
109
|
...(parsedData ? { data: parsedData } : {}),
|
|
111
110
|
...(locale ? { locale } : {}),
|
|
112
111
|
...(fallbackLocale ? { fallbackLocale } : {}),
|
|
@@ -5,7 +5,6 @@ import { z } from 'zod'
|
|
|
5
5
|
import { defaultAccess } from '../../../defaultAccess.js'
|
|
6
6
|
import { defineCollectionTool } from '../../../defineTool.js'
|
|
7
7
|
import { getLogger } from '../../../utils/getLogger.js'
|
|
8
|
-
import { localAPIDefaults } from '../../../utils/localAPIDefaults.js'
|
|
9
8
|
import { whereSchema } from '../../../utils/whereSchema.js'
|
|
10
9
|
|
|
11
10
|
const DEFAULT_DESCRIPTION =
|
|
@@ -83,8 +82,8 @@ export const findDistinctTool = defineCollectionTool({
|
|
|
83
82
|
collection: collectionSlug,
|
|
84
83
|
depth,
|
|
85
84
|
field,
|
|
85
|
+
overrideAccess: authorizedMCP.overrideAccess,
|
|
86
86
|
req,
|
|
87
|
-
...localAPIDefaults(authorizedMCP),
|
|
88
87
|
...(limit ? { limit } : {}),
|
|
89
88
|
...(locale ? { locale } : {}),
|
|
90
89
|
...(page ? { page } : {}),
|
|
@@ -5,7 +5,6 @@ import { z } from 'zod'
|
|
|
5
5
|
import { defaultAccess } from '../../../defaultAccess.js'
|
|
6
6
|
import { defineCollectionTool } from '../../../defineTool.js'
|
|
7
7
|
import { getLogger } from '../../../utils/getLogger.js'
|
|
8
|
-
import { localAPIDefaults } from '../../../utils/localAPIDefaults.js'
|
|
9
8
|
import { whereSchema } from '../../../utils/whereSchema.js'
|
|
10
9
|
|
|
11
10
|
const DEFAULT_DESCRIPTION =
|
|
@@ -134,8 +133,8 @@ export const findDocumentsTool = defineCollectionTool({
|
|
|
134
133
|
id,
|
|
135
134
|
collection: collectionSlug,
|
|
136
135
|
depth,
|
|
136
|
+
overrideAccess: authorizedMCP.overrideAccess,
|
|
137
137
|
req,
|
|
138
|
-
...localAPIDefaults(authorizedMCP),
|
|
139
138
|
...(select && { select: select as SelectType }),
|
|
140
139
|
...(populate && { populate: populate as PopulateType }),
|
|
141
140
|
...(joins !== undefined && { joins: joins as JoinQuery }),
|
|
@@ -171,9 +170,9 @@ export const findDocumentsTool = defineCollectionTool({
|
|
|
171
170
|
collection: collectionSlug,
|
|
172
171
|
depth,
|
|
173
172
|
limit,
|
|
173
|
+
overrideAccess: authorizedMCP.overrideAccess,
|
|
174
174
|
page,
|
|
175
175
|
req,
|
|
176
|
-
...localAPIDefaults(authorizedMCP),
|
|
177
176
|
...(select && { select: select as SelectType }),
|
|
178
177
|
...(populate && { populate: populate as PopulateType }),
|
|
179
178
|
...(joins !== undefined && { joins: joins as JoinQuery }),
|
|
@@ -5,7 +5,6 @@ import { z } from 'zod'
|
|
|
5
5
|
import { defaultAccess } from '../../../defaultAccess.js'
|
|
6
6
|
import { defineCollectionTool } from '../../../defineTool.js'
|
|
7
7
|
import { getLogger } from '../../../utils/getLogger.js'
|
|
8
|
-
import { localAPIDefaults } from '../../../utils/localAPIDefaults.js'
|
|
9
8
|
|
|
10
9
|
const DEFAULT_DESCRIPTION =
|
|
11
10
|
'Find a specific document version in any version-enabled collection by passing the collection slug and version ID.'
|
|
@@ -75,8 +74,8 @@ export const findVersionByIDTool = defineCollectionTool({
|
|
|
75
74
|
id,
|
|
76
75
|
collection: collectionSlug,
|
|
77
76
|
depth,
|
|
77
|
+
overrideAccess: authorizedMCP.overrideAccess,
|
|
78
78
|
req,
|
|
79
|
-
...localAPIDefaults(authorizedMCP),
|
|
80
79
|
...(fallbackLocale ? { fallbackLocale } : {}),
|
|
81
80
|
...(locale ? { locale } : {}),
|
|
82
81
|
...(populate ? { populate: populate as PopulateType } : {}),
|
|
@@ -5,7 +5,6 @@ import { z } from 'zod'
|
|
|
5
5
|
import { defaultAccess } from '../../../defaultAccess.js'
|
|
6
6
|
import { defineCollectionTool } from '../../../defineTool.js'
|
|
7
7
|
import { getLogger } from '../../../utils/getLogger.js'
|
|
8
|
-
import { localAPIDefaults } from '../../../utils/localAPIDefaults.js'
|
|
9
8
|
import { whereSchema } from '../../../utils/whereSchema.js'
|
|
10
9
|
|
|
11
10
|
const DEFAULT_DESCRIPTION =
|
|
@@ -116,9 +115,9 @@ export const findVersionsTool = defineCollectionTool({
|
|
|
116
115
|
collection: collectionSlug,
|
|
117
116
|
depth,
|
|
118
117
|
limit,
|
|
118
|
+
overrideAccess: authorizedMCP.overrideAccess,
|
|
119
119
|
page,
|
|
120
120
|
req,
|
|
121
|
-
...localAPIDefaults(authorizedMCP),
|
|
122
121
|
...(fallbackLocale ? { fallbackLocale } : {}),
|
|
123
122
|
...(locale ? { locale } : {}),
|
|
124
123
|
...(pagination !== undefined ? { pagination } : {}),
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { getAccessResults } from 'payload'
|
|
2
|
+
|
|
1
3
|
import { defaultAccess } from '../../../defaultAccess.js'
|
|
2
4
|
import { defineCollectionTool } from '../../../defineTool.js'
|
|
3
5
|
import { getCollectionInputSchema } from '../../../utils/schemaConversion/getEntityInputSchema.js'
|
|
@@ -6,12 +8,7 @@ export const getCollectionSchemaTool = defineCollectionTool({
|
|
|
6
8
|
access: (args) => {
|
|
7
9
|
const permissions = args.permissions?.collections?.[args.collectionSlug]
|
|
8
10
|
|
|
9
|
-
return (
|
|
10
|
-
defaultAccess(args) &&
|
|
11
|
-
Boolean(
|
|
12
|
-
permissions?.create || permissions?.delete || permissions?.read || permissions?.update,
|
|
13
|
-
)
|
|
14
|
-
)
|
|
11
|
+
return defaultAccess(args) && Boolean(permissions?.create || permissions?.update)
|
|
15
12
|
},
|
|
16
13
|
annotations: {
|
|
17
14
|
destructiveHint: false,
|
|
@@ -21,8 +18,28 @@ export const getCollectionSchemaTool = defineCollectionTool({
|
|
|
21
18
|
title: 'Get Collection Schema',
|
|
22
19
|
},
|
|
23
20
|
description: 'Get the input schema for creating or updating documents in a collection.',
|
|
24
|
-
}).handler(({ collectionSlug, req }) => {
|
|
25
|
-
const
|
|
21
|
+
}).handler(async ({ authorizedMCP, collectionSlug, req }) => {
|
|
22
|
+
const permissions = authorizedMCP.overrideAccess
|
|
23
|
+
? null
|
|
24
|
+
: (await getAccessResults({ req })).collections?.[collectionSlug]
|
|
25
|
+
|
|
26
|
+
if (!authorizedMCP.overrideAccess && !permissions?.create && !permissions?.update) {
|
|
27
|
+
return {
|
|
28
|
+
content: [
|
|
29
|
+
{
|
|
30
|
+
type: 'text',
|
|
31
|
+
text: `Error: MCP access to "getCollectionSchema" is not enabled for collection "${collectionSlug}"`,
|
|
32
|
+
},
|
|
33
|
+
],
|
|
34
|
+
isError: true,
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const inputSchema = getCollectionInputSchema({
|
|
39
|
+
collectionSlug,
|
|
40
|
+
req,
|
|
41
|
+
...(permissions ? { permissions } : {}),
|
|
42
|
+
})
|
|
26
43
|
|
|
27
44
|
if (!inputSchema) {
|
|
28
45
|
return {
|
|
@@ -5,7 +5,6 @@ import { z } from 'zod'
|
|
|
5
5
|
import { defaultAccess } from '../../../defaultAccess.js'
|
|
6
6
|
import { defineCollectionTool } from '../../../defineTool.js'
|
|
7
7
|
import { getLogger } from '../../../utils/getLogger.js'
|
|
8
|
-
import { localAPIDefaults } from '../../../utils/localAPIDefaults.js'
|
|
9
8
|
|
|
10
9
|
const DEFAULT_DESCRIPTION =
|
|
11
10
|
'Restore a document from a previous version in any version-enabled collection.'
|
|
@@ -74,8 +73,8 @@ export const restoreVersionTool = defineCollectionTool({
|
|
|
74
73
|
collection: collectionSlug,
|
|
75
74
|
depth,
|
|
76
75
|
draft,
|
|
76
|
+
overrideAccess: authorizedMCP.overrideAccess,
|
|
77
77
|
req,
|
|
78
|
-
...localAPIDefaults(authorizedMCP),
|
|
79
78
|
...(fallbackLocale ? { fallbackLocale } : {}),
|
|
80
79
|
...(locale ? { locale } : {}),
|
|
81
80
|
...(populate ? { populate: populate as PopulateType } : {}),
|
|
@@ -9,7 +9,6 @@ import {
|
|
|
9
9
|
getCollectionVirtualFieldNames,
|
|
10
10
|
stripVirtualFields,
|
|
11
11
|
} from '../../../utils/getVirtualFieldNames.js'
|
|
12
|
-
import { localAPIDefaults } from '../../../utils/localAPIDefaults.js'
|
|
13
12
|
import { getCollectionInputSchema } from '../../../utils/schemaConversion/getEntityInputSchema.js'
|
|
14
13
|
import { transformPointDataToPayload } from '../../../utils/transformPointDataToPayload.js'
|
|
15
14
|
import { whereSchema } from '../../../utils/whereSchema.js'
|
|
@@ -129,9 +128,9 @@ export const updateDocumentTool = defineCollectionTool({
|
|
|
129
128
|
data: parsedData,
|
|
130
129
|
depth,
|
|
131
130
|
draft,
|
|
131
|
+
overrideAccess: authorizedMCP.overrideAccess,
|
|
132
132
|
overrideLock,
|
|
133
133
|
req,
|
|
134
|
-
...localAPIDefaults(authorizedMCP),
|
|
135
134
|
...(filePath ? { filePath } : {}),
|
|
136
135
|
...(overwriteExistingFiles ? { overwriteExistingFiles } : {}),
|
|
137
136
|
...(locale ? { locale } : {}),
|
|
@@ -155,10 +154,10 @@ export const updateDocumentTool = defineCollectionTool({
|
|
|
155
154
|
data: parsedData,
|
|
156
155
|
depth,
|
|
157
156
|
draft,
|
|
157
|
+
overrideAccess: authorizedMCP.overrideAccess,
|
|
158
158
|
overrideLock,
|
|
159
159
|
req,
|
|
160
160
|
where: whereClause,
|
|
161
|
-
...localAPIDefaults(authorizedMCP),
|
|
162
161
|
...(filePath ? { filePath } : {}),
|
|
163
162
|
...(overwriteExistingFiles ? { overwriteExistingFiles } : {}),
|
|
164
163
|
...(locale ? { locale } : {}),
|
|
@@ -12,10 +12,8 @@ export const getConfigInfoTool = defineTool({
|
|
|
12
12
|
},
|
|
13
13
|
description: 'List the Payload collection and global slugs visible to this MCP client.',
|
|
14
14
|
}).handler(async ({ authorizedMCP, req }) => {
|
|
15
|
-
const user =
|
|
16
|
-
const permissions = authorizedMCP.overrideAccess
|
|
17
|
-
? null
|
|
18
|
-
: await getAccessResults({ req: { ...req, user } })
|
|
15
|
+
const user = req.user
|
|
16
|
+
const permissions = authorizedMCP.overrideAccess ? null : await getAccessResults({ req })
|
|
19
17
|
const authorizedCollectionSlugs = new Set<string>()
|
|
20
18
|
const authorizedGlobalSlugs = new Set<string>()
|
|
21
19
|
|
|
@@ -3,7 +3,6 @@ import { z } from 'zod'
|
|
|
3
3
|
import { defaultAccess } from '../../../defaultAccess.js'
|
|
4
4
|
import { defineGlobalTool } from '../../../defineTool.js'
|
|
5
5
|
import { getLogger } from '../../../utils/getLogger.js'
|
|
6
|
-
import { localAPIDefaults } from '../../../utils/localAPIDefaults.js'
|
|
7
6
|
import { whereSchema } from '../../../utils/whereSchema.js'
|
|
8
7
|
|
|
9
8
|
const DEFAULT_DESCRIPTION =
|
|
@@ -38,8 +37,8 @@ export const countGlobalVersionsTool = defineGlobalTool({
|
|
|
38
37
|
try {
|
|
39
38
|
const result = await payload.countGlobalVersions({
|
|
40
39
|
global: globalSlug,
|
|
40
|
+
overrideAccess: authorizedMCP.overrideAccess,
|
|
41
41
|
req,
|
|
42
|
-
...localAPIDefaults(authorizedMCP),
|
|
43
42
|
...(locale ? { locale } : {}),
|
|
44
43
|
...(where ? { where } : {}),
|
|
45
44
|
})
|
|
@@ -5,7 +5,6 @@ import { z } from 'zod'
|
|
|
5
5
|
import { defaultAccess } from '../../../defaultAccess.js'
|
|
6
6
|
import { defineGlobalTool } from '../../../defineTool.js'
|
|
7
7
|
import { getLogger } from '../../../utils/getLogger.js'
|
|
8
|
-
import { localAPIDefaults } from '../../../utils/localAPIDefaults.js'
|
|
9
8
|
|
|
10
9
|
const DEFAULT_DESCRIPTION = 'Find any Payload global by passing the global slug.'
|
|
11
10
|
|
|
@@ -66,7 +65,8 @@ export const findGlobalTool = defineGlobalTool({
|
|
|
66
65
|
const findOptions: Parameters<typeof payload.findGlobal>[0] = {
|
|
67
66
|
slug: globalSlug,
|
|
68
67
|
depth,
|
|
69
|
-
|
|
68
|
+
overrideAccess: authorizedMCP.overrideAccess,
|
|
69
|
+
req,
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
if (locale) {
|
|
@@ -5,7 +5,6 @@ import { z } from 'zod'
|
|
|
5
5
|
import { defaultAccess } from '../../../defaultAccess.js'
|
|
6
6
|
import { defineGlobalTool } from '../../../defineTool.js'
|
|
7
7
|
import { getLogger } from '../../../utils/getLogger.js'
|
|
8
|
-
import { localAPIDefaults } from '../../../utils/localAPIDefaults.js'
|
|
9
8
|
|
|
10
9
|
const DEFAULT_DESCRIPTION =
|
|
11
10
|
'Find a specific global version in any version-enabled global by passing the global slug and version ID.'
|
|
@@ -70,8 +69,8 @@ export const findGlobalVersionByIDTool = defineGlobalTool({
|
|
|
70
69
|
id,
|
|
71
70
|
slug: globalSlug,
|
|
72
71
|
depth,
|
|
72
|
+
overrideAccess: authorizedMCP.overrideAccess,
|
|
73
73
|
req,
|
|
74
|
-
...localAPIDefaults(authorizedMCP),
|
|
75
74
|
...(fallbackLocale ? { fallbackLocale } : {}),
|
|
76
75
|
...(locale ? { locale } : {}),
|
|
77
76
|
...(populate ? { populate: populate as PopulateType } : {}),
|
|
@@ -5,7 +5,6 @@ import { z } from 'zod'
|
|
|
5
5
|
import { defaultAccess } from '../../../defaultAccess.js'
|
|
6
6
|
import { defineGlobalTool } from '../../../defineTool.js'
|
|
7
7
|
import { getLogger } from '../../../utils/getLogger.js'
|
|
8
|
-
import { localAPIDefaults } from '../../../utils/localAPIDefaults.js'
|
|
9
8
|
import { whereSchema } from '../../../utils/whereSchema.js'
|
|
10
9
|
|
|
11
10
|
const DEFAULT_DESCRIPTION =
|
|
@@ -110,9 +109,9 @@ export const findGlobalVersionsTool = defineGlobalTool({
|
|
|
110
109
|
slug: globalSlug,
|
|
111
110
|
depth,
|
|
112
111
|
limit,
|
|
112
|
+
overrideAccess: authorizedMCP.overrideAccess,
|
|
113
113
|
page,
|
|
114
114
|
req,
|
|
115
|
-
...localAPIDefaults(authorizedMCP),
|
|
116
115
|
...(fallbackLocale ? { fallbackLocale } : {}),
|
|
117
116
|
...(locale ? { locale } : {}),
|
|
118
117
|
...(pagination !== undefined ? { pagination } : {}),
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { getAccessResults } from 'payload'
|
|
2
|
+
|
|
1
3
|
import { defaultAccess } from '../../../defaultAccess.js'
|
|
2
4
|
import { defineGlobalTool } from '../../../defineTool.js'
|
|
3
5
|
import { getGlobalInputSchema } from '../../../utils/schemaConversion/getEntityInputSchema.js'
|
|
@@ -6,7 +8,7 @@ export const getGlobalSchemaTool = defineGlobalTool({
|
|
|
6
8
|
access: (args) => {
|
|
7
9
|
const permissions = args.permissions?.globals?.[args.globalSlug]
|
|
8
10
|
|
|
9
|
-
return defaultAccess(args) && Boolean(permissions?.
|
|
11
|
+
return defaultAccess(args) && Boolean(permissions?.update)
|
|
10
12
|
},
|
|
11
13
|
annotations: {
|
|
12
14
|
destructiveHint: false,
|
|
@@ -16,8 +18,28 @@ export const getGlobalSchemaTool = defineGlobalTool({
|
|
|
16
18
|
title: 'Get Global Schema',
|
|
17
19
|
},
|
|
18
20
|
description: 'Get the input schema for updating a global.',
|
|
19
|
-
}).handler(({ globalSlug, req }) => {
|
|
20
|
-
const
|
|
21
|
+
}).handler(async ({ authorizedMCP, globalSlug, req }) => {
|
|
22
|
+
const permissions = authorizedMCP.overrideAccess
|
|
23
|
+
? null
|
|
24
|
+
: (await getAccessResults({ req })).globals?.[globalSlug]
|
|
25
|
+
|
|
26
|
+
if (!authorizedMCP.overrideAccess && !permissions?.update) {
|
|
27
|
+
return {
|
|
28
|
+
content: [
|
|
29
|
+
{
|
|
30
|
+
type: 'text',
|
|
31
|
+
text: `Error: MCP access to "getGlobalSchema" is not enabled for global "${globalSlug}"`,
|
|
32
|
+
},
|
|
33
|
+
],
|
|
34
|
+
isError: true,
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const inputSchema = getGlobalInputSchema({
|
|
39
|
+
globalSlug,
|
|
40
|
+
req,
|
|
41
|
+
...(permissions ? { permissions } : {}),
|
|
42
|
+
})
|
|
21
43
|
|
|
22
44
|
if (!inputSchema) {
|
|
23
45
|
return {
|
|
@@ -5,7 +5,6 @@ import { z } from 'zod'
|
|
|
5
5
|
import { defaultAccess } from '../../../defaultAccess.js'
|
|
6
6
|
import { defineGlobalTool } from '../../../defineTool.js'
|
|
7
7
|
import { getLogger } from '../../../utils/getLogger.js'
|
|
8
|
-
import { localAPIDefaults } from '../../../utils/localAPIDefaults.js'
|
|
9
8
|
|
|
10
9
|
const DEFAULT_DESCRIPTION =
|
|
11
10
|
'Restore a global from a previous version in any version-enabled global.'
|
|
@@ -62,8 +61,8 @@ export const restoreGlobalVersionTool = defineGlobalTool({
|
|
|
62
61
|
id,
|
|
63
62
|
slug: globalSlug,
|
|
64
63
|
depth,
|
|
64
|
+
overrideAccess: authorizedMCP.overrideAccess,
|
|
65
65
|
req,
|
|
66
|
-
...localAPIDefaults(authorizedMCP),
|
|
67
66
|
...(fallbackLocale ? { fallbackLocale } : {}),
|
|
68
67
|
...(locale ? { locale } : {}),
|
|
69
68
|
...(populate ? { populate: populate as PopulateType } : {}),
|
|
@@ -9,7 +9,6 @@ import {
|
|
|
9
9
|
getGlobalVirtualFieldNames,
|
|
10
10
|
stripVirtualFields,
|
|
11
11
|
} from '../../../utils/getVirtualFieldNames.js'
|
|
12
|
-
import { localAPIDefaults } from '../../../utils/localAPIDefaults.js'
|
|
13
12
|
import { transformPointDataToPayload } from '../../../utils/transformPointDataToPayload.js'
|
|
14
13
|
import { validateGlobalData } from '../validateEntityData.js'
|
|
15
14
|
|
|
@@ -81,7 +80,8 @@ export const updateGlobalTool = defineGlobalTool({
|
|
|
81
80
|
data: parsedData,
|
|
82
81
|
depth,
|
|
83
82
|
draft,
|
|
84
|
-
|
|
83
|
+
overrideAccess: authorizedMCP.overrideAccess,
|
|
84
|
+
req,
|
|
85
85
|
}
|
|
86
86
|
|
|
87
87
|
if (locale) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { CollectionSlug, GlobalSlug, PayloadRequest, SanitizedConfig } from 'payload'
|
|
2
2
|
|
|
3
|
-
import { CfWorkerJsonSchemaValidator } from '@modelcontextprotocol/server'
|
|
3
|
+
import { CfWorkerJsonSchemaValidator } from '@modelcontextprotocol/server/validators/cf-worker'
|
|
4
4
|
|
|
5
5
|
import type { JsonSchemaType, MCPToolResponse } from '../../types.js'
|
|
6
6
|
|
package/src/stdio.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { Config, Plugin, SanitizedConfig } from 'payload'
|
|
2
2
|
|
|
3
3
|
/* eslint-disable no-console */
|
|
4
|
-
import {
|
|
4
|
+
import { serveStdio } from '@modelcontextprotocol/server/stdio'
|
|
5
5
|
import { fileURLToPath, pathToFileURL } from 'node:url'
|
|
6
6
|
import { createLocalReq, getPayload } from 'payload'
|
|
7
7
|
import { findConfig } from 'payload/node'
|
|
@@ -15,23 +15,14 @@ import { getPluginConfig } from './utils/getPluginConfig.js'
|
|
|
15
15
|
import { resolveProjectRoot } from './utils/resolveProjectRoot.js'
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
|
-
*
|
|
18
|
+
* Starts Payload's MCP server over stdin and stdout.
|
|
19
19
|
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
* skips access control for local setup.
|
|
20
|
+
* Set `PAYLOAD_MCP_AUTHORIZATION` to authenticate. In development,
|
|
21
|
+
* `PAYLOAD_MCP_OVERRIDE_ACCESS=true` skips access checks.
|
|
23
22
|
*/
|
|
24
23
|
export const runMcpStdio = async (): Promise<void> => {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
* Payload's cwd-anchored `findConfig()` can't locate the project on
|
|
28
|
-
* its own. This module always lives inside the project's `node_modules`, so
|
|
29
|
-
* we derive the project root from its own path and `chdir` into it.
|
|
30
|
-
*
|
|
31
|
-
* An absolute `PAYLOAD_CONFIG_PATH` still overrides everything; unusual
|
|
32
|
-
* layouts (e.g. a monorepo where the package is hoisted above the app) can
|
|
33
|
-
* fall back to it. See the implementation of findConfig for details.
|
|
34
|
-
*/
|
|
24
|
+
// MCP clients may start this command from another folder. Move to the Payload
|
|
25
|
+
// project so findConfig() can find the config.
|
|
35
26
|
const projectRoot = resolveProjectRoot(fileURLToPath(import.meta.url))
|
|
36
27
|
if (projectRoot) {
|
|
37
28
|
process.chdir(projectRoot)
|
|
@@ -39,29 +30,46 @@ export const runMcpStdio = async (): Promise<void> => {
|
|
|
39
30
|
|
|
40
31
|
const configPath = findConfig()
|
|
41
32
|
const configModule = await import(pathToFileURL(configPath).toString())
|
|
42
|
-
const config = (await (configModule.default ?? configModule)) as
|
|
43
|
-
|
|
44
|
-
const payload = await getPayload({ config })
|
|
33
|
+
const config = (await (configModule.default ?? configModule)) as SanitizedConfig
|
|
45
34
|
|
|
46
35
|
/**
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
36
|
+
* stdout is only for MCP messages. The spec says the server must not write
|
|
37
|
+
* logs there and may write them to stderr instead.
|
|
38
|
+
*
|
|
39
|
+
* The 2.0 client library recovers from stray stdout logs, but that behavior is not
|
|
40
|
+
* guaranteed. Move Payload logs to stderr so Payload does not add invalid data
|
|
41
|
+
* to stdout. Keep options from configurable loggers. Replace pre-built loggers
|
|
42
|
+
* because their output cannot be redirected.
|
|
43
|
+
*
|
|
44
|
+
* @see https://modelcontextprotocol.io/specification/2025-11-25/basic/transports#stdio
|
|
51
45
|
*/
|
|
46
|
+
const loggerConfig: { logger?: Config['logger'] } = config
|
|
47
|
+
if (
|
|
48
|
+
loggerConfig.logger &&
|
|
49
|
+
typeof loggerConfig.logger === 'object' &&
|
|
50
|
+
'options' in loggerConfig.logger
|
|
51
|
+
) {
|
|
52
|
+
loggerConfig.logger.destination = process.stderr
|
|
53
|
+
} else {
|
|
54
|
+
loggerConfig.logger = { destination: process.stderr, options: {} }
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const payload = await getPayload({ config, cron: false, disableOnInit: true })
|
|
58
|
+
|
|
52
59
|
let pluginConfig: SanitizedMCPPluginConfig
|
|
53
60
|
try {
|
|
54
61
|
pluginConfig = getPluginConfig({ config: payload.config })
|
|
55
62
|
} catch {
|
|
63
|
+
// The command also works when mcpPlugin() is not in the Payload config.
|
|
56
64
|
pluginConfig = sanitizeMCPConfig({ config: payload.config, pluginConfig: {} })
|
|
57
65
|
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
66
|
+
const fallbackPlugin: Plugin = (config) => config
|
|
67
|
+
Object.assign(fallbackPlugin, {
|
|
68
|
+
slug: '@payloadcms/plugin-mcp',
|
|
69
|
+
sanitizedOptions: pluginConfig,
|
|
70
|
+
})
|
|
71
|
+
payload.config.plugins ??= []
|
|
72
|
+
payload.config.plugins.push(fallbackPlugin)
|
|
65
73
|
}
|
|
66
74
|
|
|
67
75
|
const overrideAccessEnv = process.env.PAYLOAD_MCP_OVERRIDE_ACCESS
|
|
@@ -86,28 +94,37 @@ export const runMcpStdio = async (): Promise<void> => {
|
|
|
86
94
|
req.payloadAPI = 'MCP' as const
|
|
87
95
|
const authorizedMCP = await getAuthorizedMCP({ overrideAccess, req })
|
|
88
96
|
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
97
|
+
const stdioServer = serveStdio(() => buildMcpServer({ authorizedMCP, pluginConfig, req }), {
|
|
98
|
+
onerror: (err) => {
|
|
99
|
+
// MCP messages use stdout, so write SDK errors to stderr.
|
|
100
|
+
console.error('[payload-mcp] error serving MCP over stdio:', err)
|
|
101
|
+
},
|
|
102
|
+
})
|
|
103
|
+
|
|
104
|
+
// Close the MCP server and Payload when the client disconnects or the process stops.
|
|
105
|
+
let isShuttingDown = false
|
|
106
|
+
const shutdown = async () => {
|
|
107
|
+
if (isShuttingDown) {
|
|
108
|
+
return
|
|
109
|
+
}
|
|
110
|
+
isShuttingDown = true
|
|
93
111
|
|
|
94
|
-
// Process now lives until stdin closes. Wire graceful shutdown so DB
|
|
95
|
-
// connections (and any other Payload-managed resources) get released.
|
|
96
|
-
const shutdown = async (code = 0) => {
|
|
97
112
|
try {
|
|
98
|
-
await
|
|
113
|
+
await stdioServer.close()
|
|
99
114
|
} catch (err) {
|
|
100
115
|
console.error('[payload-mcp] error closing server:', err)
|
|
101
116
|
}
|
|
117
|
+
|
|
102
118
|
try {
|
|
103
119
|
await payload.destroy()
|
|
104
120
|
} catch (err) {
|
|
105
121
|
console.error('[payload-mcp] error destroying payload:', err)
|
|
106
122
|
}
|
|
107
|
-
|
|
123
|
+
|
|
124
|
+
process.exit(0)
|
|
108
125
|
}
|
|
109
126
|
|
|
110
|
-
process.
|
|
111
|
-
process.
|
|
112
|
-
process.stdin.
|
|
127
|
+
process.once('SIGINT', () => void shutdown())
|
|
128
|
+
process.once('SIGTERM', () => void shutdown())
|
|
129
|
+
process.stdin.once('close', () => void shutdown())
|
|
113
130
|
}
|