@payloadcms/plugin-mcp 4.0.0-internal.8867dba → 4.0.0-internal.9496957

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 (165) hide show
  1. package/dist/endpoint/access.js +2 -2
  2. package/dist/endpoint/access.js.map +1 -1
  3. package/dist/mcp/buildMcpServer.d.ts +1 -1
  4. package/dist/mcp/buildMcpServer.d.ts.map +1 -1
  5. package/dist/mcp/buildMcpServer.js +35 -23
  6. package/dist/mcp/buildMcpServer.js.map +1 -1
  7. package/dist/mcp/builtin/collections/authTools.d.ts.map +1 -1
  8. package/dist/mcp/builtin/collections/authTools.js +79 -56
  9. package/dist/mcp/builtin/collections/authTools.js.map +1 -1
  10. package/dist/mcp/builtin/collections/countTool.d.ts.map +1 -1
  11. package/dist/mcp/builtin/collections/countTool.js +9 -14
  12. package/dist/mcp/builtin/collections/countTool.js.map +1 -1
  13. package/dist/mcp/builtin/collections/countVersionsTool.d.ts.map +1 -1
  14. package/dist/mcp/builtin/collections/countVersionsTool.js +9 -13
  15. package/dist/mcp/builtin/collections/countVersionsTool.js.map +1 -1
  16. package/dist/mcp/builtin/collections/createTool.d.ts +1 -1
  17. package/dist/mcp/builtin/collections/createTool.d.ts.map +1 -1
  18. package/dist/mcp/builtin/collections/createTool.js +97 -62
  19. package/dist/mcp/builtin/collections/createTool.js.map +1 -1
  20. package/dist/mcp/builtin/collections/deleteTool.d.ts.map +1 -1
  21. package/dist/mcp/builtin/collections/deleteTool.js +40 -43
  22. package/dist/mcp/builtin/collections/deleteTool.js.map +1 -1
  23. package/dist/mcp/builtin/collections/duplicateTool.d.ts.map +1 -1
  24. package/dist/mcp/builtin/collections/duplicateTool.js +26 -36
  25. package/dist/mcp/builtin/collections/duplicateTool.js.map +1 -1
  26. package/dist/mcp/builtin/collections/fileInput.d.ts +21 -21
  27. package/dist/mcp/builtin/collections/fileInput.d.ts.map +1 -1
  28. package/dist/mcp/builtin/collections/fileInput.js +30 -24
  29. package/dist/mcp/builtin/collections/fileInput.js.map +1 -1
  30. package/dist/mcp/builtin/collections/fileInput.spec.js +2 -2
  31. package/dist/mcp/builtin/collections/fileInput.spec.js.map +1 -1
  32. package/dist/mcp/builtin/collections/findDistinctTool.d.ts.map +1 -1
  33. package/dist/mcp/builtin/collections/findDistinctTool.js +11 -26
  34. package/dist/mcp/builtin/collections/findDistinctTool.js.map +1 -1
  35. package/dist/mcp/builtin/collections/findTool.d.ts.map +1 -1
  36. package/dist/mcp/builtin/collections/findTool.js +21 -43
  37. package/dist/mcp/builtin/collections/findTool.js.map +1 -1
  38. package/dist/mcp/builtin/collections/findVersionByIDTool.d.ts.map +1 -1
  39. package/dist/mcp/builtin/collections/findVersionByIDTool.js +17 -26
  40. package/dist/mcp/builtin/collections/findVersionByIDTool.js.map +1 -1
  41. package/dist/mcp/builtin/collections/findVersionsTool.d.ts.map +1 -1
  42. package/dist/mcp/builtin/collections/findVersionsTool.js +16 -30
  43. package/dist/mcp/builtin/collections/findVersionsTool.js.map +1 -1
  44. package/dist/mcp/builtin/collections/getCollectionSchemaTool.d.ts.map +1 -1
  45. package/dist/mcp/builtin/collections/getCollectionSchemaTool.js +12 -12
  46. package/dist/mcp/builtin/collections/getCollectionSchemaTool.js.map +1 -1
  47. package/dist/mcp/builtin/collections/restoreVersionTool.d.ts.map +1 -1
  48. package/dist/mcp/builtin/collections/restoreVersionTool.js +14 -26
  49. package/dist/mcp/builtin/collections/restoreVersionTool.js.map +1 -1
  50. package/dist/mcp/builtin/collections/updateTool.d.ts.map +1 -1
  51. package/dist/mcp/builtin/collections/updateTool.js +40 -85
  52. package/dist/mcp/builtin/collections/updateTool.js.map +1 -1
  53. package/dist/mcp/builtin/collections/uploadInstructionsTool.js +13 -13
  54. package/dist/mcp/builtin/collections/uploadInstructionsTool.js.map +1 -1
  55. package/dist/mcp/builtin/formatEntityError.d.ts +16 -0
  56. package/dist/mcp/builtin/formatEntityError.d.ts.map +1 -0
  57. package/dist/mcp/builtin/formatEntityError.js +55 -0
  58. package/dist/mcp/builtin/formatEntityError.js.map +1 -0
  59. package/dist/mcp/builtin/getConfigInfoTool.d.ts.map +1 -1
  60. package/dist/mcp/builtin/getConfigInfoTool.js +3 -2
  61. package/dist/mcp/builtin/getConfigInfoTool.js.map +1 -1
  62. package/dist/mcp/builtin/globals/countVersionsTool.d.ts.map +1 -1
  63. package/dist/mcp/builtin/globals/countVersionsTool.js +9 -13
  64. package/dist/mcp/builtin/globals/countVersionsTool.js.map +1 -1
  65. package/dist/mcp/builtin/globals/findTool.d.ts.map +1 -1
  66. package/dist/mcp/builtin/globals/findTool.js +10 -16
  67. package/dist/mcp/builtin/globals/findTool.js.map +1 -1
  68. package/dist/mcp/builtin/globals/findVersionByIDTool.d.ts.map +1 -1
  69. package/dist/mcp/builtin/globals/findVersionByIDTool.js +13 -24
  70. package/dist/mcp/builtin/globals/findVersionByIDTool.js.map +1 -1
  71. package/dist/mcp/builtin/globals/findVersionsTool.d.ts.map +1 -1
  72. package/dist/mcp/builtin/globals/findVersionsTool.js +13 -29
  73. package/dist/mcp/builtin/globals/findVersionsTool.js.map +1 -1
  74. package/dist/mcp/builtin/globals/getGlobalSchemaTool.d.ts.map +1 -1
  75. package/dist/mcp/builtin/globals/getGlobalSchemaTool.js +11 -11
  76. package/dist/mcp/builtin/globals/getGlobalSchemaTool.js.map +1 -1
  77. package/dist/mcp/builtin/globals/restoreVersionTool.d.ts.map +1 -1
  78. package/dist/mcp/builtin/globals/restoreVersionTool.js +15 -22
  79. package/dist/mcp/builtin/globals/restoreVersionTool.js.map +1 -1
  80. package/dist/mcp/builtin/globals/updateTool.d.ts.map +1 -1
  81. package/dist/mcp/builtin/globals/updateTool.js +27 -36
  82. package/dist/mcp/builtin/globals/updateTool.js.map +1 -1
  83. package/dist/mcp/builtinTools.d.ts.map +1 -1
  84. package/dist/mcp/builtinTools.js +3 -3
  85. package/dist/mcp/builtinTools.js.map +1 -1
  86. package/dist/stdio.d.ts.map +1 -1
  87. package/dist/stdio.js +2 -1
  88. package/dist/stdio.js.map +1 -1
  89. package/dist/types.d.ts +4 -4
  90. package/dist/types.d.ts.map +1 -1
  91. package/dist/types.js.map +1 -1
  92. package/package.json +5 -7
  93. package/src/endpoint/access.ts +2 -3
  94. package/src/mcp/buildMcpServer.ts +39 -29
  95. package/src/mcp/builtin/collections/authTools.ts +77 -69
  96. package/src/mcp/builtin/collections/countTool.ts +9 -21
  97. package/src/mcp/builtin/collections/countVersionsTool.ts +9 -18
  98. package/src/mcp/builtin/collections/createTool.ts +87 -85
  99. package/src/mcp/builtin/collections/deleteTool.ts +36 -64
  100. package/src/mcp/builtin/collections/duplicateTool.ts +33 -84
  101. package/src/mcp/builtin/collections/fileInput.spec.ts +2 -2
  102. package/src/mcp/builtin/collections/fileInput.ts +40 -25
  103. package/src/mcp/builtin/collections/findDistinctTool.ts +11 -63
  104. package/src/mcp/builtin/collections/findTool.ts +21 -103
  105. package/src/mcp/builtin/collections/findVersionByIDTool.ts +15 -58
  106. package/src/mcp/builtin/collections/findVersionsTool.ts +14 -85
  107. package/src/mcp/builtin/collections/getCollectionSchemaTool.ts +11 -11
  108. package/src/mcp/builtin/collections/restoreVersionTool.ts +14 -56
  109. package/src/mcp/builtin/collections/updateTool.ts +49 -107
  110. package/src/mcp/builtin/collections/uploadInstructionsTool.ts +15 -15
  111. package/src/mcp/builtin/formatEntityError.ts +77 -0
  112. package/src/mcp/builtin/getConfigInfoTool.ts +2 -1
  113. package/src/mcp/builtin/globals/countVersionsTool.ts +9 -17
  114. package/src/mcp/builtin/globals/findTool.ts +12 -51
  115. package/src/mcp/builtin/globals/findVersionByIDTool.ts +13 -52
  116. package/src/mcp/builtin/globals/findVersionsTool.ts +14 -92
  117. package/src/mcp/builtin/globals/getGlobalSchemaTool.ts +10 -10
  118. package/src/mcp/builtin/globals/restoreVersionTool.ts +14 -45
  119. package/src/mcp/builtin/globals/updateTool.ts +37 -60
  120. package/src/mcp/builtinTools.ts +2 -2
  121. package/src/stdio.ts +2 -1
  122. package/src/types.ts +4 -4
  123. package/dist/mcp/builtin/collections/formatCollectionError.d.ts +0 -9
  124. package/dist/mcp/builtin/collections/formatCollectionError.d.ts.map +0 -1
  125. package/dist/mcp/builtin/collections/formatCollectionError.js +0 -60
  126. package/dist/mcp/builtin/collections/formatCollectionError.js.map +0 -1
  127. package/dist/mcp/builtin/validateEntityData.d.ts +0 -14
  128. package/dist/mcp/builtin/validateEntityData.d.ts.map +0 -1
  129. package/dist/mcp/builtin/validateEntityData.js +0 -82
  130. package/dist/mcp/builtin/validateEntityData.js.map +0 -1
  131. package/dist/utils/getVirtualFieldNames.d.ts +0 -14
  132. package/dist/utils/getVirtualFieldNames.d.ts.map +0 -1
  133. package/dist/utils/getVirtualFieldNames.js +0 -35
  134. package/dist/utils/getVirtualFieldNames.js.map +0 -1
  135. package/dist/utils/schemaConversion/filterFieldsByAccess.d.ts +0 -28
  136. package/dist/utils/schemaConversion/filterFieldsByAccess.d.ts.map +0 -1
  137. package/dist/utils/schemaConversion/filterFieldsByAccess.js +0 -71
  138. package/dist/utils/schemaConversion/filterFieldsByAccess.js.map +0 -1
  139. package/dist/utils/schemaConversion/getEntityInputSchema.d.ts +0 -13
  140. package/dist/utils/schemaConversion/getEntityInputSchema.d.ts.map +0 -1
  141. package/dist/utils/schemaConversion/getEntityInputSchema.js +0 -66
  142. package/dist/utils/schemaConversion/getEntityInputSchema.js.map +0 -1
  143. package/dist/utils/schemaConversion/sanitizeEntitySchema.d.ts +0 -10
  144. package/dist/utils/schemaConversion/sanitizeEntitySchema.d.ts.map +0 -1
  145. package/dist/utils/schemaConversion/sanitizeEntitySchema.js +0 -384
  146. package/dist/utils/schemaConversion/sanitizeEntitySchema.js.map +0 -1
  147. package/dist/utils/schemaConversion/sanitizeEntitySchema.spec.js +0 -133
  148. package/dist/utils/schemaConversion/sanitizeEntitySchema.spec.js.map +0 -1
  149. package/dist/utils/transformPointDataToPayload.d.ts +0 -7
  150. package/dist/utils/transformPointDataToPayload.d.ts.map +0 -1
  151. package/dist/utils/transformPointDataToPayload.js +0 -28
  152. package/dist/utils/transformPointDataToPayload.js.map +0 -1
  153. package/dist/utils/whereSchema.d.ts +0 -9
  154. package/dist/utils/whereSchema.d.ts.map +0 -1
  155. package/dist/utils/whereSchema.js +0 -13
  156. package/dist/utils/whereSchema.js.map +0 -1
  157. package/src/mcp/builtin/collections/formatCollectionError.ts +0 -84
  158. package/src/mcp/builtin/validateEntityData.ts +0 -132
  159. package/src/utils/getVirtualFieldNames.ts +0 -53
  160. package/src/utils/schemaConversion/filterFieldsByAccess.ts +0 -123
  161. package/src/utils/schemaConversion/getEntityInputSchema.ts +0 -96
  162. package/src/utils/schemaConversion/sanitizeEntitySchema.spec.ts +0 -96
  163. package/src/utils/schemaConversion/sanitizeEntitySchema.ts +0 -432
  164. package/src/utils/transformPointDataToPayload.ts +0 -40
  165. package/src/utils/whereSchema.ts +0 -24
