@payloadcms/plugin-mcp 4.0.0-internal.45cfa3d → 4.0.0-internal.4a6b4c3

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.
Files changed (193) hide show
  1. package/dist/defaultAccess.d.ts.map +1 -1
  2. package/dist/defineTool.d.ts +8 -8
  3. package/dist/defineTool.d.ts.map +1 -1
  4. package/dist/endpoint/access.d.ts +2 -7
  5. package/dist/endpoint/access.d.ts.map +1 -1
  6. package/dist/endpoint/access.js +21 -16
  7. package/dist/endpoint/access.js.map +1 -1
  8. package/dist/endpoint/index.d.ts.map +1 -1
  9. package/dist/endpoint/index.js +46 -4
  10. package/dist/endpoint/index.js.map +1 -1
  11. package/dist/endpoint/oauth.d.ts +35 -0
  12. package/dist/endpoint/oauth.d.ts.map +1 -0
  13. package/dist/endpoint/oauth.js +82 -0
  14. package/dist/endpoint/oauth.js.map +1 -0
  15. package/dist/index.d.ts +8 -0
  16. package/dist/index.d.ts.map +1 -1
  17. package/dist/index.js +12 -1
  18. package/dist/index.js.map +1 -1
  19. package/dist/mcp/buildMcpServer.d.ts +2 -2
  20. package/dist/mcp/buildMcpServer.d.ts.map +1 -1
  21. package/dist/mcp/buildMcpServer.js +36 -24
  22. package/dist/mcp/buildMcpServer.js.map +1 -1
  23. package/dist/mcp/builtin/collections/authTools.d.ts.map +1 -1
  24. package/dist/mcp/builtin/collections/authTools.js +80 -56
  25. package/dist/mcp/builtin/collections/authTools.js.map +1 -1
  26. package/dist/mcp/builtin/collections/countTool.d.ts.map +1 -1
  27. package/dist/mcp/builtin/collections/countTool.js +10 -16
  28. package/dist/mcp/builtin/collections/countTool.js.map +1 -1
  29. package/dist/mcp/builtin/collections/countVersionsTool.d.ts.map +1 -1
  30. package/dist/mcp/builtin/collections/countVersionsTool.js +10 -15
  31. package/dist/mcp/builtin/collections/countVersionsTool.js.map +1 -1
  32. package/dist/mcp/builtin/collections/createTool.d.ts +1 -1
  33. package/dist/mcp/builtin/collections/createTool.d.ts.map +1 -1
  34. package/dist/mcp/builtin/collections/createTool.js +104 -54
  35. package/dist/mcp/builtin/collections/createTool.js.map +1 -1
  36. package/dist/mcp/builtin/collections/deleteTool.d.ts.map +1 -1
  37. package/dist/mcp/builtin/collections/deleteTool.js +45 -45
  38. package/dist/mcp/builtin/collections/deleteTool.js.map +1 -1
  39. package/dist/mcp/builtin/collections/duplicateTool.d.ts.map +1 -1
  40. package/dist/mcp/builtin/collections/duplicateTool.js +32 -39
  41. package/dist/mcp/builtin/collections/duplicateTool.js.map +1 -1
  42. package/dist/mcp/builtin/collections/fileInput.d.ts +28 -0
  43. package/dist/mcp/builtin/collections/fileInput.d.ts.map +1 -0
  44. package/dist/mcp/builtin/collections/fileInput.js +88 -0
  45. package/dist/mcp/builtin/collections/fileInput.js.map +1 -0
  46. package/dist/mcp/builtin/collections/findDistinctTool.d.ts.map +1 -1
  47. package/dist/mcp/builtin/collections/findDistinctTool.js +12 -28
  48. package/dist/mcp/builtin/collections/findDistinctTool.js.map +1 -1
  49. package/dist/mcp/builtin/collections/findTool.d.ts.map +1 -1
  50. package/dist/mcp/builtin/collections/findTool.js +29 -48
  51. package/dist/mcp/builtin/collections/findTool.js.map +1 -1
  52. package/dist/mcp/builtin/collections/findVersionByIDTool.d.ts.map +1 -1
  53. package/dist/mcp/builtin/collections/findVersionByIDTool.js +18 -28
  54. package/dist/mcp/builtin/collections/findVersionByIDTool.js.map +1 -1
  55. package/dist/mcp/builtin/collections/findVersionsTool.d.ts.map +1 -1
  56. package/dist/mcp/builtin/collections/findVersionsTool.js +17 -32
  57. package/dist/mcp/builtin/collections/findVersionsTool.js.map +1 -1
  58. package/dist/mcp/builtin/collections/getCollectionSchemaTool.d.ts.map +1 -1
  59. package/dist/mcp/builtin/collections/getCollectionSchemaTool.js +68 -12
  60. package/dist/mcp/builtin/collections/getCollectionSchemaTool.js.map +1 -1
  61. package/dist/mcp/builtin/collections/restoreVersionTool.d.ts.map +1 -1
  62. package/dist/mcp/builtin/collections/restoreVersionTool.js +15 -28
  63. package/dist/mcp/builtin/collections/restoreVersionTool.js.map +1 -1
  64. package/dist/mcp/builtin/collections/updateTool.d.ts.map +1 -1
  65. package/dist/mcp/builtin/collections/updateTool.js +67 -87
  66. package/dist/mcp/builtin/collections/updateTool.js.map +1 -1
  67. package/dist/mcp/builtin/collections/uploadInstructionsTool.d.ts +2 -0
  68. package/dist/mcp/builtin/collections/uploadInstructionsTool.d.ts.map +1 -0
  69. package/dist/mcp/builtin/collections/uploadInstructionsTool.js +55 -0
  70. package/dist/mcp/builtin/collections/uploadInstructionsTool.js.map +1 -0
  71. package/dist/mcp/builtin/formatEntityError.d.ts +16 -0
  72. package/dist/mcp/builtin/formatEntityError.d.ts.map +1 -0
  73. package/dist/mcp/builtin/formatEntityError.js +55 -0
  74. package/dist/mcp/builtin/formatEntityError.js.map +1 -0
  75. package/dist/mcp/builtin/getConfigInfoTool.d.ts.map +1 -1
  76. package/dist/mcp/builtin/getConfigInfoTool.js +5 -7
  77. package/dist/mcp/builtin/getConfigInfoTool.js.map +1 -1
  78. package/dist/mcp/builtin/globals/countVersionsTool.d.ts.map +1 -1
  79. package/dist/mcp/builtin/globals/countVersionsTool.js +10 -15
  80. package/dist/mcp/builtin/globals/countVersionsTool.js.map +1 -1
  81. package/dist/mcp/builtin/globals/findTool.d.ts.map +1 -1
  82. package/dist/mcp/builtin/globals/findTool.js +12 -18
  83. package/dist/mcp/builtin/globals/findTool.js.map +1 -1
  84. package/dist/mcp/builtin/globals/findVersionByIDTool.d.ts.map +1 -1
  85. package/dist/mcp/builtin/globals/findVersionByIDTool.js +14 -26
  86. package/dist/mcp/builtin/globals/findVersionByIDTool.js.map +1 -1
  87. package/dist/mcp/builtin/globals/findVersionsTool.d.ts.map +1 -1
  88. package/dist/mcp/builtin/globals/findVersionsTool.js +14 -31
  89. package/dist/mcp/builtin/globals/findVersionsTool.js.map +1 -1
  90. package/dist/mcp/builtin/globals/getGlobalSchemaTool.d.ts.map +1 -1
  91. package/dist/mcp/builtin/globals/getGlobalSchemaTool.js +46 -12
  92. package/dist/mcp/builtin/globals/getGlobalSchemaTool.js.map +1 -1
  93. package/dist/mcp/builtin/globals/restoreVersionTool.d.ts.map +1 -1
  94. package/dist/mcp/builtin/globals/restoreVersionTool.js +16 -24
  95. package/dist/mcp/builtin/globals/restoreVersionTool.js.map +1 -1
  96. package/dist/mcp/builtin/globals/updateTool.d.ts.map +1 -1
  97. package/dist/mcp/builtin/globals/updateTool.js +28 -37
  98. package/dist/mcp/builtin/globals/updateTool.js.map +1 -1
  99. package/dist/mcp/builtinTools.d.ts +6 -0
  100. package/dist/mcp/builtinTools.d.ts.map +1 -1
  101. package/dist/mcp/builtinTools.js +9 -3
  102. package/dist/mcp/builtinTools.js.map +1 -1
  103. package/dist/mcp/sanitizeMCPConfig.d.ts.map +1 -1
  104. package/dist/mcp/sanitizeMCPConfig.js +5 -1
  105. package/dist/mcp/sanitizeMCPConfig.js.map +1 -1
  106. package/dist/stdio.d.ts.map +1 -1
  107. package/dist/stdio.js +6 -4
  108. package/dist/stdio.js.map +1 -1
  109. package/dist/types.d.ts +95 -15
  110. package/dist/types.d.ts.map +1 -1
  111. package/dist/types.js +2 -4
  112. package/dist/types.js.map +1 -1
  113. package/dist/utils/camelCase.d.ts.map +1 -1
  114. package/dist/utils/resolveProjectRoot.d.ts.map +1 -1
  115. package/dist/utils/toStandardSchema.d.ts.map +1 -1
  116. package/package.json +6 -8
  117. package/src/endpoint/access.ts +17 -16
  118. package/src/endpoint/index.ts +41 -3
  119. package/src/endpoint/oauth.ts +84 -0
  120. package/src/index.ts +19 -2
  121. package/src/mcp/buildMcpServer.ts +40 -30
  122. package/src/mcp/builtin/collections/authTools.ts +80 -69
  123. package/src/mcp/builtin/collections/countTool.ts +10 -23
  124. package/src/mcp/builtin/collections/countVersionsTool.ts +10 -23
  125. package/src/mcp/builtin/collections/createTool.ts +110 -77
  126. package/src/mcp/builtin/collections/deleteTool.ts +36 -65
  127. package/src/mcp/builtin/collections/duplicateTool.ts +36 -87
  128. package/src/mcp/builtin/collections/fileInput.spec.ts +93 -0
  129. package/src/mcp/builtin/collections/fileInput.ts +127 -0
  130. package/src/mcp/builtin/collections/findDistinctTool.ts +12 -64
  131. package/src/mcp/builtin/collections/findTool.ts +25 -108
  132. package/src/mcp/builtin/collections/findVersionByIDTool.ts +16 -60
  133. package/src/mcp/builtin/collections/findVersionsTool.ts +15 -87
  134. package/src/mcp/builtin/collections/getCollectionSchemaTool.ts +60 -15
  135. package/src/mcp/builtin/collections/restoreVersionTool.ts +15 -58
  136. package/src/mcp/builtin/collections/updateTool.ts +63 -101
  137. package/src/mcp/builtin/collections/uploadInstructionsTool.ts +64 -0
  138. package/src/mcp/builtin/formatEntityError.ts +77 -0
  139. package/src/mcp/builtin/getConfigInfoTool.ts +4 -5
  140. package/src/mcp/builtin/globals/countVersionsTool.ts +10 -22
  141. package/src/mcp/builtin/globals/findTool.ts +14 -53
  142. package/src/mcp/builtin/globals/findVersionByIDTool.ts +14 -54
  143. package/src/mcp/builtin/globals/findVersionsTool.ts +15 -94
  144. package/src/mcp/builtin/globals/getGlobalSchemaTool.ts +41 -9
  145. package/src/mcp/builtin/globals/restoreVersionTool.ts +17 -48
  146. package/src/mcp/builtin/globals/updateTool.ts +39 -62
  147. package/src/mcp/builtinTools.ts +9 -2
  148. package/src/mcp/sanitizeMCPConfig.ts +5 -1
  149. package/src/stdio.ts +4 -3
  150. package/src/types.ts +93 -15
  151. package/dist/mcp/builtin/collections/formatCollectionError.d.ts +0 -9
  152. package/dist/mcp/builtin/collections/formatCollectionError.d.ts.map +0 -1
  153. package/dist/mcp/builtin/collections/formatCollectionError.js +0 -60
  154. package/dist/mcp/builtin/collections/formatCollectionError.js.map +0 -1
  155. package/dist/mcp/builtin/validateEntityData.d.ts +0 -14
  156. package/dist/mcp/builtin/validateEntityData.d.ts.map +0 -1
  157. package/dist/mcp/builtin/validateEntityData.js +0 -82
  158. package/dist/mcp/builtin/validateEntityData.js.map +0 -1
  159. package/dist/utils/getVirtualFieldNames.d.ts +0 -14
  160. package/dist/utils/getVirtualFieldNames.d.ts.map +0 -1
  161. package/dist/utils/getVirtualFieldNames.js +0 -35
  162. package/dist/utils/getVirtualFieldNames.js.map +0 -1
  163. package/dist/utils/localAPIDefaults.d.ts +0 -20
  164. package/dist/utils/localAPIDefaults.d.ts.map +0 -1
  165. package/dist/utils/localAPIDefaults.js +0 -19
  166. package/dist/utils/localAPIDefaults.js.map +0 -1
  167. package/dist/utils/schemaConversion/getEntityInputSchema.d.ts +0 -11
  168. package/dist/utils/schemaConversion/getEntityInputSchema.d.ts.map +0 -1
  169. package/dist/utils/schemaConversion/getEntityInputSchema.js +0 -32
  170. package/dist/utils/schemaConversion/getEntityInputSchema.js.map +0 -1
  171. package/dist/utils/schemaConversion/sanitizeEntitySchema.d.ts +0 -10
  172. package/dist/utils/schemaConversion/sanitizeEntitySchema.d.ts.map +0 -1
  173. package/dist/utils/schemaConversion/sanitizeEntitySchema.js +0 -384
  174. package/dist/utils/schemaConversion/sanitizeEntitySchema.js.map +0 -1
  175. package/dist/utils/schemaConversion/sanitizeEntitySchema.spec.js +0 -133
  176. package/dist/utils/schemaConversion/sanitizeEntitySchema.spec.js.map +0 -1
  177. package/dist/utils/transformPointDataToPayload.d.ts +0 -7
  178. package/dist/utils/transformPointDataToPayload.d.ts.map +0 -1
  179. package/dist/utils/transformPointDataToPayload.js +0 -28
  180. package/dist/utils/transformPointDataToPayload.js.map +0 -1
  181. package/dist/utils/whereSchema.d.ts +0 -9
  182. package/dist/utils/whereSchema.d.ts.map +0 -1
  183. package/dist/utils/whereSchema.js +0 -13
  184. package/dist/utils/whereSchema.js.map +0 -1
  185. package/src/mcp/builtin/collections/formatCollectionError.ts +0 -84
  186. package/src/mcp/builtin/validateEntityData.ts +0 -132
  187. package/src/utils/getVirtualFieldNames.ts +0 -53
  188. package/src/utils/localAPIDefaults.ts +0 -22
  189. package/src/utils/schemaConversion/getEntityInputSchema.ts +0 -62
  190. package/src/utils/schemaConversion/sanitizeEntitySchema.spec.ts +0 -96
  191. package/src/utils/schemaConversion/sanitizeEntitySchema.ts +0 -432
  192. package/src/utils/transformPointDataToPayload.ts +0 -40
  193. package/src/utils/whereSchema.ts +0 -24
