@payloadcms/plugin-mcp 4.0.0-internal.cd69eef → 4.0.0-internal.ce66a41

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 (176) hide show
  1. package/bin.js +0 -7
  2. package/dist/endpoint/access.js +2 -2
  3. package/dist/endpoint/access.js.map +1 -1
  4. package/dist/endpoint/index.d.ts.map +1 -1
  5. package/dist/endpoint/index.js +33 -4
  6. package/dist/endpoint/index.js.map +1 -1
  7. package/dist/mcp/buildMcpServer.d.ts +2 -2
  8. package/dist/mcp/buildMcpServer.d.ts.map +1 -1
  9. package/dist/mcp/buildMcpServer.js +36 -24
  10. package/dist/mcp/buildMcpServer.js.map +1 -1
  11. package/dist/mcp/builtin/collections/authTools.d.ts.map +1 -1
  12. package/dist/mcp/builtin/collections/authTools.js +80 -56
  13. package/dist/mcp/builtin/collections/authTools.js.map +1 -1
  14. package/dist/mcp/builtin/collections/countTool.d.ts.map +1 -1
  15. package/dist/mcp/builtin/collections/countTool.js +9 -14
  16. package/dist/mcp/builtin/collections/countTool.js.map +1 -1
  17. package/dist/mcp/builtin/collections/countVersionsTool.d.ts.map +1 -1
  18. package/dist/mcp/builtin/collections/countVersionsTool.js +9 -13
  19. package/dist/mcp/builtin/collections/countVersionsTool.js.map +1 -1
  20. package/dist/mcp/builtin/collections/createTool.d.ts +1 -1
  21. package/dist/mcp/builtin/collections/createTool.d.ts.map +1 -1
  22. package/dist/mcp/builtin/collections/createTool.js +104 -63
  23. package/dist/mcp/builtin/collections/createTool.js.map +1 -1
  24. package/dist/mcp/builtin/collections/deleteTool.d.ts.map +1 -1
  25. package/dist/mcp/builtin/collections/deleteTool.js +44 -43
  26. package/dist/mcp/builtin/collections/deleteTool.js.map +1 -1
  27. package/dist/mcp/builtin/collections/duplicateTool.d.ts.map +1 -1
  28. package/dist/mcp/builtin/collections/duplicateTool.js +31 -37
  29. package/dist/mcp/builtin/collections/duplicateTool.js.map +1 -1
  30. package/dist/mcp/builtin/collections/fileInput.d.ts +21 -13
  31. package/dist/mcp/builtin/collections/fileInput.d.ts.map +1 -1
  32. package/dist/mcp/builtin/collections/fileInput.js +52 -64
  33. package/dist/mcp/builtin/collections/fileInput.js.map +1 -1
  34. package/dist/mcp/builtin/collections/findDistinctTool.d.ts.map +1 -1
  35. package/dist/mcp/builtin/collections/findDistinctTool.js +11 -26
  36. package/dist/mcp/builtin/collections/findDistinctTool.js.map +1 -1
  37. package/dist/mcp/builtin/collections/findTool.d.ts.map +1 -1
  38. package/dist/mcp/builtin/collections/findTool.js +27 -45
  39. package/dist/mcp/builtin/collections/findTool.js.map +1 -1
  40. package/dist/mcp/builtin/collections/findVersionByIDTool.d.ts.map +1 -1
  41. package/dist/mcp/builtin/collections/findVersionByIDTool.js +17 -26
  42. package/dist/mcp/builtin/collections/findVersionByIDTool.js.map +1 -1
  43. package/dist/mcp/builtin/collections/findVersionsTool.d.ts.map +1 -1
  44. package/dist/mcp/builtin/collections/findVersionsTool.js +16 -30
  45. package/dist/mcp/builtin/collections/findVersionsTool.js.map +1 -1
  46. package/dist/mcp/builtin/collections/getCollectionSchemaTool.d.ts.map +1 -1
  47. package/dist/mcp/builtin/collections/getCollectionSchemaTool.js +33 -16
  48. package/dist/mcp/builtin/collections/getCollectionSchemaTool.js.map +1 -1
  49. package/dist/mcp/builtin/collections/restoreVersionTool.d.ts.map +1 -1
  50. package/dist/mcp/builtin/collections/restoreVersionTool.js +14 -26
  51. package/dist/mcp/builtin/collections/restoreVersionTool.js.map +1 -1
  52. package/dist/mcp/builtin/collections/updateTool.d.ts.map +1 -1
  53. package/dist/mcp/builtin/collections/updateTool.js +58 -90
  54. package/dist/mcp/builtin/collections/updateTool.js.map +1 -1
  55. package/dist/mcp/builtin/collections/uploadInstructionsTool.d.ts +2 -0
  56. package/dist/mcp/builtin/collections/uploadInstructionsTool.d.ts.map +1 -0
  57. package/dist/mcp/builtin/collections/uploadInstructionsTool.js +55 -0
  58. package/dist/mcp/builtin/collections/uploadInstructionsTool.js.map +1 -0
  59. package/dist/mcp/builtin/formatEntityError.d.ts +16 -0
  60. package/dist/mcp/builtin/formatEntityError.d.ts.map +1 -0
  61. package/dist/mcp/builtin/formatEntityError.js +55 -0
  62. package/dist/mcp/builtin/formatEntityError.js.map +1 -0
  63. package/dist/mcp/builtin/getConfigInfoTool.d.ts.map +1 -1
  64. package/dist/mcp/builtin/getConfigInfoTool.js +3 -2
  65. package/dist/mcp/builtin/getConfigInfoTool.js.map +1 -1
  66. package/dist/mcp/builtin/globals/countVersionsTool.d.ts.map +1 -1
  67. package/dist/mcp/builtin/globals/countVersionsTool.js +9 -13
  68. package/dist/mcp/builtin/globals/countVersionsTool.js.map +1 -1
  69. package/dist/mcp/builtin/globals/findTool.d.ts.map +1 -1
  70. package/dist/mcp/builtin/globals/findTool.js +10 -16
  71. package/dist/mcp/builtin/globals/findTool.js.map +1 -1
  72. package/dist/mcp/builtin/globals/findVersionByIDTool.d.ts.map +1 -1
  73. package/dist/mcp/builtin/globals/findVersionByIDTool.js +13 -24
  74. package/dist/mcp/builtin/globals/findVersionByIDTool.js.map +1 -1
  75. package/dist/mcp/builtin/globals/findVersionsTool.d.ts.map +1 -1
  76. package/dist/mcp/builtin/globals/findVersionsTool.js +13 -29
  77. package/dist/mcp/builtin/globals/findVersionsTool.js.map +1 -1
  78. package/dist/mcp/builtin/globals/getGlobalSchemaTool.d.ts.map +1 -1
  79. package/dist/mcp/builtin/globals/getGlobalSchemaTool.js +29 -13
  80. package/dist/mcp/builtin/globals/getGlobalSchemaTool.js.map +1 -1
  81. package/dist/mcp/builtin/globals/restoreVersionTool.d.ts.map +1 -1
  82. package/dist/mcp/builtin/globals/restoreVersionTool.js +15 -22
  83. package/dist/mcp/builtin/globals/restoreVersionTool.js.map +1 -1
  84. package/dist/mcp/builtin/globals/updateTool.d.ts.map +1 -1
  85. package/dist/mcp/builtin/globals/updateTool.js +27 -36
  86. package/dist/mcp/builtin/globals/updateTool.js.map +1 -1
  87. package/dist/mcp/builtinTools.d.ts +6 -0
  88. package/dist/mcp/builtinTools.d.ts.map +1 -1
  89. package/dist/mcp/builtinTools.js +9 -3
  90. package/dist/mcp/builtinTools.js.map +1 -1
  91. package/dist/mcp/sanitizeMCPConfig.js +4 -1
  92. package/dist/mcp/sanitizeMCPConfig.js.map +1 -1
  93. package/dist/stdio.d.ts.map +1 -1
  94. package/dist/stdio.js +6 -4
  95. package/dist/stdio.js.map +1 -1
  96. package/dist/types.d.ts +14 -7
  97. package/dist/types.d.ts.map +1 -1
  98. package/dist/types.js.map +1 -1
  99. package/package.json +7 -9
  100. package/src/endpoint/access.ts +2 -3
  101. package/src/endpoint/index.ts +33 -3
  102. package/src/mcp/buildMcpServer.ts +40 -30
  103. package/src/mcp/builtin/collections/authTools.ts +80 -69
  104. package/src/mcp/builtin/collections/countTool.ts +9 -21
  105. package/src/mcp/builtin/collections/countVersionsTool.ts +9 -18
  106. package/src/mcp/builtin/collections/createTool.ts +110 -86
  107. package/src/mcp/builtin/collections/deleteTool.ts +36 -64
  108. package/src/mcp/builtin/collections/duplicateTool.ts +35 -85
  109. package/src/mcp/builtin/collections/fileInput.spec.ts +20 -6
  110. package/src/mcp/builtin/collections/fileInput.ts +64 -76
  111. package/src/mcp/builtin/collections/findDistinctTool.ts +11 -63
  112. package/src/mcp/builtin/collections/findTool.ts +23 -105
  113. package/src/mcp/builtin/collections/findVersionByIDTool.ts +15 -58
  114. package/src/mcp/builtin/collections/findVersionsTool.ts +14 -85
  115. package/src/mcp/builtin/collections/getCollectionSchemaTool.ts +28 -13
  116. package/src/mcp/builtin/collections/restoreVersionTool.ts +14 -56
  117. package/src/mcp/builtin/collections/updateTool.ts +57 -111
  118. package/src/mcp/builtin/collections/uploadInstructionsTool.ts +64 -0
  119. package/src/mcp/builtin/formatEntityError.ts +77 -0
  120. package/src/mcp/builtin/getConfigInfoTool.ts +2 -1
  121. package/src/mcp/builtin/globals/countVersionsTool.ts +9 -17
  122. package/src/mcp/builtin/globals/findTool.ts +12 -51
  123. package/src/mcp/builtin/globals/findVersionByIDTool.ts +13 -52
  124. package/src/mcp/builtin/globals/findVersionsTool.ts +14 -92
  125. package/src/mcp/builtin/globals/getGlobalSchemaTool.ts +21 -11
  126. package/src/mcp/builtin/globals/restoreVersionTool.ts +14 -45
  127. package/src/mcp/builtin/globals/updateTool.ts +37 -60
  128. package/src/mcp/builtinTools.ts +9 -2
  129. package/src/mcp/sanitizeMCPConfig.ts +4 -1
  130. package/src/stdio.ts +4 -3
  131. package/src/types.ts +15 -7
  132. package/dist/mcp/builtin/collections/fileInput.spec.js +0 -72
  133. package/dist/mcp/builtin/collections/fileInput.spec.js.map +0 -1
  134. package/dist/mcp/builtin/collections/formatCollectionError.d.ts +0 -9
  135. package/dist/mcp/builtin/collections/formatCollectionError.d.ts.map +0 -1
  136. package/dist/mcp/builtin/collections/formatCollectionError.js +0 -60
  137. package/dist/mcp/builtin/collections/formatCollectionError.js.map +0 -1
  138. package/dist/mcp/builtin/validateEntityData.d.ts +0 -14
  139. package/dist/mcp/builtin/validateEntityData.d.ts.map +0 -1
  140. package/dist/mcp/builtin/validateEntityData.js +0 -82
  141. package/dist/mcp/builtin/validateEntityData.js.map +0 -1
  142. package/dist/utils/getVirtualFieldNames.d.ts +0 -14
  143. package/dist/utils/getVirtualFieldNames.d.ts.map +0 -1
  144. package/dist/utils/getVirtualFieldNames.js +0 -35
  145. package/dist/utils/getVirtualFieldNames.js.map +0 -1
  146. package/dist/utils/schemaConversion/filterFieldsByAccess.d.ts +0 -28
  147. package/dist/utils/schemaConversion/filterFieldsByAccess.d.ts.map +0 -1
  148. package/dist/utils/schemaConversion/filterFieldsByAccess.js +0 -71
  149. package/dist/utils/schemaConversion/filterFieldsByAccess.js.map +0 -1
  150. package/dist/utils/schemaConversion/getEntityInputSchema.d.ts +0 -13
  151. package/dist/utils/schemaConversion/getEntityInputSchema.d.ts.map +0 -1
  152. package/dist/utils/schemaConversion/getEntityInputSchema.js +0 -66
  153. package/dist/utils/schemaConversion/getEntityInputSchema.js.map +0 -1
  154. package/dist/utils/schemaConversion/sanitizeEntitySchema.d.ts +0 -10
  155. package/dist/utils/schemaConversion/sanitizeEntitySchema.d.ts.map +0 -1
  156. package/dist/utils/schemaConversion/sanitizeEntitySchema.js +0 -384
  157. package/dist/utils/schemaConversion/sanitizeEntitySchema.js.map +0 -1
  158. package/dist/utils/schemaConversion/sanitizeEntitySchema.spec.js +0 -133
  159. package/dist/utils/schemaConversion/sanitizeEntitySchema.spec.js.map +0 -1
  160. package/dist/utils/transformPointDataToPayload.d.ts +0 -7
  161. package/dist/utils/transformPointDataToPayload.d.ts.map +0 -1
  162. package/dist/utils/transformPointDataToPayload.js +0 -28
  163. package/dist/utils/transformPointDataToPayload.js.map +0 -1
  164. package/dist/utils/whereSchema.d.ts +0 -9
  165. package/dist/utils/whereSchema.d.ts.map +0 -1
  166. package/dist/utils/whereSchema.js +0 -13
  167. package/dist/utils/whereSchema.js.map +0 -1
  168. package/src/mcp/builtin/collections/formatCollectionError.ts +0 -84
  169. package/src/mcp/builtin/validateEntityData.ts +0 -132
  170. package/src/utils/getVirtualFieldNames.ts +0 -53
  171. package/src/utils/schemaConversion/filterFieldsByAccess.ts +0 -123
  172. package/src/utils/schemaConversion/getEntityInputSchema.ts +0 -96
  173. package/src/utils/schemaConversion/sanitizeEntitySchema.spec.ts +0 -96
  174. package/src/utils/schemaConversion/sanitizeEntitySchema.ts +0 -432
  175. package/src/utils/transformPointDataToPayload.ts +0 -40
  176. package/src/utils/whereSchema.ts +0 -24
