@payloadcms/plugin-mcp 4.0.0-internal.a0ef1b8 → 4.0.0-internal.a1317b2

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 (240) hide show
  1. package/LICENSE.md +1 -1
  2. package/bin.js +7 -0
  3. package/dist/defaultAccess.d.ts +3 -0
  4. package/dist/defaultAccess.d.ts.map +1 -0
  5. package/dist/defaultAccess.js +3 -0
  6. package/dist/defaultAccess.js.map +1 -0
  7. package/dist/defineTool.d.ts +8 -8
  8. package/dist/defineTool.d.ts.map +1 -1
  9. package/dist/endpoint/access.d.ts +12 -5
  10. package/dist/endpoint/access.d.ts.map +1 -1
  11. package/dist/endpoint/access.js +75 -88
  12. package/dist/endpoint/access.js.map +1 -1
  13. package/dist/endpoint/index.d.ts +1 -1
  14. package/dist/endpoint/index.d.ts.map +1 -1
  15. package/dist/endpoint/index.js +68 -17
  16. package/dist/endpoint/index.js.map +1 -1
  17. package/dist/exports/client.d.ts +1 -1
  18. package/dist/exports/client.d.ts.map +1 -1
  19. package/dist/exports/client.js +1 -1
  20. package/dist/exports/client.js.map +1 -1
  21. package/dist/exports/internal.d.ts +2 -0
  22. package/dist/exports/internal.d.ts.map +1 -0
  23. package/dist/exports/internal.js +3 -0
  24. package/dist/exports/internal.js.map +1 -0
  25. package/dist/index.d.ts +2 -2
  26. package/dist/index.d.ts.map +1 -1
  27. package/dist/index.js +15 -20
  28. package/dist/index.js.map +1 -1
  29. package/dist/mcp/buildMcpServer.d.ts +5 -5
  30. package/dist/mcp/buildMcpServer.d.ts.map +1 -1
  31. package/dist/mcp/buildMcpServer.js +145 -80
  32. package/dist/mcp/buildMcpServer.js.map +1 -1
  33. package/dist/mcp/builtin/collections/authTools.d.ts.map +1 -1
  34. package/dist/mcp/builtin/collections/authTools.js +122 -61
  35. package/dist/mcp/builtin/collections/authTools.js.map +1 -1
  36. package/dist/mcp/builtin/collections/countTool.d.ts +2 -0
  37. package/dist/mcp/builtin/collections/countTool.d.ts.map +1 -0
  38. package/dist/mcp/builtin/collections/countTool.js +63 -0
  39. package/dist/mcp/builtin/collections/countTool.js.map +1 -0
  40. package/dist/mcp/builtin/collections/countVersionsTool.d.ts +2 -0
  41. package/dist/mcp/builtin/collections/countVersionsTool.d.ts.map +1 -0
  42. package/dist/mcp/builtin/collections/countVersionsTool.js +60 -0
  43. package/dist/mcp/builtin/collections/countVersionsTool.js.map +1 -0
  44. package/dist/mcp/builtin/collections/createTool.d.ts +1 -1
  45. package/dist/mcp/builtin/collections/createTool.d.ts.map +1 -1
  46. package/dist/mcp/builtin/collections/createTool.js +111 -68
  47. package/dist/mcp/builtin/collections/createTool.js.map +1 -1
  48. package/dist/mcp/builtin/collections/deleteTool.d.ts +1 -1
  49. package/dist/mcp/builtin/collections/deleteTool.d.ts.map +1 -1
  50. package/dist/mcp/builtin/collections/deleteTool.js +51 -61
  51. package/dist/mcp/builtin/collections/deleteTool.js.map +1 -1
  52. package/dist/mcp/builtin/collections/duplicateTool.d.ts +2 -0
  53. package/dist/mcp/builtin/collections/duplicateTool.d.ts.map +1 -0
  54. package/dist/mcp/builtin/collections/duplicateTool.js +86 -0
  55. package/dist/mcp/builtin/collections/duplicateTool.js.map +1 -0
  56. package/dist/mcp/builtin/collections/fileInput.d.ts +28 -0
  57. package/dist/mcp/builtin/collections/fileInput.d.ts.map +1 -0
  58. package/dist/mcp/builtin/collections/fileInput.js +123 -0
  59. package/dist/mcp/builtin/collections/fileInput.js.map +1 -0
  60. package/dist/mcp/builtin/collections/fileInput.spec.js +86 -0
  61. package/dist/mcp/builtin/collections/fileInput.spec.js.map +1 -0
  62. package/dist/mcp/builtin/collections/findDistinctTool.d.ts +2 -0
  63. package/dist/mcp/builtin/collections/findDistinctTool.d.ts.map +1 -0
  64. package/dist/mcp/builtin/collections/findDistinctTool.js +77 -0
  65. package/dist/mcp/builtin/collections/findDistinctTool.js.map +1 -0
  66. package/dist/mcp/builtin/collections/findTool.d.ts +1 -1
  67. package/dist/mcp/builtin/collections/findTool.d.ts.map +1 -1
  68. package/dist/mcp/builtin/collections/findTool.js +55 -72
  69. package/dist/mcp/builtin/collections/findTool.js.map +1 -1
  70. package/dist/mcp/builtin/collections/findVersionByIDTool.d.ts +2 -0
  71. package/dist/mcp/builtin/collections/findVersionByIDTool.d.ts.map +1 -0
  72. package/dist/mcp/builtin/collections/findVersionByIDTool.js +74 -0
  73. package/dist/mcp/builtin/collections/findVersionByIDTool.js.map +1 -0
  74. package/dist/mcp/builtin/collections/findVersionsTool.d.ts +2 -0
  75. package/dist/mcp/builtin/collections/findVersionsTool.d.ts.map +1 -0
  76. package/dist/mcp/builtin/collections/findVersionsTool.js +84 -0
  77. package/dist/mcp/builtin/collections/findVersionsTool.js.map +1 -0
  78. package/dist/mcp/builtin/collections/getCollectionSchemaTool.d.ts +2 -0
  79. package/dist/mcp/builtin/collections/getCollectionSchemaTool.d.ts.map +1 -0
  80. package/dist/mcp/builtin/collections/getCollectionSchemaTool.js +87 -0
  81. package/dist/mcp/builtin/collections/getCollectionSchemaTool.js.map +1 -0
  82. package/dist/mcp/builtin/collections/restoreVersionTool.d.ts +2 -0
  83. package/dist/mcp/builtin/collections/restoreVersionTool.d.ts.map +1 -0
  84. package/dist/mcp/builtin/collections/restoreVersionTool.js +69 -0
  85. package/dist/mcp/builtin/collections/restoreVersionTool.js.map +1 -0
  86. package/dist/mcp/builtin/collections/updateTool.d.ts +1 -1
  87. package/dist/mcp/builtin/collections/updateTool.d.ts.map +1 -1
  88. package/dist/mcp/builtin/collections/updateTool.js +104 -136
  89. package/dist/mcp/builtin/collections/updateTool.js.map +1 -1
  90. package/dist/mcp/builtin/collections/uploadInstructionsTool.d.ts +2 -0
  91. package/dist/mcp/builtin/collections/uploadInstructionsTool.d.ts.map +1 -0
  92. package/dist/mcp/builtin/collections/uploadInstructionsTool.js +55 -0
  93. package/dist/mcp/builtin/collections/uploadInstructionsTool.js.map +1 -0
  94. package/dist/mcp/builtin/formatEntityError.d.ts +16 -0
  95. package/dist/mcp/builtin/formatEntityError.d.ts.map +1 -0
  96. package/dist/mcp/builtin/formatEntityError.js +55 -0
  97. package/dist/mcp/builtin/formatEntityError.js.map +1 -0
  98. package/dist/mcp/builtin/getConfigInfoTool.d.ts +2 -0
  99. package/dist/mcp/builtin/getConfigInfoTool.d.ts.map +1 -0
  100. package/dist/mcp/builtin/getConfigInfoTool.js +69 -0
  101. package/dist/mcp/builtin/getConfigInfoTool.js.map +1 -0
  102. package/dist/mcp/builtin/globals/countVersionsTool.d.ts +2 -0
  103. package/dist/mcp/builtin/globals/countVersionsTool.d.ts.map +1 -0
  104. package/dist/mcp/builtin/globals/countVersionsTool.js +60 -0
  105. package/dist/mcp/builtin/globals/countVersionsTool.js.map +1 -0
  106. package/dist/mcp/builtin/globals/findTool.d.ts.map +1 -1
  107. package/dist/mcp/builtin/globals/findTool.js +27 -36
  108. package/dist/mcp/builtin/globals/findTool.js.map +1 -1
  109. package/dist/mcp/builtin/globals/findVersionByIDTool.d.ts +2 -0
  110. package/dist/mcp/builtin/globals/findVersionByIDTool.d.ts.map +1 -0
  111. package/dist/mcp/builtin/globals/findVersionByIDTool.js +68 -0
  112. package/dist/mcp/builtin/globals/findVersionByIDTool.js.map +1 -0
  113. package/dist/mcp/builtin/globals/findVersionsTool.d.ts +2 -0
  114. package/dist/mcp/builtin/globals/findVersionsTool.d.ts.map +1 -0
  115. package/dist/mcp/builtin/globals/findVersionsTool.js +78 -0
  116. package/dist/mcp/builtin/globals/findVersionsTool.js.map +1 -0
  117. package/dist/mcp/builtin/globals/getGlobalSchemaTool.d.ts +2 -0
  118. package/dist/mcp/builtin/globals/getGlobalSchemaTool.d.ts.map +1 -0
  119. package/dist/mcp/builtin/globals/getGlobalSchemaTool.js +65 -0
  120. package/dist/mcp/builtin/globals/getGlobalSchemaTool.js.map +1 -0
  121. package/dist/mcp/builtin/globals/restoreVersionTool.d.ts +2 -0
  122. package/dist/mcp/builtin/globals/restoreVersionTool.d.ts.map +1 -0
  123. package/dist/mcp/builtin/globals/restoreVersionTool.js +70 -0
  124. package/dist/mcp/builtin/globals/restoreVersionTool.js.map +1 -0
  125. package/dist/mcp/builtin/globals/updateTool.d.ts.map +1 -1
  126. package/dist/mcp/builtin/globals/updateTool.js +44 -62
  127. package/dist/mcp/builtin/globals/updateTool.js.map +1 -1
  128. package/dist/mcp/builtinTools.d.ts +150 -19
  129. package/dist/mcp/builtinTools.d.ts.map +1 -1
  130. package/dist/mcp/builtinTools.js +125 -20
  131. package/dist/mcp/builtinTools.js.map +1 -1
  132. package/dist/mcp/sanitizeMCPConfig.d.ts +0 -1
  133. package/dist/mcp/sanitizeMCPConfig.d.ts.map +1 -1
  134. package/dist/mcp/sanitizeMCPConfig.js +124 -58
  135. package/dist/mcp/sanitizeMCPConfig.js.map +1 -1
  136. package/dist/stdio.d.ts +3 -3
  137. package/dist/stdio.d.ts.map +1 -1
  138. package/dist/stdio.js +84 -46
  139. package/dist/stdio.js.map +1 -1
  140. package/dist/types.d.ts +114 -112
  141. package/dist/types.d.ts.map +1 -1
  142. package/dist/types.js +2 -4
  143. package/dist/types.js.map +1 -1
  144. package/dist/utils/camelCase.d.ts.map +1 -1
  145. package/dist/utils/getPluginConfig.d.ts +1 -1
  146. package/dist/utils/getPluginConfig.js +1 -1
  147. package/dist/utils/getPluginConfig.js.map +1 -1
  148. package/dist/utils/resolveProjectRoot.d.ts.map +1 -1
  149. package/dist/utils/toStandardSchema.d.ts.map +1 -1
  150. package/package.json +11 -18
  151. package/src/defaultAccess.ts +3 -0
  152. package/src/endpoint/access.ts +80 -101
  153. package/src/endpoint/index.ts +58 -16
  154. package/src/exports/client.ts +2 -1
  155. package/src/exports/internal.ts +1 -0
  156. package/src/index.ts +12 -20
  157. package/src/mcp/buildMcpServer.ts +179 -114
  158. package/src/mcp/builtin/collections/authTools.ts +119 -75
  159. package/src/mcp/builtin/collections/countTool.ts +61 -0
  160. package/src/mcp/builtin/collections/countVersionsTool.ts +60 -0
  161. package/src/mcp/builtin/collections/createTool.ts +104 -88
  162. package/src/mcp/builtin/collections/deleteTool.ts +48 -74
  163. package/src/mcp/builtin/collections/duplicateTool.ts +83 -0
  164. package/src/mcp/builtin/collections/fileInput.spec.ts +93 -0
  165. package/src/mcp/builtin/collections/fileInput.ts +169 -0
  166. package/src/mcp/builtin/collections/findDistinctTool.ts +67 -0
  167. package/src/mcp/builtin/collections/findTool.ts +55 -108
  168. package/src/mcp/builtin/collections/findVersionByIDTool.ts +66 -0
  169. package/src/mcp/builtin/collections/findVersionsTool.ts +83 -0
  170. package/src/mcp/builtin/collections/getCollectionSchemaTool.ts +80 -0
  171. package/src/mcp/builtin/collections/restoreVersionTool.ts +65 -0
  172. package/src/mcp/builtin/collections/updateTool.ts +101 -142
  173. package/src/mcp/builtin/collections/uploadInstructionsTool.ts +64 -0
  174. package/src/mcp/builtin/formatEntityError.ts +77 -0
  175. package/src/mcp/builtin/getConfigInfoTool.ts +68 -0
  176. package/src/mcp/builtin/globals/countVersionsTool.ts +60 -0
  177. package/src/mcp/builtin/globals/findTool.ts +27 -57
  178. package/src/mcp/builtin/globals/findVersionByIDTool.ts +64 -0
  179. package/src/mcp/builtin/globals/findVersionsTool.ts +69 -0
  180. package/src/mcp/builtin/globals/getGlobalSchemaTool.ts +63 -0
  181. package/src/mcp/builtin/globals/restoreVersionTool.ts +68 -0
  182. package/src/mcp/builtin/globals/updateTool.ts +51 -79
  183. package/src/mcp/builtinTools.ts +118 -41
  184. package/src/mcp/sanitizeMCPConfig.ts +120 -78
  185. package/src/stdio.ts +79 -46
  186. package/src/types.ts +130 -117
  187. package/src/utils/getPluginConfig.ts +1 -1
  188. package/dist/@types/assets.d.js +0 -2
  189. package/dist/@types/assets.d.js.map +0 -1
  190. package/dist/collection/getAccessField.d.ts +0 -12
  191. package/dist/collection/getAccessField.d.ts.map +0 -1
  192. package/dist/collection/getAccessField.js +0 -57
  193. package/dist/collection/getAccessField.js.map +0 -1
  194. package/dist/collection/index.d.ts +0 -6
  195. package/dist/collection/index.d.ts.map +0 -1
  196. package/dist/collection/index.js +0 -60
  197. package/dist/collection/index.js.map +0 -1
  198. package/dist/components/AccessField/index.client.d.ts +0 -10
  199. package/dist/components/AccessField/index.client.d.ts.map +0 -1
  200. package/dist/components/AccessField/index.client.js +0 -305
  201. package/dist/components/AccessField/index.client.js.map +0 -1
  202. package/dist/components/AccessField/index.css +0 -93
  203. package/dist/utils/getVirtualFieldNames.d.ts +0 -14
  204. package/dist/utils/getVirtualFieldNames.d.ts.map +0 -1
  205. package/dist/utils/getVirtualFieldNames.js +0 -35
  206. package/dist/utils/getVirtualFieldNames.js.map +0 -1
  207. package/dist/utils/localAPIDefaults.d.ts +0 -20
  208. package/dist/utils/localAPIDefaults.d.ts.map +0 -1
  209. package/dist/utils/localAPIDefaults.js +0 -19
  210. package/dist/utils/localAPIDefaults.js.map +0 -1
  211. package/dist/utils/schemaConversion/buildToolInput.d.ts +0 -29
  212. package/dist/utils/schemaConversion/buildToolInput.d.ts.map +0 -1
  213. package/dist/utils/schemaConversion/buildToolInput.js +0 -51
  214. package/dist/utils/schemaConversion/buildToolInput.js.map +0 -1
  215. package/dist/utils/schemaConversion/removeVirtualFieldsFromSchema.d.ts +0 -7
  216. package/dist/utils/schemaConversion/removeVirtualFieldsFromSchema.d.ts.map +0 -1
  217. package/dist/utils/schemaConversion/removeVirtualFieldsFromSchema.js +0 -20
  218. package/dist/utils/schemaConversion/removeVirtualFieldsFromSchema.js.map +0 -1
  219. package/dist/utils/schemaConversion/sanitizeEntitySchema.d.ts +0 -15
  220. package/dist/utils/schemaConversion/sanitizeEntitySchema.d.ts.map +0 -1
  221. package/dist/utils/schemaConversion/sanitizeEntitySchema.js +0 -464
  222. package/dist/utils/schemaConversion/sanitizeEntitySchema.js.map +0 -1
  223. package/dist/utils/schemaConversion/sanitizeEntitySchema.spec.js +0 -158
  224. package/dist/utils/schemaConversion/sanitizeEntitySchema.spec.js.map +0 -1
  225. package/dist/utils/transformPointDataToPayload.d.ts +0 -7
  226. package/dist/utils/transformPointDataToPayload.d.ts.map +0 -1
  227. package/dist/utils/transformPointDataToPayload.js +0 -28
  228. package/dist/utils/transformPointDataToPayload.js.map +0 -1
  229. package/src/@types/assets.d.ts +0 -3
  230. package/src/collection/getAccessField.ts +0 -64
  231. package/src/collection/index.ts +0 -64
  232. package/src/components/AccessField/index.client.tsx +0 -344
  233. package/src/components/AccessField/index.css +0 -93
  234. package/src/utils/getVirtualFieldNames.ts +0 -53
  235. package/src/utils/localAPIDefaults.ts +0 -22
  236. package/src/utils/schemaConversion/buildToolInput.ts +0 -68
  237. package/src/utils/schemaConversion/removeVirtualFieldsFromSchema.ts +0 -27
  238. package/src/utils/schemaConversion/sanitizeEntitySchema.spec.ts +0 -103
  239. package/src/utils/schemaConversion/sanitizeEntitySchema.ts +0 -529
  240. package/src/utils/transformPointDataToPayload.ts +0 -40