@@ -1,12 +1,14 @@
1
+ import { getAccessResults, getGlobalInputSchema, getGlobalSchemaInputSchema } from 'payload'
2
+ import { getLLMInstructions } from 'payload/internal'
3
+
1
4
  import { defaultAccess } from '../../../defaultAccess.js'
2
5
  import { defineGlobalTool } from '../../../defineTool.js'
3
- import { getGlobalInputSchema } from '../../../utils/schemaConversion/getEntityInputSchema.js'
4
6
 
5
7
  export const getGlobalSchemaTool = defineGlobalTool({
6
8
  access: (args) => {
7
- const permissions = args.permissions?.globals?.[args.globalSlug]
9
+ const permissions = args.permissions?.globals?.[args.slug]
8
10
 
9
- return defaultAccess(args) && Boolean(permissions?.read || permissions?.update)
11
+ return defaultAccess(args) && Boolean(permissions?.update)
10
12
  },
11
13
  annotations: {
12
14
  destructiveHint: false,
@@ -15,27 +17,57 @@ export const getGlobalSchemaTool = defineGlobalTool({
15
17
  readOnlyHint: true,
16
18
  title: 'Get Global Schema',
17
19
  },
18
- description: 'Get the input schema for updating a global.',
19
- }).handler(({ globalSlug, req }) => {
20
- const inputSchema = getGlobalInputSchema({ globalSlug, req })
20
+ description: 'Get the input schema and LLM instructions before updating a global.',
21
+ input: getGlobalSchemaInputSchema,
22
+ }).handler(async ({ slug, authorizedMCP, req }) => {
23
+ const permissions = authorizedMCP.overrideAccess
24
+ ? null
25
+ : (await getAccessResults({ req })).globals?.[slug]
26
+
27
+ if (!authorizedMCP.overrideAccess && !permissions?.update) {
28
+ return {
29
+ content: [
30
+ {
31
+ type: 'text',
32
+ text: `Error: MCP access to "getGlobalSchema" is not enabled for global "${slug}"`,
33
+ },
34
+ ],
35
+ isError: true,
36
+ }
37
+ }
38
+
39
+ const inputSchema = getGlobalInputSchema({
40
+ globalSlug: slug,
41
+ req,
42
+ ...(permissions ? { permissions } : {}),
43
+ })
21
44
 
22
45
  if (!inputSchema) {
23
46
  return {
24
- content: [{ type: 'text', text: `Error: Global "${globalSlug}" not found` }],
47
+ content: [{ type: 'text', text: `Error: Global "${slug}" not found` }],
25
48
  isError: true,
26
49
  }
27
50
  }
28
51
 
52
+ const instructions = await getLLMInstructions({
53
+ slug,
54
+ type: 'global',
55
+ overrideAccess: authorizedMCP.overrideAccess,
56
+ req,
57
+ })
58
+
29
59
  return {
30
60
  content: [
31
61
  {
32
62
  type: 'text',
33
- text: `Schema for global "${globalSlug}":\n\`\`\`json\n${JSON.stringify(inputSchema)}\n\`\`\``,
63
+ text: `Schema for global "${slug}":\n\`\`\`json\n${JSON.stringify(inputSchema)}\n\`\`\``,
34
64
  },
65
+ ...(instructions ? [{ type: 'text' as const, text: instructions }] : []),
35
66
  ],
36
67
  structuredContent: {
37
- globalSlug,
68
+ slug,
38
69
  schema: inputSchema,
70
+ ...(instructions ? { instructions } : {}),
39
71
  },
40
72
  }
41
73
  })
@@ -1,17 +1,14 @@
1
- import type { PopulateType } from 'payload'
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'
7
5
  import { getLogger } from '../../../utils/getLogger.js'
8
- import { localAPIDefaults } from '../../../utils/localAPIDefaults.js'
9
6
 
10
- const DEFAULT_DESCRIPTION = 'Restore a global from a previous version in any version-enabled global.'
7
+ const DEFAULT_DESCRIPTION =
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: z.object({
24
- id: z.string().describe('The ID of the global version to restore'),
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, showHiddenFields } = input
24
+ const { id, depth, fallbackLocale, locale, populate, select } = input
56
25
 
57
- logger.info(`Restoring version for global: ${globalSlug} with ID: ${id}`)
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: globalSlug,
30
+ id: String(id),
31
+ slug,
63
32
  depth,
33
+ overrideAccess: authorizedMCP.overrideAccess,
64
34
  req,
65
- ...localAPIDefaults(authorizedMCP),
66
- ...(fallbackLocale ? { fallbackLocale } : {}),
35
+ ...(fallbackLocale !== undefined ? { fallbackLocale } : {}),
67
36
  ...(locale ? { locale } : {}),
68
- ...(populate ? { populate: populate as PopulateType } : {}),
69
- ...(showHiddenFields !== undefined ? { showHiddenFields } : {}),
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 "${globalSlug}"!\nRestored global:\n\`\`\`json\n${JSON.stringify(restoredGlobal)}\n\`\`\``,
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 ${globalSlug}: ${errorMessage}`)
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 "${globalSlug}":** ${errorMessage}`,
62
+ text: `❌ **Error restoring version "${id}" for global "${slug}":** ${errorMessage}`,
94
63
  },
95
64
  ],
96
65
  isError: true,
@@ -1,23 +1,20 @@
1
- import type { SelectType } from 'payload'
2
-
3
- import { z } from 'zod'
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 { localAPIDefaults } from '../../../utils/localAPIDefaults.js'
13
- import { transformPointDataToPayload } from '../../../utils/transformPointDataToPayload.js'
14
- import { validateGlobalData } from '../validateEntityData.js'
12
+ import { formatEntityError } from '../formatEntityError.js'
15
13
 
16
14
  const DEFAULT_DESCRIPTION = 'Update any Payload global by passing the global slug and data.'
17
15
 
18
16
  export const updateGlobalTool = defineGlobalTool({
19
- access: (args) =>
20
- defaultAccess(args) && Boolean(args.permissions?.globals?.[args.globalSlug]?.update),
17
+ access: (args) => defaultAccess(args) && Boolean(args.permissions?.globals?.[args.slug]?.update),
21
18
  annotations: {
22
19
  destructiveHint: true,
23
20
  idempotentHint: false,
@@ -26,72 +23,54 @@ export const updateGlobalTool = defineGlobalTool({
26
23
  title: 'Update Global',
27
24
  },
28
25
  description: DEFAULT_DESCRIPTION,
29
- input: z.object({
30
- data: z.record(z.string(), z.unknown()).describe('The global fields to update'),
31
- depth: z
32
- .number()
33
- .describe('Optional: Depth of relationships to populate')
34
- .optional()
35
- .default(0),
36
- draft: z
37
- .boolean()
38
- .describe('Optional: Whether to save as draft (default: false)')
39
- .optional()
40
- .default(false),
41
- fallbackLocale: z
42
- .string()
43
- .describe('Optional: fallback locale code to use when requested locale is not available')
44
- .optional(),
45
- locale: z
46
- .string()
47
- .describe(
48
- 'Optional: locale code to update data in (e.g., "en", "es"). Use "all" to update all locales for localized fields',
49
- )
50
- .optional(),
51
- select: z
52
- .record(z.string(), z.unknown())
53
- .describe(
54
- 'Optional: define exactly which fields you\'d like to return in the response, e.g., {"siteName": true}',
55
- )
56
- .optional(),
57
- }),
58
- }).handler(async ({ authorizedMCP, globalSlug, input, req }) => {
26
+ input: updateGlobalInputSchema,
27
+ }).handler(async ({ slug, authorizedMCP, input, req }) => {
59
28
  const payload = req.payload
60
29
  const logger = getLogger({ payload })
61
30
 
62
- const { data, depth, draft, fallbackLocale, locale, select } = input
31
+ const {
32
+ data,
33
+ depth,
34
+ draft,
35
+ fallbackLocale,
36
+ locale,
37
+ overrideLock,
38
+ populate,
39
+ publishAllLocales,
40
+ select,
41
+ unpublishAllLocales,
42
+ } = input
63
43
 
64
- logger.info(
65
- `Updating global: ${globalSlug}, draft: ${draft}${locale ? `, locale: ${locale}` : ''}`,
66
- )
44
+ logger.info(`Updating global: ${slug}, draft: ${draft}${locale ? `, locale: ${locale}` : ''}`)
67
45
 
68
46
  try {
69
- const virtualFieldNames = getGlobalVirtualFieldNames(payload.config, globalSlug)
47
+ const virtualFieldNames = getGlobalVirtualFieldNames(payload.config, slug)
70
48
  const inputData = stripVirtualFields(data, virtualFieldNames)
71
- const validationError = validateGlobalData({ data: inputData, globalSlug, req })
72
-
73
- if (validationError) {
74
- return validationError
75
- }
49
+ validateGlobalData({ slug, data: inputData, req })
76
50
 
77
51
  const parsedData = transformPointDataToPayload(inputData)
78
52
 
79
53
  const updateOptions: Parameters<typeof payload.updateGlobal>[0] = {
80
- slug: globalSlug,
54
+ slug,
81
55
  data: parsedData,
82
56
  depth,
83
57
  draft,
84
- ...localAPIDefaults(authorizedMCP),
58
+ overrideAccess: authorizedMCP.overrideAccess,
59
+ overrideLock,
60
+ populate,
61
+ publishAllLocales,
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 as SelectType
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 "${globalSlug}" updated successfully!\n\`\`\`json\n${JSON.stringify(result)}\n\`\`\``,
82
+ text: `Global "${slug}" updated successfully!\n\`\`\`json\n${JSON.stringify(result)}\n\`\`\``,
104
83
  },
105
84
  ],
106
85
  doc: result as Record<string, unknown>,
107
86
  }
108
87
  } catch (error) {
109
- const errorMessage = error instanceof Error ? error.message : 'Unknown error'
110
- logger.error(`Error updating global ${globalSlug}: ${errorMessage}`)
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
  })
@@ -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 { createDocumentTool } from './builtin/collections/createTool.js'
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'
@@ -20,6 +20,7 @@ import { findVersionsTool } from './builtin/collections/findVersionsTool.js'
20
20
  import { getCollectionSchemaTool } from './builtin/collections/getCollectionSchemaTool.js'
21
21
  import { restoreVersionTool } from './builtin/collections/restoreVersionTool.js'
22
22
  import { updateDocumentTool } from './builtin/collections/updateTool.js'
23
+ import { getUploadInstructionsTool } from './builtin/collections/uploadInstructionsTool.js'
23
24
  import { getConfigInfoTool } from './builtin/getConfigInfoTool.js'
24
25
  import { countGlobalVersionsTool } from './builtin/globals/countVersionsTool.js'
25
26
  import { findGlobalTool } from './builtin/globals/findTool.js'
@@ -32,6 +33,7 @@ import { updateGlobalTool } from './builtin/globals/updateTool.js'
32
33
  type CollectionBuiltin = {
33
34
  mcpName: string
34
35
  requiresDuplicateEnabled?: boolean
36
+ requiresUpload?: boolean
35
37
  requiresVersions?: boolean
36
38
  tool: CollectionTool
37
39
  }
@@ -54,7 +56,7 @@ export const TOOL_BUILTINS = {
54
56
  export const COLLECTION_BUILTINS = {
55
57
  count: { mcpName: 'countDocuments', tool: countDocumentsTool },
56
58
  countVersions: { mcpName: 'countVersions', requiresVersions: true, tool: countVersionsTool },
57
- create: { mcpName: 'createDocument', tool: createDocumentTool },
59
+ create: { mcpName: 'createDocuments', tool: createDocumentsTool },
58
60
  delete: { mcpName: 'deleteDocuments', tool: deleteDocumentsTool },
59
61
  duplicate: {
60
62
  mcpName: 'duplicateDocument',
@@ -70,6 +72,11 @@ export const COLLECTION_BUILTINS = {
70
72
  },
71
73
  findVersions: { mcpName: 'findVersions', requiresVersions: true, tool: findVersionsTool },
72
74
  getCollectionSchema: { mcpName: 'getCollectionSchema', tool: getCollectionSchemaTool },
75
+ getUploadInstructions: {
76
+ mcpName: 'getUploadInstructions',
77
+ requiresUpload: true,
78
+ tool: getUploadInstructionsTool,
79
+ },
73
80
  restoreVersion: { mcpName: 'restoreVersion', requiresVersions: true, tool: restoreVersionTool },
74
81
  update: { mcpName: 'updateDocument', tool: updateDocumentTool },
75
82
  } satisfies Record<string, CollectionBuiltin>
@@ -103,6 +103,7 @@ export const sanitizeMCPConfig = ({
103
103
  hooks: pluginConfig.hooks,
104
104
  items,
105
105
  mcp: pluginConfig.mcp,
106
+ oauth: pluginConfig.oauth,
106
107
  overrideGetAuthorizedMCP: pluginConfig.overrideGetAuthorizedMCP,
107
108
  }
108
109
  }
@@ -127,7 +128,7 @@ const sanitizeCollectionConfig = ({
127
128
 
128
129
  for (const [
129
130
  toolKey,
130
- { mcpName, requiresDuplicateEnabled, requiresVersions, tool },
131
+ { mcpName, requiresDuplicateEnabled, requiresUpload, requiresVersions, tool },
131
132
  ] of COLLECTION_BUILTIN_ENTRIES) {
132
133
  if (requiresVersions && !collection.versions) {
133
134
  continue
@@ -135,6 +136,9 @@ const sanitizeCollectionConfig = ({
135
136
  if (requiresDuplicateEnabled && isDuplicateDisabled) {
136
137
  continue
137
138
  }
139
+ if (requiresUpload && !collection.upload) {
140
+ continue
141
+ }
138
142
  const matchedConfigEntry = collectionPluginConfig?.tools?.[toolKey]
139
143
  if (matchedConfigEntry === false) {
140
144
  continue
package/src/stdio.ts CHANGED
@@ -3,8 +3,8 @@ 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 { createLocalReq, getPayload } from 'payload'
7
- import { findConfig } from 'payload/node'
6
+ import { createPayloadRequest, getPayload } from 'payload'
7
+ import { findConfig, loadEnv } from 'payload/node'
8
8
 
9
9
  import type { SanitizedMCPPluginConfig } from './types.js'
10
10
 
@@ -28,6 +28,7 @@ export const runMcpStdio = async (): Promise<void> => {
28
28
  process.chdir(projectRoot)
29
29
  }
30
30
 
31
+ loadEnv()
31
32
  const configPath = findConfig()
32
33
  const configModule = await import(pathToFileURL(configPath).toString())
33
34
  const config = (await (configModule.default ?? configModule)) as SanitizedConfig
@@ -90,7 +91,7 @@ export const runMcpStdio = async (): Promise<void> => {
90
91
  headers.set('Authorization', process.env.PAYLOAD_MCP_AUTHORIZATION)
91
92
  }
92
93
 
93
- const req = await createLocalReq({ req: { headers } }, payload)
94
+ const req = await createPayloadRequest({ payload, req: { headers } })
94
95
  req.payloadAPI = 'MCP' as const
95
96
  const authorizedMCP = await getAuthorizedMCP({ overrideAccess, req })
96
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
- McpServer,
6
+ McpServerOptions,
6
7
  ResourceTemplate,
7
8
  ServerContext,
8
9
  StandardSchemaWithJSON,
@@ -15,7 +16,6 @@ import type {
15
16
  MaybePromise,
16
17
  PayloadRequest,
17
18
  SanitizedPermissions,
18
- User,
19
19
  } from 'payload'
20
20
 
21
21
  import type { GetAuthorizedMCPArgs } from './endpoint/access.js'
@@ -76,11 +76,11 @@ export type MCPAccessArgs = {
76
76
  }
77
77
 
78
78
  export type CollectionMCPAccessArgs = {
79
- collectionSlug: CollectionSlug
79
+ slug: CollectionSlug
80
80
  } & MCPAccessArgs
81
81
 
82
82
  export type GlobalMCPAccessArgs = {
83
- globalSlug: GlobalSlug
83
+ slug: GlobalSlug
84
84
  } & MCPAccessArgs
85
85
 
86
86
  export type ToolHandlerArgs<TSchema = undefined> = {
@@ -91,14 +91,19 @@ export type ToolHandlerArgs<TSchema = undefined> = {
91
91
  }
92
92
 
93
93
  export type CollectionToolHandlerArgs<TSchema = undefined> = {
94
- collectionSlug: CollectionSlug
94
+ slug: CollectionSlug
95
95
  } & ToolHandlerArgs<TSchema>
96
96
 
97
97
  export type GlobalToolHandlerArgs<TSchema = undefined> = {
98
- globalSlug: GlobalSlug
98
+ slug: GlobalSlug
99
99
  } & ToolHandlerArgs<TSchema>
100
100
 
101
101
  export type Tool<TSchema extends ToolInputSchema | undefined = ToolInputSchema | undefined> = {
102
+ /**
103
+ * Runs while authorizing each MCP request, before the tool is advertised or called. Return
104
+ * `false` to make the tool unavailable for that request. This is skipped when `overrideAccess`
105
+ * is enabled.
106
+ */
102
107
  access?: (args: MCPAccessArgs) => MaybePromise<boolean>
103
108
  annotations?: ToolAnnotations
104
109
  description: string
@@ -113,6 +118,12 @@ export type Tool<TSchema extends ToolInputSchema | undefined = ToolInputSchema |
113
118
  export type CollectionTool<
114
119
  TSchema extends ToolInputSchema | undefined = ToolInputSchema | undefined,
115
120
  > = {
121
+ /**
122
+ * Runs while authorizing each MCP request for this collection. Return `false` to reject calls
123
+ * to this tool for the collection. The shared tool is not advertised when no collections allow
124
+ * it, but can remain advertised when it is available for another collection. This is skipped
125
+ * when `overrideAccess` is enabled.
126
+ */
116
127
  access?: (args: CollectionMCPAccessArgs) => MaybePromise<boolean>
117
128
  handler: (args: CollectionToolHandlerArgs<TSchema>) => MaybePromise<MCPToolResponse>
118
129
  input?: TSchema
@@ -120,6 +131,12 @@ export type CollectionTool<
120
131
 
121
132
  export type GlobalTool<TSchema extends ToolInputSchema | undefined = ToolInputSchema | undefined> =
122
133
  {
134
+ /**
135
+ * Runs while authorizing each MCP request for this global. Return `false` to reject calls to
136
+ * this tool for the global. The shared tool is not advertised when no globals allow it, but
137
+ * can remain advertised when it is available for another global. This is skipped when
138
+ * `overrideAccess` is enabled.
139
+ */
123
140
  access?: (args: GlobalMCPAccessArgs) => MaybePromise<boolean>
124
141
  handler: (args: GlobalToolHandlerArgs<TSchema>) => MaybePromise<MCPToolResponse>
125
142
  input?: TSchema
@@ -131,6 +148,10 @@ export type GlobalTool<TSchema extends ToolInputSchema | undefined = ToolInputSc
131
148
  * required handler) from being silently accepted at a built-in key slot.
132
149
  */
133
150
  export type MCPBuiltInCollectionToolOverride = {
151
+ /**
152
+ * Replaces the built-in tool's access check. Return `false` to make the tool unavailable for
153
+ * this collection. This is skipped when `overrideAccess` is enabled.
154
+ */
134
155
  access?: (args: CollectionMCPAccessArgs) => MaybePromise<boolean>
135
156
  annotations?: ToolAnnotations
136
157
  description?: string
@@ -139,6 +160,10 @@ export type MCPBuiltInCollectionToolOverride = {
139
160
  }
140
161
 
141
162
  export type MCPBuiltInGlobalToolOverride = {
163
+ /**
164
+ * Replaces the built-in tool's access check. Return `false` to make the tool unavailable for
165
+ * this global. This is skipped when `overrideAccess` is enabled.
166
+ */
142
167
  access?: (args: GlobalMCPAccessArgs) => MaybePromise<boolean>
143
168
  annotations?: ToolAnnotations
144
169
  description?: string
@@ -183,6 +208,11 @@ export type PromptHandlerArgs<TSchema = undefined> = {
183
208
  }
184
209
 
185
210
  export type Prompt<TSchema extends ToolInputSchema = ToolInputSchema> = {
211
+ /**
212
+ * Runs while authorizing each MCP request, before the prompt is advertised or used. Return
213
+ * `false` to make the prompt unavailable for that request. This is skipped when
214
+ * `overrideAccess` is enabled.
215
+ */
186
216
  access?: (args: MCPAccessArgs) => MaybePromise<boolean>
187
217
  argsSchema: TSchema
188
218
  description: string
@@ -201,6 +231,11 @@ export type ResourceHandlerArgs = {
201
231
  }
202
232
 
203
233
  export type Resource = {
234
+ /**
235
+ * Runs while authorizing each MCP request, before the resource is advertised or read. Return
236
+ * `false` to make the resource unavailable for that request. This is skipped when
237
+ * `overrideAccess` is enabled.
238
+ */
204
239
  access?: (args: MCPAccessArgs) => MaybePromise<boolean>
205
240
  description: string
206
241
  handler: (args: ResourceHandlerArgs) => MaybePromise<{
@@ -245,10 +280,56 @@ export type MCPPluginConfig = {
245
280
  afterToolCall?: MCPAfterToolCallHook[]
246
281
  }
247
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
248
290
  serverOptions?: MCPServerOptions
249
291
  verboseLogs?: boolean
250
292
  }
251
- /** Replace the default MCP authorization resolver. */
293
+ /**
294
+ * Lets MCP clients sign in through an OAuth authorization server. MCP requests without an
295
+ * authenticated user get a `401` that points to the protected resource metadata (RFC 9728),
296
+ * served by `oauthProtectedResourceHandler`. Payload's auth strategies must accept the
297
+ * issued access tokens.
298
+ */
299
+ oauth?: {
300
+ /**
301
+ * Called on MCP requests with a bearer token that Payload's auth strategies didn't accept.
302
+ * Return the Payload user, including its `collection`, or `null` to answer with the OAuth challenge.
303
+ */
304
+ authenticate?: (args: {
305
+ req: PayloadRequest
306
+ token: string
307
+ }) => MaybePromise<PayloadRequest['user']>
308
+ /**
309
+ * The authorization servers that issue access tokens for MCP clients. Clients require each one
310
+ * to exactly match the `issuer` in that server's metadata, so pass a function when the exact
311
+ * value is only known at runtime, e.g. from the server's OpenID configuration or per host.
312
+ */
313
+ authorizationServers: ((args: { req: PayloadRequest }) => MaybePromise<string[]>) | string[]
314
+ /**
315
+ * The URL clients call to reach the MCP endpoint.
316
+ *
317
+ * @default the absolute URL of `/api/mcp`, based on `serverURL` or the request URL
318
+ */
319
+ resource?: string
320
+ /**
321
+ * Scopes MCP clients should request, e.g. `['openid', 'email', 'profile']`. Without them,
322
+ * clients request none, which some authorization servers reject or answer with a token that
323
+ * doesn't identify the user.
324
+ */
325
+ scopes?: string[]
326
+ }
327
+ /**
328
+ * Replace the default MCP authorization resolver.
329
+ *
330
+ * This hook replaces the default authentication flow. It must set `req.user` to the
331
+ * authenticated Payload user, or to `null` for an anonymous caller, before returning.
332
+ */
252
333
  overrideGetAuthorizedMCP?: (
253
334
  args: {
254
335
  pluginConfig: SanitizedMCPPluginConfig
@@ -262,11 +343,11 @@ export type MCPPluginConfig = {
262
343
 
263
344
  export type SanitizedMCPPluginConfig = {
264
345
  items: MCPItem[]
265
- } & Pick<MCPPluginConfig, 'disabled' | 'hooks' | 'mcp' | 'overrideGetAuthorizedMCP'>
346
+ } & Pick<MCPPluginConfig, 'disabled' | 'hooks' | 'mcp' | 'oauth' | 'overrideGetAuthorizedMCP'>
266
347
 
267
348
  export type MCPServerOptions = {
268
- options?: ConstructorParameters<typeof McpServer>[1]
269
- serverInfo?: Partial<ConstructorParameters<typeof McpServer>[0]>
349
+ options?: McpServerOptions
350
+ serverInfo?: Partial<Implementation>
270
351
  }
271
352
 
272
353
  /**
@@ -312,13 +393,10 @@ export type MCPItem =
312
393
  | GlobalMCPItem
313
394
 
314
395
  /**
315
- * The caller's identity + the MCP items authorized for this request. Disabled
316
- * items and items blocked by access callbacks or Payload operation access are
317
- * absent from `items`. Tool handlers receive this via `args.authorizedMCP` so
318
- * they can spread `localAPIDefaults(authorizedMCP)` into every local API call.
396
+ * The MCP items and access mode authorized for this request. The authenticated user is available
397
+ * as `req.user`.
319
398
  */
320
399
  export type AuthorizedMCP = {
321
400
  items: MCPItem[]
322
401
  overrideAccess: boolean
323
- user: null | User
324
402
  }
@@ -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,GAAI,yCAKnC;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"}