@@ -1,6 +1,4 @@
1
- import type { PopulateType, SelectType } from 'payload'
2
-
3
- import { z } from 'zod'
1
+ import { restoreVersionInputSchema } from 'payload'
4
2
 
5
3
  import { defaultAccess } from '../../../defaultAccess.js'
6
4
  import { defineCollectionTool } from '../../../defineTool.js'
@@ -11,7 +9,7 @@ const DEFAULT_DESCRIPTION =
11
9
 
12
10
  export const restoreVersionTool = defineCollectionTool({
13
11
  access: (args) =>
14
- defaultAccess(args) && Boolean(args.permissions?.collections?.[args.collectionSlug]?.update),
12
+ defaultAccess(args) && Boolean(args.permissions?.collections?.[args.slug]?.update),
15
13
  annotations: {
16
14
  destructiveHint: true,
17
15
  idempotentHint: false,
@@ -20,85 +18,45 @@ export const restoreVersionTool = defineCollectionTool({
20
18
  title: 'Restore Version',
21
19
  },
22
20
  description: DEFAULT_DESCRIPTION,
23
- input: z.object({
24
- id: z.string().describe('The ID of the 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
- draft: z
34
- .boolean()
35
- .describe('Whether to restore the version as a draft')
36
- .optional()
37
- .default(false),
38
- fallbackLocale: z
39
- .string()
40
- .describe('Optional: fallback locale code to use when requested locale is not available')
41
- .optional(),
42
- locale: z
43
- .string()
44
- .describe('Optional: locale code to restore in (e.g., "en", "es")')
45
- .optional(),
46
- populate: z
47
- .record(z.string(), z.unknown())
48
- .describe(
49
- 'Optional: control which fields to include from populated relationship or upload documents.',
50
- )
51
- .optional(),
52
- select: z
53
- .record(z.string(), z.unknown())
54
- .describe(
55
- 'Optional: define exactly which fields you\'d like to return in the response, e.g., {"title": true}',
56
- )
57
- .optional(),
58
- showHiddenFields: z
59
- .boolean()
60
- .describe('Optional: include hidden fields in the restored document response')
61
- .optional(),
62
- }),
63
- }).handler(async ({ authorizedMCP, collectionSlug, input, req }) => {
21
+ input: restoreVersionInputSchema,
22
+ }).handler(async ({ slug, authorizedMCP, input, req }) => {
64
23
  const payload = req.payload
65
24
  const logger = getLogger({ payload })
66
- const { id, depth, draft, fallbackLocale, locale, populate, select, showHiddenFields } = input
25
+ const { id, depth, draft, fallbackLocale, locale, populate, select } = input
67
26
 
68
- logger.info(`Restoring version in collection: ${collectionSlug} with ID: ${id}`)
27
+ logger.info(`Restoring version in collection: ${slug} with ID: ${id}`)
69
28
 
70
29
  try {
71
30
  const result = await payload.restoreVersion({
72
- id,
73
- collection: collectionSlug,
31
+ id: String(id),
32
+ collection: slug,
74
33
  depth,
75
34
  draft,
76
35
  overrideAccess: authorizedMCP.overrideAccess,
77
36
  req,
78
- ...(fallbackLocale ? { fallbackLocale } : {}),
37
+ ...(fallbackLocale !== undefined ? { fallbackLocale } : {}),
79
38
  ...(locale ? { locale } : {}),
80
- ...(populate ? { populate: populate as PopulateType } : {}),
81
- ...(select ? { select: select as SelectType } : {}),
82
- ...(showHiddenFields !== undefined ? { showHiddenFields } : {}),
39
+ ...(populate ? { populate } : {}),
40
+ ...(select ? { select } : {}),
83
41
  })
84
42
 
85
43
  return {
86
44
  content: [
87
45
  {
88
46
  type: 'text',
89
- text: `Version "${id}" restored successfully in collection "${collectionSlug}"!\nRestored document:\n\`\`\`json\n${JSON.stringify(result)}\n\`\`\``,
47
+ text: `Version "${id}" restored successfully in collection "${slug}"!\nRestored document:\n\`\`\`json\n${JSON.stringify(result)}\n\`\`\``,
90
48
  },
91
49
  ],
92
50
  doc: result as Record<string, unknown>,
93
51
  }
94
52
  } catch (error) {
95
53
  const errorMessage = error instanceof Error ? error.message : 'Unknown error'
96
- logger.error(`Error restoring version ${id} in ${collectionSlug}: ${errorMessage}`)
54
+ logger.error(`Error restoring version ${id} in ${slug}: ${errorMessage}`)
97
55
  return {
98
56
  content: [
99
57
  {
100
58
  type: 'text',
101
- text: `❌ **Error restoring version "${id}" in collection "${collectionSlug}":** ${errorMessage}`,
59
+ text: `❌ **Error restoring version "${id}" in collection "${slug}":** ${errorMessage}`,
102
60
  },
103
61
  ],
104
62
  isError: true,
@@ -1,27 +1,27 @@
1
- import type { SelectType, Where } from 'payload'
1
+ import type { Where } from 'payload'
2
2
 
3
- import { z } from 'zod'
3
+ import {
4
+ getCollectionInputSchema,
5
+ getCollectionVirtualFieldNames,
6
+ parseDocumentID,
7
+ stripVirtualFields,
8
+ transformPointDataToPayload,
9
+ updateDocumentInputSchema,
10
+ validateCollectionData,
11
+ } from 'payload'
4
12
 
5
13
  import { defaultAccess } from '../../../defaultAccess.js'
6
14
  import { defineCollectionTool } from '../../../defineTool.js'
7
15
  import { getLogger } from '../../../utils/getLogger.js'
8
- import {
9
- getCollectionVirtualFieldNames,
10
- stripVirtualFields,
11
- } from '../../../utils/getVirtualFieldNames.js'
12
- import { getCollectionInputSchema } from '../../../utils/schemaConversion/getEntityInputSchema.js'
13
- import { transformPointDataToPayload } from '../../../utils/transformPointDataToPayload.js'
14
- import { whereSchema } from '../../../utils/whereSchema.js'
15
- import { validateCollectionData } from '../validateEntityData.js'
16
- import { fileInputSchema, resolveFileInput } from './fileInput.js'
17
- import { formatCollectionError } from './formatCollectionError.js'
16
+ import { formatEntityError } from '../formatEntityError.js'
17
+ import { fileInputSchema, resolveFile } from './fileInput.js'
18
18
 
19
19
  const DEFAULT_DESCRIPTION =
20
- 'Update documents in any collection by passing the collection slug and data.'
20
+ 'Update documents. Prefer uploadReference after upload, externalURL for URLs, or base64 for small local files.'
21
21
 
22
22
  export const updateDocumentTool = defineCollectionTool({
23
23
  access: (args) =>
24
- defaultAccess(args) && Boolean(args.permissions?.collections?.[args.collectionSlug]?.update),
24
+ defaultAccess(args) && Boolean(args.permissions?.collections?.[args.slug]?.update),
25
25
  annotations: {
26
26
  destructiveHint: true,
27
27
  idempotentHint: false,
@@ -30,65 +30,8 @@ export const updateDocumentTool = defineCollectionTool({
30
30
  title: 'Update Document',
31
31
  },
32
32
  description: DEFAULT_DESCRIPTION,
33
- input: z.object({
34
- id: z.union([z.string(), z.number()]).describe('The ID of the document to update').optional(),
35
- data: z
36
- .record(z.string(), z.unknown())
37
- .describe(
38
- 'The fields to update. Only include fields permitted by the schema returned by getCollectionSchema.',
39
- ),
40
- depth: z
41
- .number()
42
- .describe('How many levels deep to populate relationships')
43
- .optional()
44
- .default(0),
45
- draft: z
46
- .boolean()
47
- .describe(
48
- 'Only if getCollectionSchema includes _status; otherwise _status does not exist. true saves only a draft version; false updates main and versions. data._status: "published" overrides true.',
49
- )
50
- .optional()
51
- .default(false),
52
- fallbackLocale: z
53
- .string()
54
- .describe('Optional: fallback locale code to use when requested locale is not available')
55
- .optional(),
56
- file: fileInputSchema.optional(),
57
- locale: z
58
- .string()
59
- .describe(
60
- 'Optional: locale code to update the document in (e.g., "en", "es"). Defaults to the default locale',
61
- )
62
- .optional(),
63
- overrideLock: z
64
- .boolean()
65
- .describe('Whether to override document locks')
66
- .optional()
67
- .default(true),
68
- overwriteExistingFiles: z
69
- .boolean()
70
- .describe('Whether to overwrite existing files')
71
- .optional()
72
- .default(false),
73
- publishAllLocales: z
74
- .boolean()
75
- .describe(
76
- 'For collections with localized publishing status, whether publishing should affect every locale. Set false with locale to publish only that locale.',
77
- )
78
- .optional(),
79
- select: z
80
- .record(z.string(), z.unknown())
81
- .describe(
82
- 'Optional: define exactly which fields you\'d like to return in the response, e.g., {"title": true}',
83
- )
84
- .optional(),
85
- where: whereSchema
86
- .describe(
87
- 'Where clause to update multiple documents. Use field names with Payload operators, and/or arrays for grouping. Example: {"title":{"contains":"test"}}',
88
- )
89
- .optional(),
90
- }),
91
- }).handler(async ({ authorizedMCP, collectionSlug, input, req }) => {
33
+ input: updateDocumentInputSchema({ file: fileInputSchema }),
34
+ }).handler(async ({ slug, authorizedMCP, input, req }) => {
92
35
  const payload = req.payload
93
36
  const logger = getLogger({ payload })
94
37
 
@@ -99,100 +42,103 @@ export const updateDocumentTool = defineCollectionTool({
99
42
  draft,
100
43
  fallbackLocale,
101
44
  file: fileInput,
45
+ limit,
102
46
  locale,
103
47
  overrideLock,
104
- overwriteExistingFiles,
48
+ populate,
105
49
  publishAllLocales,
50
+ returning,
106
51
  select,
52
+ sort,
53
+ trash,
54
+ unpublishAllLocales,
107
55
  where,
108
56
  } = input
109
57
 
110
58
  logger.info(
111
- `Updating document in collection: ${collectionSlug}${id ? ` with ID: ${id}` : ' with where clause'}, draft: ${draft}${locale ? `, locale: ${locale}` : ''}`,
59
+ `Updating document in collection: ${slug}${id ? ` with ID: ${id}` : ' with where clause'}, draft: ${draft}${locale ? `, locale: ${locale}` : ''}`,
112
60
  )
113
61
 
114
62
  try {
115
- if (!id && !where) {
116
- return {
117
- content: [{ type: 'text', text: 'Error: Either id or where clause must be provided' }],
118
- }
119
- }
120
-
121
- const virtualFieldNames = getCollectionVirtualFieldNames(payload.config, collectionSlug)
63
+ const virtualFieldNames = getCollectionVirtualFieldNames(payload.config, slug)
122
64
  const inputData = stripVirtualFields(data, virtualFieldNames)
123
- const validationError = validateCollectionData({
124
- collectionSlug,
65
+ validateCollectionData({
66
+ slug,
125
67
  data: inputData,
126
68
  partial: true,
127
69
  req,
128
70
  })
129
71
 
130
- if (validationError) {
131
- return validationError
132
- }
133
-
134
72
  const parsedData = transformPointDataToPayload(inputData)
135
- const file = await resolveFileInput({ collectionSlug, input: fileInput, req })
73
+ const file = await resolveFile({ slug, input: fileInput, req })
136
74
 
137
75
  const whereClause: Where = where ?? {}
138
76
 
139
- if (id) {
77
+ if (id !== undefined) {
140
78
  const result = await payload.update({
141
- id,
142
- collection: collectionSlug,
79
+ id: parseDocumentID({ id, collectionSlug: slug, payload }),
80
+ collection: slug,
143
81
  data: parsedData,
144
82
  depth,
145
83
  draft,
84
+ fallbackLocale,
85
+ locale,
146
86
  overrideAccess: authorizedMCP.overrideAccess,
147
87
  overrideLock,
88
+ populate,
89
+ publishAllLocales,
148
90
  req,
91
+ select: returning ? select : { id: true },
92
+ trash,
93
+ unpublishAllLocales,
149
94
  ...(file ? { file } : {}),
150
- ...(overwriteExistingFiles ? { overwriteExistingFiles } : {}),
151
- ...(publishAllLocales !== undefined ? { publishAllLocales } : {}),
152
- ...(locale ? { locale } : {}),
153
- ...(fallbackLocale ? { fallbackLocale } : {}),
154
- ...(select ? { select: select as SelectType } : {}),
155
95
  })
156
96
 
97
+ const responseResult = returning ? result : { id: result.id }
98
+
157
99
  return {
158
100
  content: [
159
101
  {
160
102
  type: 'text',
161
- text: `Document updated successfully in collection "${collectionSlug}"!\nUpdated document:\n\`\`\`json\n${JSON.stringify(result)}\n\`\`\``,
103
+ text: `Document updated successfully in collection "${slug}"!\nResult:\n\`\`\`json\n${JSON.stringify(responseResult)}\n\`\`\``,
162
104
  },
163
105
  ],
164
- doc: result as Record<string, unknown>,
106
+ doc: responseResult as Record<string, unknown>,
165
107
  }
166
108
  }
167
109
 
168
110
  const result = await payload.update({
169
- collection: collectionSlug,
111
+ collection: slug,
170
112
  data: parsedData,
171
113
  depth,
172
114
  draft,
115
+ fallbackLocale,
116
+ limit,
117
+ locale,
173
118
  overrideAccess: authorizedMCP.overrideAccess,
174
119
  overrideLock,
120
+ populate,
121
+ publishAllLocales,
175
122
  req,
123
+ select: returning ? select : { id: true },
124
+ sort,
125
+ trash,
126
+ unpublishAllLocales,
176
127
  where: whereClause,
177
128
  ...(file ? { file } : {}),
178
- ...(overwriteExistingFiles ? { overwriteExistingFiles } : {}),
179
- ...(publishAllLocales !== undefined ? { publishAllLocales } : {}),
180
- ...(locale ? { locale } : {}),
181
- ...(fallbackLocale ? { fallbackLocale } : {}),
182
- ...(select ? { select: select as SelectType } : {}),
183
129
  })
184
130
 
185
- const docs = result.docs || []
131
+ const docs = returning ? result.docs : result.docs.map(({ id }) => ({ id }))
186
132
  const errors = result.errors || []
187
133
 
188
- let responseText = `Multiple documents updated in collection "${collectionSlug}"!\nUpdated: ${docs.length} documents\nErrors: ${errors.length}\n---`
134
+ let responseText = `Multiple documents updated in collection "${slug}"!\nUpdated: ${docs.length} documents\nErrors: ${errors.length}\n---`
189
135
  if (docs.length > 0) {
190
136
  responseText += `\n\nUpdated documents:\n\`\`\`json\n${JSON.stringify(docs)}\n\`\`\``
191
137
  }
192
138
  if (errors.length > 0) {
193
139
  responseText += `\n\nErrors:\n\`\`\`json\n${JSON.stringify(errors)}\n\`\`\``
194
140
 
195
- const errorSchema = getCollectionInputSchema({ collectionSlug, req })
141
+ const errorSchema = getCollectionInputSchema({ collectionSlug: slug, req })
196
142
 
197
143
  if (errorSchema) {
198
144
  responseText += `\n\nUse this schema for data:\n\`\`\`json\n${JSON.stringify(errorSchema)}\n\`\`\``
@@ -205,7 +151,7 @@ export const updateDocumentTool = defineCollectionTool({
205
151
  ...(errorSchema
206
152
  ? {
207
153
  structuredContent: {
208
- collectionSlug,
154
+ slug,
209
155
  docs,
210
156
  errors,
211
157
  schema: errorSchema,
@@ -221,7 +167,7 @@ export const updateDocumentTool = defineCollectionTool({
221
167
  }
222
168
  } catch (error) {
223
169
  const errorMessage = error instanceof Error ? error.message : 'Unknown error'
224
- logger.error(`Error updating document in ${collectionSlug}: ${errorMessage}`)
225
- return formatCollectionError({ action: 'updating', collectionSlug, error, req })
170
+ logger.error(`Error updating document in ${slug}: ${errorMessage}`)
171
+ return formatEntityError({ slug, action: 'updating', entity: 'collection', error, req })
226
172
  }
227
173
  })
@@ -0,0 +1,64 @@
1
+ import { strictObject, z } from 'payload'
2
+ import { getUploadInstructions as getPayloadUploadInstructions } from 'payload/internal'
3
+
4
+ import { defaultAccess } from '../../../defaultAccess.js'
5
+ import { defineCollectionTool } from '../../../defineTool.js'
6
+
7
+ export const getUploadInstructionsTool = defineCollectionTool({
8
+ access: (args) =>
9
+ defaultAccess(args) &&
10
+ Boolean(
11
+ args.permissions?.collections?.[args.slug]?.create ||
12
+ args.permissions?.collections?.[args.slug]?.update,
13
+ ),
14
+ annotations: {
15
+ destructiveHint: false,
16
+ idempotentHint: false,
17
+ openWorldHint: true,
18
+ readOnlyHint: false,
19
+ title: 'Get Upload Instructions',
20
+ },
21
+ description:
22
+ 'Prepare uploads for createDocuments or updateDocument. This does not upload bytes; finish the returned action before use.',
23
+ input: strictObject({
24
+ docPrefix: z.optional(z.string()).check(z.describe('Document folder or prefix.')),
25
+ filename: z.string().check(z.describe('The original file name.')),
26
+ filesize: z.int().check(z.nonnegative(), z.describe('The file size in bytes.')),
27
+ mimeType: z.string().check(z.describe('The file MIME type.')),
28
+ }),
29
+ }).handler(async ({ slug, authorizedMCP, input, req }) => {
30
+ try {
31
+ const instructions = await getPayloadUploadInstructions({
32
+ ...input,
33
+ collectionSlug: slug,
34
+ overrideAccess: authorizedMCP.overrideAccess,
35
+ req,
36
+ })
37
+
38
+ const nextStep =
39
+ instructions.type === 'http'
40
+ ? 'Upload bytes with instructions.request. After success, pass { source: "uploadReference", file: instructions.file }.'
41
+ : `Call "${instructions.name}" with file and data. After success, pass { source: "uploadReference", file: instructions.file }.`
42
+
43
+ return {
44
+ content: [
45
+ {
46
+ type: 'text',
47
+ text: `Upload instructions for collection "${slug}":\n\`\`\`json\n${JSON.stringify(instructions)}\n\`\`\`\n${nextStep}`,
48
+ },
49
+ ],
50
+ structuredContent: { instructions },
51
+ }
52
+ } catch (error) {
53
+ const message = error instanceof Error ? error.message : 'Unknown error'
54
+ return {
55
+ content: [
56
+ {
57
+ type: 'text',
58
+ text: `Error getting upload instructions for collection "${slug}": ${message}`,
59
+ },
60
+ ],
61
+ isError: true,
62
+ }
63
+ }
64
+ })
@@ -0,0 +1,77 @@
1
+ import type { CollectionSlug, GlobalSlug, PayloadRequest } from 'payload'
2
+
3
+ import { getCollectionInputSchema, getGlobalInputSchema, ValidationError } from 'payload'
4
+
5
+ import type { MCPToolResponse } from '../../types.js'
6
+
7
+ export const formatEntityError = ({
8
+ slug,
9
+ action,
10
+ entity,
11
+ error,
12
+ req,
13
+ }:
14
+ | {
15
+ action: 'creating' | 'duplicating' | 'updating'
16
+ entity: 'collection'
17
+ error: unknown
18
+ req: PayloadRequest
19
+ slug: CollectionSlug
20
+ }
21
+ | {
22
+ action: 'updating'
23
+ entity: 'global'
24
+ error: unknown
25
+ req: PayloadRequest
26
+ slug: GlobalSlug
27
+ }): MCPToolResponse => {
28
+ const message = error instanceof Error ? error.message : 'Unknown error'
29
+ const target = entity === 'collection' ? `document in collection "${slug}"` : `global "${slug}"`
30
+
31
+ if (!isValidationError(error, message)) {
32
+ return {
33
+ content: [{ type: 'text', text: `Error ${action} ${target}: ${message}` }],
34
+ isError: true,
35
+ }
36
+ }
37
+
38
+ const schema =
39
+ entity === 'collection'
40
+ ? getCollectionInputSchema({ collectionSlug: slug, req })
41
+ : getGlobalInputSchema({ globalSlug: slug, req })
42
+ const errors = error instanceof ValidationError ? error.data.errors : [{ message }]
43
+ const validationMessage = errors
44
+ .map((issue) => `${'path' in issue ? `${issue.path}: ` : ''}${issue.message}`)
45
+ .join('\n')
46
+ const schemaText = schema
47
+ ? `\n\nUse this schema for data:\n\`\`\`json\n${JSON.stringify(schema)}\n\`\`\``
48
+ : ''
49
+
50
+ return {
51
+ content: [
52
+ { type: 'text', text: `Error ${action} ${target}: ${validationMessage}${schemaText}` },
53
+ ],
54
+ isError: true,
55
+ ...(schema
56
+ ? {
57
+ structuredContent: {
58
+ slug,
59
+ errors,
60
+ schema,
61
+ },
62
+ }
63
+ : {}),
64
+ }
65
+ }
66
+
67
+ const isValidationError = (error: unknown, message: string): boolean => {
68
+ if (error instanceof ValidationError) {
69
+ return true
70
+ }
71
+
72
+ const name = error && typeof error === 'object' && 'name' in error ? error.name : undefined
73
+
74
+ return (
75
+ name === 'CastError' || message.includes('Cast to ') || message.includes('validation failed')
76
+ )
77
+ }
@@ -1,4 +1,4 @@
1
- import { getAccessResults, isEntityHidden } from 'payload'
1
+ import { getAccessResults, getConfigInfoInputSchema, isEntityHidden } from 'payload'
2
2
 
3
3
  import { defineTool } from '../../defineTool.js'
4
4
 
@@ -11,6 +11,7 @@ export const getConfigInfoTool = defineTool({
11
11
  title: 'Config Info',
12
12
  },
13
13
  description: 'List the Payload collection and global slugs visible to this MCP client.',
14
+ input: getConfigInfoInputSchema,
14
15
  }).handler(async ({ authorizedMCP, req }) => {
15
16
  const user = req.user
16
17
  const permissions = authorizedMCP.overrideAccess ? null : await getAccessResults({ req })
@@ -1,16 +1,15 @@
1
- import { z } from 'zod'
1
+ import { countGlobalVersionsInputSchema } from 'payload'
2
2
 
3
3
  import { defaultAccess } from '../../../defaultAccess.js'
4
4
  import { defineGlobalTool } from '../../../defineTool.js'
5
5
  import { getLogger } from '../../../utils/getLogger.js'
6
- import { whereSchema } from '../../../utils/whereSchema.js'
7
6
 
8
7
  const DEFAULT_DESCRIPTION =
9
8
  'Count global versions in any version-enabled global by passing the global slug and optional where clause.'
10
9
 
11
10
  export const countGlobalVersionsTool = defineGlobalTool({
12
11
  access: (args) =>
13
- defaultAccess(args) && Boolean(args.permissions?.globals?.[args.globalSlug]?.readVersions),
12
+ defaultAccess(args) && Boolean(args.permissions?.globals?.[args.slug]?.readVersions),
14
13
  annotations: {
15
14
  destructiveHint: false,
16
15
  idempotentHint: true,
@@ -19,24 +18,17 @@ export const countGlobalVersionsTool = defineGlobalTool({
19
18
  title: 'Count Global Versions',
20
19
  },
21
20
  description: DEFAULT_DESCRIPTION,
22
- input: z.object({
23
- locale: z.string().describe('Optional: locale code to count versions in').optional(),
24
- where: whereSchema
25
- .describe(
26
- 'Optional: where clause for filtering versions. Version document fields are usually under "version". Example: {"version.siteName":{"contains":"test"}}',
27
- )
28
- .optional(),
29
- }),
30
- }).handler(async ({ authorizedMCP, globalSlug, input, req }) => {
21
+ input: countGlobalVersionsInputSchema,
22
+ }).handler(async ({ slug, authorizedMCP, input, req }) => {
31
23
  const payload = req.payload
32
24
  const logger = getLogger({ payload })
33
25
  const { locale, where } = input
34
26
 
35
- logger.info(`Counting versions for global: ${globalSlug}`)
27
+ logger.info(`Counting versions for global: ${slug}`)
36
28
 
37
29
  try {
38
30
  const result = await payload.countGlobalVersions({
39
- global: globalSlug,
31
+ global: slug,
40
32
  overrideAccess: authorizedMCP.overrideAccess,
41
33
  req,
42
34
  ...(locale ? { locale } : {}),
@@ -47,19 +39,19 @@ export const countGlobalVersionsTool = defineGlobalTool({
47
39
  content: [
48
40
  {
49
41
  type: 'text',
50
- text: `Global "${globalSlug}" contains ${result.totalDocs} matching versions.\n\`\`\`json\n${JSON.stringify(result)}\n\`\`\``,
42
+ text: `Global "${slug}" contains ${result.totalDocs} matching versions.\n\`\`\`json\n${JSON.stringify(result)}\n\`\`\``,
51
43
  },
52
44
  ],
53
45
  doc: result,
54
46
  }
55
47
  } catch (error) {
56
48
  const errorMessage = error instanceof Error ? error.message : 'Unknown error'
57
- logger.error(`Error counting versions for global ${globalSlug}: ${errorMessage}`)
49
+ logger.error(`Error counting versions for global ${slug}: ${errorMessage}`)
58
50
  return {
59
51
  content: [
60
52
  {
61
53
  type: 'text',
62
- text: `❌ **Error counting versions for global "${globalSlug}":** ${errorMessage}`,
54
+ text: `❌ **Error counting versions for global "${slug}":** ${errorMessage}`,
63
55
  },
64
56
  ],
65
57
  isError: true,