@@ -1,7 +1,8 @@
1
- import { z } from 'zod'
1
+ import { createLocalReq, strictObject, z } from 'payload'
2
2
 
3
3
  import type { MCPToolResponse } from '../../../types.js'
4
4
 
5
+ import { defaultAccess } from '../../../defaultAccess.js'
5
6
  import { defineCollectionTool } from '../../../defineTool.js'
6
7
  import { getLogger } from '../../../utils/getLogger.js'
7
8
 
@@ -16,43 +17,62 @@ import { getLogger } from '../../../utils/getLogger.js'
16
17
  * users collection so all auth-shaped tools live in one place.
17
18
  */
18
19
 
19
- const emailSchema = z.string().email().describe('The user email address')
20
+ const emailSchema = z.email().check(z.describe('The user email address.'))
20
21
 
21
22
  const wrapError =
22
23
  (name: string) =>
23
- ({ collectionSlug, message }: { collectionSlug: string; message: string }): MCPToolResponse => {
24
+ ({ slug, message }: { message: string; slug: string }): MCPToolResponse => {
24
25
  return {
25
26
  content: [
26
27
  {
27
28
  type: 'text',
28
- text: `❌ **Error in ${name}** on ${collectionSlug}: ${message}`,
29
+ text: `❌ **Error in ${name}** on ${slug}: ${message}`,
29
30
  },
30
31
  ],
31
32
  }
32
33
  }
33
34
 
34
35
  export const authCollectionTool = defineCollectionTool({
36
+ annotations: {
37
+ destructiveHint: false,
38
+ idempotentHint: true,
39
+ openWorldHint: false,
40
+ readOnlyHint: true,
41
+ title: 'Check Auth Status',
42
+ },
35
43
  description: 'Checks authentication status for the current user.',
36
- input: z.object({
44
+ input: strictObject({
37
45
  headers: z
38
- .string()
39
- .describe(
40
- 'Optional JSON string containing custom headers to send with the authentication request',
41
- )
42
- .optional(),
46
+ .optional(z.record(z.string(), z.string()))
47
+ .check(z.describe('Custom headers to send with the authentication request.')),
43
48
  }),
44
- }).handler(async ({ collectionSlug, input, req }) => {
49
+ }).handler(async ({ slug, authorizedMCP, input, req }) => {
45
50
  const logger = getLogger({ payload: req.payload })
46
51
  try {
47
52
  let authHeaders = new Headers()
48
53
  if (input.headers) {
49
- try {
50
- authHeaders = new Headers(JSON.parse(input.headers) as Record<string, string>)
51
- } catch {
52
- logger.warn(`Invalid headers JSON for auth: ${input.headers}, using empty headers`)
54
+ authHeaders = new Headers(input.headers)
55
+ }
56
+ const authReq = await createLocalReq({ req: { headers: authHeaders } }, req.payload)
57
+ const result = await req.payload.auth({ headers: authHeaders, req: authReq })
58
+
59
+ if (result.user) {
60
+ const authenticatedUser = result.user
61
+ // Auth strategies read users with trusted Local API access. Re-read the user with the MCP
62
+ // caller's access level before returning it to the client.
63
+ const user = await req.payload.findByID({
64
+ id: authenticatedUser.id,
65
+ collection: authenticatedUser.collection,
66
+ overrideAccess: authorizedMCP.overrideAccess,
67
+ req: authReq,
68
+ })
69
+ result.user = {
70
+ ...user,
71
+ _sid: authenticatedUser._sid,
72
+ _strategy: authenticatedUser._strategy,
73
+ collection: authenticatedUser.collection,
53
74
  }
54
75
  }
55
- const result = await req.payload.auth({ headers: authHeaders })
56
76
  return {
57
77
  content: [
58
78
  {
@@ -64,170 +84,194 @@ export const authCollectionTool = defineCollectionTool({
64
84
  }
65
85
  } catch (error) {
66
86
  const errorMessage = error instanceof Error ? error.message : 'Unknown error'
67
- logger.error(`Error in auth tool on ${collectionSlug}: ${errorMessage}`)
68
- return wrapError('auth')({ collectionSlug, message: errorMessage })
87
+ logger.error(`Error in auth tool on ${slug}: ${errorMessage}`)
88
+ return wrapError('auth')({ slug, message: errorMessage })
69
89
  }
70
90
  })
71
91
 
72
92
  export const forgotPasswordCollectionTool = defineCollectionTool({
93
+ annotations: {
94
+ destructiveHint: false,
95
+ idempotentHint: false,
96
+ openWorldHint: true,
97
+ readOnlyHint: false,
98
+ title: 'Forgot Password',
99
+ },
73
100
  description: 'Sends a password reset email to a user.',
74
- input: z.object({
75
- disableEmail: z
76
- .boolean()
77
- .describe('Whether to disable sending the email (for testing)')
78
- .optional()
79
- .default(false),
101
+ input: strictObject({
80
102
  email: emailSchema,
81
103
  }),
82
- }).handler(async ({ collectionSlug, input, req }) => {
104
+ }).handler(async ({ slug, input, req }) => {
83
105
  const logger = getLogger({ payload: req.payload })
84
106
  try {
85
- const result = await req.payload.forgotPassword({
86
- collection: collectionSlug,
107
+ await req.payload.forgotPassword({
108
+ collection: slug,
87
109
  data: { email: input.email },
88
- disableEmail: input.disableEmail,
110
+ disableEmail: false,
111
+ overrideAccess: false,
112
+ req,
89
113
  })
90
114
  return {
91
115
  content: [
92
116
  {
93
117
  type: 'text',
94
- text: `# Forgot Password Email Sent\n\n**Collection:** ${collectionSlug}\n**Email:** ${input.email}\n\n\`\`\`json\n${JSON.stringify(result)}\n\`\`\``,
118
+ text: 'If an account matches that email, password reset instructions have been sent.',
95
119
  },
96
120
  ],
97
- doc: { result } as Record<string, unknown>,
98
121
  }
99
122
  } catch (error) {
100
123
  const errorMessage = error instanceof Error ? error.message : 'Unknown error'
101
- logger.error(`Error in forgotPassword tool on ${collectionSlug}: ${errorMessage}`)
102
- return wrapError('forgotPassword')({ collectionSlug, message: errorMessage })
124
+ logger.error(`Error in forgotPassword tool on ${slug}: ${errorMessage}`)
125
+ return wrapError('forgotPassword')({ slug, message: errorMessage })
103
126
  }
104
127
  })
105
128
 
106
129
  export const loginCollectionTool = defineCollectionTool({
130
+ annotations: {
131
+ destructiveHint: false,
132
+ idempotentHint: false,
133
+ openWorldHint: false,
134
+ readOnlyHint: false,
135
+ title: 'User Login',
136
+ },
107
137
  description: 'Authenticates a user with email and password.',
108
- input: z.object({
138
+ input: strictObject({
109
139
  depth: z
110
- .number()
111
- .int()
112
- .min(0)
113
- .max(10)
114
- .describe('Depth of population for relationships')
115
- .optional()
116
- .default(0),
140
+ ._default(z.int().check(z.minimum(0), z.maximum(10)), 0)
141
+ .check(z.describe('Depth of population for relationships.')),
117
142
  email: emailSchema,
118
- password: z.string().describe('The user password'),
119
- showHiddenFields: z
120
- .boolean()
121
- .describe('Whether to show hidden fields in the response')
122
- .optional()
123
- .default(false),
143
+ password: z.string().check(z.describe('The user password.')),
124
144
  }),
125
- }).handler(async ({ collectionSlug, input, req }) => {
145
+ }).handler(async ({ slug, authorizedMCP, input, req }) => {
126
146
  const logger = getLogger({ payload: req.payload })
127
147
  try {
128
148
  const result = await req.payload.login({
129
- collection: collectionSlug,
149
+ collection: slug,
130
150
  data: { email: input.email, password: input.password },
131
151
  depth: input.depth,
132
- showHiddenFields: input.showHiddenFields,
152
+ overrideAccess: authorizedMCP.overrideAccess,
133
153
  })
134
154
  return {
135
155
  content: [
136
156
  {
137
157
  type: 'text',
138
- text: `# Login Successful\n\n**User:** ${input.email}\n**Collection:** ${collectionSlug}\n\n\`\`\`json\n${JSON.stringify(result)}\n\`\`\``,
158
+ text: `# Login Successful\n\n**User:** ${input.email}\n**Collection:** ${slug}\n\n\`\`\`json\n${JSON.stringify(result)}\n\`\`\``,
139
159
  },
140
160
  ],
141
161
  doc: result as unknown as Record<string, unknown>,
142
162
  }
143
163
  } catch (error) {
144
164
  const errorMessage = error instanceof Error ? error.message : 'Unknown error'
145
- logger.error(`Error in login tool on ${collectionSlug}: ${errorMessage}`)
146
- return wrapError('login')({ collectionSlug, message: errorMessage })
165
+ logger.error(`Error in login tool on ${slug}: ${errorMessage}`)
166
+ return wrapError('login')({ slug, message: errorMessage })
147
167
  }
148
168
  })
149
169
 
150
170
  export const resetPasswordCollectionTool = defineCollectionTool({
171
+ annotations: {
172
+ destructiveHint: false,
173
+ idempotentHint: false,
174
+ openWorldHint: false,
175
+ readOnlyHint: false,
176
+ title: 'Reset Password',
177
+ },
151
178
  description: 'Resets a user password with a reset token.',
152
- input: z.object({
153
- password: z.string().describe('The new password for the user'),
154
- token: z.string().describe('The password reset token sent to the user email'),
179
+ input: strictObject({
180
+ password: z.string().check(z.describe('The new password for the user.')),
181
+ token: z.string().check(z.describe('The password reset token sent to the user email.')),
155
182
  }),
156
- }).handler(async ({ collectionSlug, input, req }) => {
183
+ }).handler(async ({ slug, authorizedMCP, input, req }) => {
157
184
  const logger = getLogger({ payload: req.payload })
158
185
  try {
159
186
  const result = await req.payload.resetPassword({
160
- collection: collectionSlug,
187
+ collection: slug,
161
188
  data: { password: input.password, token: input.token },
162
- overrideAccess: true,
189
+ overrideAccess: authorizedMCP.overrideAccess,
163
190
  })
164
191
  return {
165
192
  content: [
166
193
  {
167
194
  type: 'text',
168
- text: `# Password Reset Successful\n\n**Collection:** ${collectionSlug}\n\n\`\`\`json\n${JSON.stringify(result)}\n\`\`\``,
195
+ text: `# Password Reset Successful\n\n**Collection:** ${slug}\n\n\`\`\`json\n${JSON.stringify(result)}\n\`\`\``,
169
196
  },
170
197
  ],
171
198
  doc: result as unknown as Record<string, unknown>,
172
199
  }
173
200
  } catch (error) {
174
201
  const errorMessage = error instanceof Error ? error.message : 'Unknown error'
175
- logger.error(`Error in resetPassword tool on ${collectionSlug}: ${errorMessage}`)
176
- return wrapError('resetPassword')({ collectionSlug, message: errorMessage })
202
+ logger.error(`Error in resetPassword tool on ${slug}: ${errorMessage}`)
203
+ return wrapError('resetPassword')({ slug, message: errorMessage })
177
204
  }
178
205
  })
179
206
 
180
207
  export const unlockCollectionTool = defineCollectionTool({
208
+ access: (args) =>
209
+ defaultAccess(args) && Boolean(args.permissions?.collections?.[args.slug]?.unlock),
210
+ annotations: {
211
+ destructiveHint: false,
212
+ idempotentHint: true,
213
+ openWorldHint: false,
214
+ readOnlyHint: false,
215
+ title: 'Unlock Account',
216
+ },
181
217
  description: 'Unlocks a user account that has been locked due to failed login attempts.',
182
- input: z.object({ email: emailSchema }),
183
- }).handler(async ({ collectionSlug, input, req }) => {
218
+ input: strictObject({ email: emailSchema }),
219
+ }).handler(async ({ slug, authorizedMCP, input, req }) => {
184
220
  const logger = getLogger({ payload: req.payload })
185
221
  try {
186
222
  const result = await req.payload.unlock({
187
- collection: collectionSlug,
223
+ collection: slug,
188
224
  data: { email: input.email },
189
- overrideAccess: true,
225
+ overrideAccess: authorizedMCP.overrideAccess,
226
+ req,
190
227
  })
191
228
  return {
192
229
  content: [
193
230
  {
194
231
  type: 'text',
195
- text: `# Account Unlocked\n\n**Collection:** ${collectionSlug}\n**Email:** ${input.email}\n**Result:** ${result ? 'Success' : 'Failed'}`,
232
+ text: `# Account Unlocked\n\n**Collection:** ${slug}\n**Email:** ${input.email}\n**Result:** ${result ? 'Success' : 'Failed'}`,
196
233
  },
197
234
  ],
198
235
  doc: { result } as Record<string, unknown>,
199
236
  }
200
237
  } catch (error) {
201
238
  const errorMessage = error instanceof Error ? error.message : 'Unknown error'
202
- logger.error(`Error in unlock tool on ${collectionSlug}: ${errorMessage}`)
203
- return wrapError('unlock')({ collectionSlug, message: errorMessage })
239
+ logger.error(`Error in unlock tool on ${slug}: ${errorMessage}`)
240
+ return wrapError('unlock')({ slug, message: errorMessage })
204
241
  }
205
242
  })
206
243
 
207
244
  export const verifyCollectionTool = defineCollectionTool({
245
+ annotations: {
246
+ destructiveHint: false,
247
+ idempotentHint: false,
248
+ openWorldHint: false,
249
+ readOnlyHint: false,
250
+ title: 'Email Verification',
251
+ },
208
252
  description: 'Verifies a user email with a verification token.',
209
- input: z.object({
210
- token: z.string().describe('The verification token sent to the user email'),
253
+ input: strictObject({
254
+ token: z.string().check(z.describe('The verification token sent to the user email.')),
211
255
  }),
212
- }).handler(async ({ collectionSlug, input, req }) => {
256
+ }).handler(async ({ slug, input, req }) => {
213
257
  const logger = getLogger({ payload: req.payload })
214
258
  try {
215
259
  const result = await req.payload.verifyEmail({
216
- collection: collectionSlug,
260
+ collection: slug,
217
261
  token: input.token,
218
262
  })
219
263
  return {
220
264
  content: [
221
265
  {
222
266
  type: 'text',
223
- text: `# Email Verification Successful\n\n**Collection:** ${collectionSlug}\n**Result:** ${result ? 'Success' : 'Failed'}`,
267
+ text: `# Email Verification Successful\n\n**Collection:** ${slug}\n**Result:** ${result ? 'Success' : 'Failed'}`,
224
268
  },
225
269
  ],
226
270
  doc: { result } as Record<string, unknown>,
227
271
  }
228
272
  } catch (error) {
229
273
  const errorMessage = error instanceof Error ? error.message : 'Unknown error'
230
- logger.error(`Error in verify tool on ${collectionSlug}: ${errorMessage}`)
231
- return wrapError('verify')({ collectionSlug, message: errorMessage })
274
+ logger.error(`Error in verify tool on ${slug}: ${errorMessage}`)
275
+ return wrapError('verify')({ slug, message: errorMessage })
232
276
  }
233
277
  })
@@ -0,0 +1,61 @@
1
+ import { countDocumentsInputSchema } from 'payload'
2
+
3
+ import { defaultAccess } from '../../../defaultAccess.js'
4
+ import { defineCollectionTool } from '../../../defineTool.js'
5
+ import { getLogger } from '../../../utils/getLogger.js'
6
+
7
+ const DEFAULT_DESCRIPTION =
8
+ 'Count documents in any collection by passing the collection slug and optional where clause.'
9
+
10
+ export const countDocumentsTool = defineCollectionTool({
11
+ access: (args) =>
12
+ defaultAccess(args) && Boolean(args.permissions?.collections?.[args.slug]?.read),
13
+ annotations: {
14
+ destructiveHint: false,
15
+ idempotentHint: true,
16
+ openWorldHint: false,
17
+ readOnlyHint: true,
18
+ title: 'Count Documents',
19
+ },
20
+ description: DEFAULT_DESCRIPTION,
21
+ input: countDocumentsInputSchema,
22
+ }).handler(async ({ slug, authorizedMCP, input, req }) => {
23
+ const payload = req.payload
24
+ const logger = getLogger({ payload })
25
+ const { locale, trash, where } = input
26
+
27
+ logger.info(`Counting documents in collection: ${slug}`)
28
+
29
+ try {
30
+ const result = await payload.count({
31
+ collection: slug,
32
+ overrideAccess: authorizedMCP.overrideAccess,
33
+ req,
34
+ ...(locale ? { locale } : {}),
35
+ ...(trash !== undefined ? { trash } : {}),
36
+ ...(where ? { where } : {}),
37
+ })
38
+
39
+ return {
40
+ content: [
41
+ {
42
+ type: 'text',
43
+ text: `Collection "${slug}" contains ${result.totalDocs} matching documents.\n\`\`\`json\n${JSON.stringify(result)}\n\`\`\``,
44
+ },
45
+ ],
46
+ doc: result,
47
+ }
48
+ } catch (error) {
49
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error'
50
+ logger.error(`Error counting documents in ${slug}: ${errorMessage}`)
51
+ return {
52
+ content: [
53
+ {
54
+ type: 'text',
55
+ text: `❌ **Error counting documents in collection "${slug}":** ${errorMessage}`,
56
+ },
57
+ ],
58
+ isError: true,
59
+ }
60
+ }
61
+ })
@@ -0,0 +1,60 @@
1
+ import { countVersionsInputSchema } from 'payload'
2
+
3
+ import { defaultAccess } from '../../../defaultAccess.js'
4
+ import { defineCollectionTool } from '../../../defineTool.js'
5
+ import { getLogger } from '../../../utils/getLogger.js'
6
+
7
+ const DEFAULT_DESCRIPTION =
8
+ 'Count document versions in any version-enabled collection by passing the collection slug and optional where clause.'
9
+
10
+ export const countVersionsTool = defineCollectionTool({
11
+ access: (args) =>
12
+ defaultAccess(args) && Boolean(args.permissions?.collections?.[args.slug]?.readVersions),
13
+ annotations: {
14
+ destructiveHint: false,
15
+ idempotentHint: true,
16
+ openWorldHint: false,
17
+ readOnlyHint: true,
18
+ title: 'Count Versions',
19
+ },
20
+ description: DEFAULT_DESCRIPTION,
21
+ input: countVersionsInputSchema,
22
+ }).handler(async ({ slug, authorizedMCP, input, req }) => {
23
+ const payload = req.payload
24
+ const logger = getLogger({ payload })
25
+ const { locale, where } = input
26
+
27
+ logger.info(`Counting versions in collection: ${slug}`)
28
+
29
+ try {
30
+ const result = await payload.countVersions({
31
+ collection: slug,
32
+ overrideAccess: authorizedMCP.overrideAccess,
33
+ req,
34
+ ...(locale ? { locale } : {}),
35
+ ...(where ? { where } : {}),
36
+ })
37
+
38
+ return {
39
+ content: [
40
+ {
41
+ type: 'text',
42
+ text: `Collection "${slug}" contains ${result.totalDocs} matching versions.\n\`\`\`json\n${JSON.stringify(result)}\n\`\`\``,
43
+ },
44
+ ],
45
+ doc: result,
46
+ }
47
+ } catch (error) {
48
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error'
49
+ logger.error(`Error counting versions in ${slug}: ${errorMessage}`)
50
+ return {
51
+ content: [
52
+ {
53
+ type: 'text',
54
+ text: `❌ **Error counting versions in collection "${slug}":** ${errorMessage}`,
55
+ },
56
+ ],
57
+ isError: true,
58
+ }
59
+ }
60
+ })