@@ -1,19 +1,15 @@
1
- import type { PopulateType, SelectType } from 'payload'
2
-
3
- import { z } from 'zod'
1
+ import { findVersionsInputSchema } from 'payload'
4
2
 
5
3
  import { defaultAccess } from '../../../defaultAccess.js'
6
4
  import { defineCollectionTool } from '../../../defineTool.js'
7
5
  import { getLogger } from '../../../utils/getLogger.js'
8
- import { whereSchema } from '../../../utils/whereSchema.js'
9
6
 
10
7
  const DEFAULT_DESCRIPTION =
11
8
  'Find document versions in any version-enabled collection by passing the collection slug and optional where clause.'
12
9
 
13
10
  export const findVersionsTool = defineCollectionTool({
14
11
  access: (args) =>
15
- defaultAccess(args) &&
16
- Boolean(args.permissions?.collections?.[args.collectionSlug]?.readVersions),
12
+ defaultAccess(args) && Boolean(args.permissions?.collections?.[args.slug]?.readVersions),
17
13
  annotations: {
18
14
  destructiveHint: false,
19
15
  idempotentHint: true,
@@ -22,79 +18,13 @@ export const findVersionsTool = defineCollectionTool({
22
18
  title: 'Find Versions',
23
19
  },
24
20
  description: DEFAULT_DESCRIPTION,
25
- input: z.object({
26
- depth: z
27
- .number()
28
- .int()
29
- .min(0)
30
- .max(10)
31
- .describe('How many levels deep to populate relationships in version documents')
32
- .optional()
33
- .default(0),
34
- fallbackLocale: z
35
- .string()
36
- .describe('Optional: fallback locale code to use when requested locale is not available')
37
- .optional(),
38
- limit: z
39
- .number()
40
- .int()
41
- .min(1)
42
- .max(100)
43
- .describe('Maximum number of versions to return (default: 10, max: 100)')
44
- .optional()
45
- .default(10),
46
- locale: z
47
- .string()
48
- .describe(
49
- 'Optional: locale code to retrieve data in (e.g., "en", "es"). Use "all" to retrieve all locales for localized fields',
50
- )
51
- .optional(),
52
- page: z
53
- .number()
54
- .int()
55
- .min(1)
56
- .describe('Page number for pagination (default: 1)')
57
- .optional()
58
- .default(1),
59
- pagination: z
60
- .boolean()
61
- .describe('Optional: set to false to skip the count query overhead')
62
- .optional(),
63
- populate: z
64
- .record(z.string(), z.unknown())
65
- .describe(
66
- 'Optional: control which fields to include from populated relationship or upload documents.',
67
- )
68
- .optional(),
69
- select: z
70
- .record(z.string(), z.unknown())
71
- .describe(
72
- 'Optional: define exactly which fields you\'d like to return in the response, e.g., {"version.title": true}',
73
- )
74
- .optional(),
75
- showHiddenFields: z
76
- .boolean()
77
- .describe('Optional: include hidden fields in returned version documents')
78
- .optional(),
79
- sort: z
80
- .string()
81
- .describe('Field to sort by (e.g., "-updatedAt", "-version.updatedAt" for descending)')
82
- .optional(),
83
- trash: z
84
- .boolean()
85
- .describe('Optional: include versions for soft-deleted documents when trash is enabled')
86
- .optional(),
87
- where: whereSchema
88
- .describe(
89
- 'Optional: where clause for filtering versions. Version document fields are usually under "version". Example: {"version.title":{"contains":"test"}}',
90
- )
91
- .optional(),
92
- }),
93
- }).handler(async ({ authorizedMCP, collectionSlug, input, req }) => {
21
+ input: findVersionsInputSchema,
22
+ }).handler(async ({ slug, authorizedMCP, input, req }) => {
94
23
  const payload = req.payload
95
24
  const logger = getLogger({ payload })
96
25
  const {
97
26
  depth,
27
+ draft,
98
28
  fallbackLocale,
99
29
  limit,
100
30
  locale,
@@ -102,28 +32,27 @@ export const findVersionsTool = defineCollectionTool({
102
32
  pagination,
103
33
  populate,
104
34
  select,
105
- showHiddenFields,
106
35
  sort,
107
36
  trash,
108
37
  where,
109
38
  } = input
110
39
 
111
- logger.info(`Finding versions in collection: ${collectionSlug}, limit: ${limit}, page: ${page}`)
40
+ logger.info(`Finding versions in collection: ${slug}, limit: ${limit}, page: ${page}`)
112
41
 
113
42
  try {
114
43
  const result = await payload.findVersions({
115
- collection: collectionSlug,
44
+ collection: slug,
116
45
  depth,
117
46
  limit,
118
47
  overrideAccess: authorizedMCP.overrideAccess,
119
48
  page,
120
49
  req,
121
- ...(fallbackLocale ? { fallbackLocale } : {}),
50
+ ...(draft !== undefined ? { draft } : {}),
51
+ ...(fallbackLocale !== undefined ? { fallbackLocale } : {}),
122
52
  ...(locale ? { locale } : {}),
123
53
  ...(pagination !== undefined ? { pagination } : {}),
124
- ...(populate ? { populate: populate as PopulateType } : {}),
125
- ...(select ? { select: select as SelectType } : {}),
126
- ...(showHiddenFields !== undefined ? { showHiddenFields } : {}),
54
+ ...(populate ? { populate } : {}),
55
+ ...(select ? { select } : {}),
127
56
  ...(sort ? { sort } : {}),
128
57
  ...(trash !== undefined ? { trash } : {}),
129
58
  ...(where ? { where } : {}),
@@ -133,19 +62,19 @@ export const findVersionsTool = defineCollectionTool({
133
62
  content: [
134
63
  {
135
64
  type: 'text',
136
- text: `Versions for collection "${collectionSlug}":\n\`\`\`json\n${JSON.stringify(result)}\n\`\`\``,
65
+ text: `Versions for collection "${slug}":\n\`\`\`json\n${JSON.stringify(result)}\n\`\`\``,
137
66
  },
138
67
  ],
139
68
  doc: result as unknown as Record<string, unknown>,
140
69
  }
141
70
  } catch (error) {
142
71
  const errorMessage = error instanceof Error ? error.message : 'Unknown error'
143
- logger.error(`Error finding versions in ${collectionSlug}: ${errorMessage}`)
72
+ logger.error(`Error finding versions in ${slug}: ${errorMessage}`)
144
73
  return {
145
74
  content: [
146
75
  {
147
76
  type: 'text',
148
- text: `❌ **Error finding versions in collection "${collectionSlug}":** ${errorMessage}`,
77
+ text: `❌ **Error finding versions in collection "${slug}":** ${errorMessage}`,
149
78
  },
150
79
  ],
151
80
  isError: true,
@@ -1,12 +1,11 @@
1
- import { getAccessResults } from 'payload'
1
+ import { getAccessResults, getCollectionInputSchema, getCollectionSchemaInputSchema } from 'payload'
2
2
 
3
3
  import { defaultAccess } from '../../../defaultAccess.js'
4
4
  import { defineCollectionTool } from '../../../defineTool.js'
5
- import { getCollectionInputSchema } from '../../../utils/schemaConversion/getEntityInputSchema.js'
6
5
 
7
6
  export const getCollectionSchemaTool = defineCollectionTool({
8
7
  access: (args) => {
9
- const permissions = args.permissions?.collections?.[args.collectionSlug]
8
+ const permissions = args.permissions?.collections?.[args.slug]
10
9
 
11
10
  return defaultAccess(args) && Boolean(permissions?.create || permissions?.update)
12
11
  },
@@ -18,17 +17,18 @@ export const getCollectionSchemaTool = defineCollectionTool({
18
17
  title: 'Get Collection Schema',
19
18
  },
20
19
  description: 'Get the input schema for creating or updating documents in a collection.',
21
- }).handler(async ({ authorizedMCP, collectionSlug, req }) => {
20
+ input: getCollectionSchemaInputSchema,
21
+ }).handler(async ({ slug, authorizedMCP, req }) => {
22
22
  const permissions = authorizedMCP.overrideAccess
23
23
  ? null
24
- : (await getAccessResults({ req })).collections?.[collectionSlug]
24
+ : (await getAccessResults({ req })).collections?.[slug]
25
25
 
26
26
  if (!authorizedMCP.overrideAccess && !permissions?.create && !permissions?.update) {
27
27
  return {
28
28
  content: [
29
29
  {
30
30
  type: 'text',
31
- text: `Error: MCP access to "getCollectionSchema" is not enabled for collection "${collectionSlug}"`,
31
+ text: `Error: MCP access to "getCollectionSchema" is not enabled for collection "${slug}"`,
32
32
  },
33
33
  ],
34
34
  isError: true,
@@ -36,19 +36,19 @@ export const getCollectionSchemaTool = defineCollectionTool({
36
36
  }
37
37
 
38
38
  const inputSchema = getCollectionInputSchema({
39
- collectionSlug,
39
+ collectionSlug: slug,
40
40
  req,
41
41
  ...(permissions ? { permissions } : {}),
42
42
  })
43
43
 
44
44
  if (!inputSchema) {
45
45
  return {
46
- content: [{ type: 'text', text: `Error: Collection "${collectionSlug}" not found` }],
46
+ content: [{ type: 'text', text: `Error: Collection "${slug}" not found` }],
47
47
  isError: true,
48
48
  }
49
49
  }
50
50
 
51
- const uploadConfig = req.payload.collections[collectionSlug]?.config.upload
51
+ const uploadConfig = req.payload.collections[slug]?.config.upload
52
52
  const maxFileSize = req.payload.config.upload.limits?.fileSize
53
53
  const upload = uploadConfig
54
54
  ? {
@@ -68,11 +68,11 @@ export const getCollectionSchemaTool = defineCollectionTool({
68
68
  content: [
69
69
  {
70
70
  type: 'text',
71
- text: `Schema for collection "${collectionSlug}":\n\`\`\`json\n${JSON.stringify(inputSchema)}\n\`\`\`\nUpload configuration:\n\`\`\`json\n${JSON.stringify(upload)}\n\`\`\``,
71
+ text: `Schema for collection "${slug}":\n\`\`\`json\n${JSON.stringify(inputSchema)}\n\`\`\`\nUpload configuration:\n\`\`\`json\n${JSON.stringify(upload)}\n\`\`\``,
72
72
  },
73
73
  ],
74
74
  structuredContent: {
75
- collectionSlug,
75
+ slug,
76
76
  schema: inputSchema,
77
77
  upload,
78
78
  },
@@ -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,26 @@
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
+ stripVirtualFields,
7
+ transformPointDataToPayload,
8
+ updateDocumentInputSchema,
9
+ validateCollectionData,
10
+ } from 'payload'
4
11
 
5
12
  import { defaultAccess } from '../../../defaultAccess.js'
6
13
  import { defineCollectionTool } from '../../../defineTool.js'
7
14
  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'
15
+ import { formatEntityError } from '../formatEntityError.js'
16
16
  import { fileInputSchema, resolveFile } from './fileInput.js'
17
- import { formatCollectionError } from './formatCollectionError.js'
18
17
 
19
18
  const DEFAULT_DESCRIPTION =
20
- 'Update documents in any collection. Files can use a URL, base64, or an upload prepared by getUploadInstructions.'
19
+ 'Update documents. Prefer uploadReference after upload, externalURL for URLs, or base64 for small local files.'
21
20
 
22
21
  export const updateDocumentTool = defineCollectionTool({
23
22
  access: (args) =>
24
- defaultAccess(args) && Boolean(args.permissions?.collections?.[args.collectionSlug]?.update),
23
+ defaultAccess(args) && Boolean(args.permissions?.collections?.[args.slug]?.update),
25
24
  annotations: {
26
25
  destructiveHint: true,
27
26
  idempotentHint: false,
@@ -30,65 +29,8 @@ export const updateDocumentTool = defineCollectionTool({
30
29
  title: 'Update Document',
31
30
  },
32
31
  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 }) => {
32
+ input: updateDocumentInputSchema({ file: fileInputSchema }),
33
+ }).handler(async ({ slug, authorizedMCP, input, req }) => {
92
34
  const payload = req.payload
93
35
  const logger = getLogger({ payload })
94
36
 
@@ -99,66 +41,62 @@ export const updateDocumentTool = defineCollectionTool({
99
41
  draft,
100
42
  fallbackLocale,
101
43
  file: fileInput,
44
+ limit,
102
45
  locale,
103
46
  overrideLock,
104
- overwriteExistingFiles,
47
+ populate,
105
48
  publishAllLocales,
106
49
  select,
50
+ sort,
51
+ trash,
52
+ unpublishAllLocales,
107
53
  where,
108
54
  } = input
109
55
 
110
56
  logger.info(
111
- `Updating document in collection: ${collectionSlug}${id ? ` with ID: ${id}` : ' with where clause'}, draft: ${draft}${locale ? `, locale: ${locale}` : ''}`,
57
+ `Updating document in collection: ${slug}${id ? ` with ID: ${id}` : ' with where clause'}, draft: ${draft}${locale ? `, locale: ${locale}` : ''}`,
112
58
  )
113
59
 
114
60
  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)
61
+ const virtualFieldNames = getCollectionVirtualFieldNames(payload.config, slug)
122
62
  const inputData = stripVirtualFields(data, virtualFieldNames)
123
- const validationError = validateCollectionData({
124
- collectionSlug,
63
+ validateCollectionData({
64
+ slug,
125
65
  data: inputData,
126
66
  partial: true,
127
67
  req,
128
68
  })
129
69
 
130
- if (validationError) {
131
- return validationError
132
- }
133
-
134
70
  const parsedData = transformPointDataToPayload(inputData)
135
- const file = await resolveFile({ collectionSlug, input: fileInput, req })
71
+ const file = await resolveFile({ slug, input: fileInput, req })
136
72
 
137
73
  const whereClause: Where = where ?? {}
138
74
 
139
- if (id) {
75
+ if (id !== undefined) {
140
76
  const result = await payload.update({
141
77
  id,
142
- collection: collectionSlug,
78
+ collection: slug,
143
79
  data: parsedData,
144
80
  depth,
145
81
  draft,
82
+ fallbackLocale,
83
+ locale,
146
84
  overrideAccess: authorizedMCP.overrideAccess,
147
85
  overrideLock,
86
+ populate,
87
+ publishAllLocales,
148
88
  req,
89
+ select,
90
+ trash,
91
+ unpublishAllLocales,
149
92
  ...(file ? { file } : {}),
150
- ...(overwriteExistingFiles ? { overwriteExistingFiles } : {}),
151
- ...(publishAllLocales !== undefined ? { publishAllLocales } : {}),
152
- ...(locale ? { locale } : {}),
153
- ...(fallbackLocale ? { fallbackLocale } : {}),
154
- ...(select ? { select: select as SelectType } : {}),
155
93
  })
156
94
 
157
95
  return {
158
96
  content: [
159
97
  {
160
98
  type: 'text',
161
- text: `Document updated successfully in collection "${collectionSlug}"!\nUpdated document:\n\`\`\`json\n${JSON.stringify(result)}\n\`\`\``,
99
+ text: `Document updated successfully in collection "${slug}"!\nUpdated document:\n\`\`\`json\n${JSON.stringify(result)}\n\`\`\``,
162
100
  },
163
101
  ],
164
102
  doc: result as Record<string, unknown>,
@@ -166,33 +104,37 @@ export const updateDocumentTool = defineCollectionTool({
166
104
  }
167
105
 
168
106
  const result = await payload.update({
169
- collection: collectionSlug,
107
+ collection: slug,
170
108
  data: parsedData,
171
109
  depth,
172
110
  draft,
111
+ fallbackLocale,
112
+ limit,
113
+ locale,
173
114
  overrideAccess: authorizedMCP.overrideAccess,
174
115
  overrideLock,
116
+ populate,
117
+ publishAllLocales,
175
118
  req,
119
+ select,
120
+ sort,
121
+ trash,
122
+ unpublishAllLocales,
176
123
  where: whereClause,
177
124
  ...(file ? { file } : {}),
178
- ...(overwriteExistingFiles ? { overwriteExistingFiles } : {}),
179
- ...(publishAllLocales !== undefined ? { publishAllLocales } : {}),
180
- ...(locale ? { locale } : {}),
181
- ...(fallbackLocale ? { fallbackLocale } : {}),
182
- ...(select ? { select: select as SelectType } : {}),
183
125
  })
184
126
 
185
127
  const docs = result.docs || []
186
128
  const errors = result.errors || []
187
129
 
188
- let responseText = `Multiple documents updated in collection "${collectionSlug}"!\nUpdated: ${docs.length} documents\nErrors: ${errors.length}\n---`
130
+ let responseText = `Multiple documents updated in collection "${slug}"!\nUpdated: ${docs.length} documents\nErrors: ${errors.length}\n---`
189
131
  if (docs.length > 0) {
190
132
  responseText += `\n\nUpdated documents:\n\`\`\`json\n${JSON.stringify(docs)}\n\`\`\``
191
133
  }
192
134
  if (errors.length > 0) {
193
135
  responseText += `\n\nErrors:\n\`\`\`json\n${JSON.stringify(errors)}\n\`\`\``
194
136
 
195
- const errorSchema = getCollectionInputSchema({ collectionSlug, req })
137
+ const errorSchema = getCollectionInputSchema({ collectionSlug: slug, req })
196
138
 
197
139
  if (errorSchema) {
198
140
  responseText += `\n\nUse this schema for data:\n\`\`\`json\n${JSON.stringify(errorSchema)}\n\`\`\``
@@ -205,7 +147,7 @@ export const updateDocumentTool = defineCollectionTool({
205
147
  ...(errorSchema
206
148
  ? {
207
149
  structuredContent: {
208
- collectionSlug,
150
+ slug,
209
151
  docs,
210
152
  errors,
211
153
  schema: errorSchema,
@@ -221,7 +163,7 @@ export const updateDocumentTool = defineCollectionTool({
221
163
  }
222
164
  } catch (error) {
223
165
  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 })
166
+ logger.error(`Error updating document in ${slug}: ${errorMessage}`)
167
+ return formatEntityError({ slug, action: 'updating', entity: 'collection', error, req })
226
168
  }
227
169
  })
@@ -1,5 +1,5 @@
1
+ import { strictObject, z } from 'payload'
1
2
  import { getUploadInstructions as getPayloadUploadInstructions } from 'payload/internal'
2
- import { z } from 'zod'
3
3
 
4
4
  import { defaultAccess } from '../../../defaultAccess.js'
5
5
  import { defineCollectionTool } from '../../../defineTool.js'
@@ -8,8 +8,8 @@ export const getUploadInstructionsTool = defineCollectionTool({
8
8
  access: (args) =>
9
9
  defaultAccess(args) &&
10
10
  Boolean(
11
- args.permissions?.collections?.[args.collectionSlug]?.create ||
12
- args.permissions?.collections?.[args.collectionSlug]?.update,
11
+ args.permissions?.collections?.[args.slug]?.create ||
12
+ args.permissions?.collections?.[args.slug]?.update,
13
13
  ),
14
14
  annotations: {
15
15
  destructiveHint: false,
@@ -19,32 +19,32 @@ export const getUploadInstructionsTool = defineCollectionTool({
19
19
  title: 'Get Upload Instructions',
20
20
  },
21
21
  description:
22
- 'Prepare a file upload before createDocument or updateDocument. Pass file metadata only, without base64 or file contents.',
23
- input: z.object({
24
- docPrefix: z.string().describe('Optional document folder or prefix').optional(),
25
- filename: z.string().describe('The original file name'),
26
- filesize: z.number().int().nonnegative().describe('The file size in bytes'),
27
- mimeType: z.string().describe('The file MIME type'),
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
28
  }),
29
- }).handler(async ({ authorizedMCP, collectionSlug, input, req }) => {
29
+ }).handler(async ({ slug, authorizedMCP, input, req }) => {
30
30
  try {
31
31
  const instructions = await getPayloadUploadInstructions({
32
32
  ...input,
33
- collectionSlug,
33
+ collectionSlug: slug,
34
34
  overrideAccess: authorizedMCP.overrideAccess,
35
35
  req,
36
36
  })
37
37
 
38
38
  const nextStep =
39
39
  instructions.type === 'http'
40
- ? 'Send the exact file bytes using request, then pass { source: "uploadReference", file } to createDocument or updateDocument.'
41
- : `Call the local MCP tool named "${instructions.name}" with the file and data, then pass { source: "uploadReference", file } to createDocument or updateDocument.`
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
42
 
43
43
  return {
44
44
  content: [
45
45
  {
46
46
  type: 'text',
47
- text: `Upload instructions for collection "${collectionSlug}":\n\`\`\`json\n${JSON.stringify(instructions)}\n\`\`\`\n${nextStep}`,
47
+ text: `Upload instructions for collection "${slug}":\n\`\`\`json\n${JSON.stringify(instructions)}\n\`\`\`\n${nextStep}`,
48
48
  },
49
49
  ],
50
50
  structuredContent: { instructions },
@@ -55,7 +55,7 @@ export const getUploadInstructionsTool = defineCollectionTool({
55
55
  content: [
56
56
  {
57
57
  type: 'text',
58
- text: `Error getting upload instructions for collection "${collectionSlug}": ${message}`,
58
+ text: `Error getting upload instructions for collection "${slug}": ${message}`,
59
59
  },
60
60
  ],
61
61
  isError: true,