@payloadcms/plugin-mcp 3.86.0-internal.ac46214 → 4.0.0-canary.1

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 (368) hide show
  1. package/README.md +2 -2
  2. package/bin.js +39 -0
  3. package/dist/collection/getAccessField.d.ts +12 -0
  4. package/dist/collection/getAccessField.d.ts.map +1 -0
  5. package/dist/collection/getAccessField.js +57 -0
  6. package/dist/collection/getAccessField.js.map +1 -0
  7. package/dist/collection/index.d.ts +6 -0
  8. package/dist/collection/index.d.ts.map +1 -0
  9. package/dist/collection/index.js +60 -0
  10. package/dist/collection/index.js.map +1 -0
  11. package/dist/components/AccessField/index.client.d.ts +10 -0
  12. package/dist/components/AccessField/index.client.d.ts.map +1 -0
  13. package/dist/components/AccessField/index.client.js +305 -0
  14. package/dist/components/AccessField/index.client.js.map +1 -0
  15. package/dist/components/AccessField/index.css +93 -0
  16. package/dist/defineTool.d.ts +26 -0
  17. package/dist/defineTool.d.ts.map +1 -0
  18. package/dist/defineTool.js +37 -0
  19. package/dist/defineTool.js.map +1 -0
  20. package/dist/endpoint/access.d.ts +10 -0
  21. package/dist/endpoint/access.d.ts.map +1 -0
  22. package/dist/endpoint/access.js +106 -0
  23. package/dist/endpoint/access.js.map +1 -0
  24. package/dist/endpoint/index.d.ts +3 -0
  25. package/dist/endpoint/index.d.ts.map +1 -0
  26. package/dist/endpoint/index.js +36 -0
  27. package/dist/endpoint/index.js.map +1 -0
  28. package/dist/exports/client.d.ts +2 -0
  29. package/dist/exports/client.d.ts.map +1 -0
  30. package/dist/exports/client.js +4 -0
  31. package/dist/exports/client.js.map +1 -0
  32. package/dist/index.d.ts +4 -7
  33. package/dist/index.d.ts.map +1 -1
  34. package/dist/index.js +44 -67
  35. package/dist/index.js.map +1 -1
  36. package/dist/mcp/buildMcpServer.d.ts +19 -0
  37. package/dist/mcp/buildMcpServer.d.ts.map +1 -0
  38. package/dist/mcp/buildMcpServer.js +199 -0
  39. package/dist/mcp/buildMcpServer.js.map +1 -0
  40. package/dist/mcp/builtin/collections/authTools.d.ts +7 -0
  41. package/dist/mcp/builtin/collections/authTools.d.ts.map +1 -0
  42. package/dist/mcp/builtin/collections/authTools.js +250 -0
  43. package/dist/mcp/builtin/collections/authTools.js.map +1 -0
  44. package/dist/mcp/builtin/collections/createTool.d.ts +2 -0
  45. package/dist/mcp/builtin/collections/createTool.d.ts.map +1 -0
  46. package/dist/mcp/builtin/collections/createTool.js +94 -0
  47. package/dist/mcp/builtin/collections/createTool.js.map +1 -0
  48. package/dist/mcp/builtin/collections/deleteTool.d.ts +2 -0
  49. package/dist/mcp/builtin/collections/deleteTool.d.ts.map +1 -0
  50. package/dist/mcp/builtin/collections/deleteTool.js +102 -0
  51. package/dist/mcp/builtin/collections/deleteTool.js.map +1 -0
  52. package/dist/mcp/builtin/collections/findTool.d.ts +2 -0
  53. package/dist/mcp/builtin/collections/findTool.d.ts.map +1 -0
  54. package/dist/mcp/builtin/collections/findTool.js +144 -0
  55. package/dist/mcp/builtin/collections/findTool.js.map +1 -0
  56. package/dist/mcp/builtin/collections/formatCollectionError.d.ts +9 -0
  57. package/dist/mcp/builtin/collections/formatCollectionError.d.ts.map +1 -0
  58. package/dist/mcp/builtin/collections/formatCollectionError.js +60 -0
  59. package/dist/mcp/builtin/collections/formatCollectionError.js.map +1 -0
  60. package/dist/mcp/builtin/collections/getCollectionSchemaTool.d.ts +2 -0
  61. package/dist/mcp/builtin/collections/getCollectionSchemaTool.d.ts.map +1 -0
  62. package/dist/mcp/builtin/collections/getCollectionSchemaTool.js +35 -0
  63. package/dist/mcp/builtin/collections/getCollectionSchemaTool.js.map +1 -0
  64. package/dist/mcp/builtin/collections/updateTool.d.ts +2 -0
  65. package/dist/mcp/builtin/collections/updateTool.d.ts.map +1 -0
  66. package/dist/mcp/builtin/collections/updateTool.js +199 -0
  67. package/dist/mcp/builtin/collections/updateTool.js.map +1 -0
  68. package/dist/mcp/builtin/getConfigInfoTool.d.ts +2 -0
  69. package/dist/mcp/builtin/getConfigInfoTool.d.ts.map +1 -0
  70. package/dist/mcp/builtin/getConfigInfoTool.js +49 -0
  71. package/dist/mcp/builtin/getConfigInfoTool.js.map +1 -0
  72. package/dist/mcp/builtin/globals/findTool.d.ts +2 -0
  73. package/dist/mcp/builtin/globals/findTool.d.ts.map +1 -0
  74. package/dist/mcp/builtin/globals/findTool.js +76 -0
  75. package/dist/mcp/builtin/globals/findTool.js.map +1 -0
  76. package/dist/mcp/builtin/globals/getGlobalSchemaTool.d.ts +2 -0
  77. package/dist/mcp/builtin/globals/getGlobalSchemaTool.d.ts.map +1 -0
  78. package/dist/mcp/builtin/globals/getGlobalSchemaTool.js +35 -0
  79. package/dist/mcp/builtin/globals/getGlobalSchemaTool.js.map +1 -0
  80. package/dist/mcp/builtin/globals/updateTool.d.ts +2 -0
  81. package/dist/mcp/builtin/globals/updateTool.d.ts.map +1 -0
  82. package/dist/mcp/builtin/globals/updateTool.js +94 -0
  83. package/dist/mcp/builtin/globals/updateTool.js.map +1 -0
  84. package/dist/mcp/builtin/validateEntityData.d.ts +14 -0
  85. package/dist/mcp/builtin/validateEntityData.d.ts.map +1 -0
  86. package/dist/mcp/builtin/validateEntityData.js +82 -0
  87. package/dist/mcp/builtin/validateEntityData.js.map +1 -0
  88. package/dist/mcp/builtinTools.d.ts +105 -0
  89. package/dist/mcp/builtinTools.d.ts.map +1 -0
  90. package/dist/mcp/builtinTools.js +107 -0
  91. package/dist/mcp/builtinTools.js.map +1 -0
  92. package/dist/mcp/sanitizeMCPConfig.d.ts +17 -0
  93. package/dist/mcp/sanitizeMCPConfig.d.ts.map +1 -0
  94. package/dist/mcp/sanitizeMCPConfig.js +188 -0
  95. package/dist/mcp/sanitizeMCPConfig.js.map +1 -0
  96. package/dist/stdio.d.ts +8 -0
  97. package/dist/stdio.d.ts.map +1 -0
  98. package/dist/stdio.js +89 -0
  99. package/dist/stdio.js.map +1 -0
  100. package/dist/types.d.ts +251 -455
  101. package/dist/types.d.ts.map +1 -1
  102. package/dist/types.js +6 -1
  103. package/dist/types.js.map +1 -1
  104. package/dist/utils/camelCase.d.ts.map +1 -1
  105. package/dist/utils/getLogger.d.ts +10 -0
  106. package/dist/utils/getLogger.d.ts.map +1 -0
  107. package/dist/utils/getLogger.js +22 -0
  108. package/dist/utils/getLogger.js.map +1 -0
  109. package/dist/utils/getPluginConfig.d.ts +12 -0
  110. package/dist/utils/getPluginConfig.d.ts.map +1 -0
  111. package/dist/utils/getPluginConfig.js +15 -0
  112. package/dist/utils/getPluginConfig.js.map +1 -0
  113. package/dist/utils/localAPIDefaults.d.ts +20 -0
  114. package/dist/utils/localAPIDefaults.d.ts.map +1 -0
  115. package/dist/utils/localAPIDefaults.js +19 -0
  116. package/dist/utils/localAPIDefaults.js.map +1 -0
  117. package/dist/utils/resolveProjectRoot.d.ts +7 -0
  118. package/dist/utils/resolveProjectRoot.d.ts.map +1 -0
  119. package/dist/utils/resolveProjectRoot.js +15 -0
  120. package/dist/utils/resolveProjectRoot.js.map +1 -0
  121. package/dist/utils/schemaConversion/getEntityInputSchema.d.ts +11 -0
  122. package/dist/utils/schemaConversion/getEntityInputSchema.d.ts.map +1 -0
  123. package/dist/utils/schemaConversion/getEntityInputSchema.js +34 -0
  124. package/dist/utils/schemaConversion/getEntityInputSchema.js.map +1 -0
  125. package/dist/utils/schemaConversion/removeVirtualFieldsFromSchema.d.ts +2 -2
  126. package/dist/utils/schemaConversion/removeVirtualFieldsFromSchema.d.ts.map +1 -1
  127. package/dist/utils/schemaConversion/removeVirtualFieldsFromSchema.js.map +1 -1
  128. package/dist/utils/schemaConversion/sanitizeEntitySchema.d.ts +15 -0
  129. package/dist/utils/schemaConversion/sanitizeEntitySchema.d.ts.map +1 -0
  130. package/dist/utils/schemaConversion/sanitizeEntitySchema.js +464 -0
  131. package/dist/utils/schemaConversion/sanitizeEntitySchema.js.map +1 -0
  132. package/dist/utils/schemaConversion/sanitizeEntitySchema.spec.js +158 -0
  133. package/dist/utils/schemaConversion/sanitizeEntitySchema.spec.js.map +1 -0
  134. package/dist/utils/toStandardSchema.d.ts +5 -0
  135. package/dist/utils/toStandardSchema.d.ts.map +1 -0
  136. package/dist/utils/toStandardSchema.js +4 -0
  137. package/dist/utils/toStandardSchema.js.map +1 -0
  138. package/dist/utils/whereSchema.d.ts +9 -0
  139. package/dist/utils/whereSchema.d.ts.map +1 -0
  140. package/dist/utils/whereSchema.js +13 -0
  141. package/dist/utils/whereSchema.js.map +1 -0
  142. package/package.json +35 -10
  143. package/src/collection/getAccessField.ts +64 -0
  144. package/src/collection/index.ts +64 -0
  145. package/src/components/AccessField/index.client.tsx +347 -0
  146. package/src/components/AccessField/index.css +93 -0
  147. package/src/defineTool.ts +44 -0
  148. package/src/endpoint/access.ts +132 -0
  149. package/src/endpoint/index.ts +35 -0
  150. package/src/exports/client.ts +2 -0
  151. package/src/index.ts +35 -85
  152. package/src/mcp/buildMcpServer.ts +257 -0
  153. package/src/mcp/builtin/collections/authTools.ts +233 -0
  154. package/src/mcp/builtin/collections/createTool.ts +112 -0
  155. package/src/mcp/builtin/collections/deleteTool.ts +116 -0
  156. package/src/mcp/builtin/collections/findTool.ts +177 -0
  157. package/src/mcp/builtin/collections/formatCollectionError.ts +84 -0
  158. package/src/mcp/builtin/collections/getCollectionSchemaTool.ts +28 -0
  159. package/src/mcp/builtin/collections/updateTool.ts +211 -0
  160. package/src/mcp/builtin/getConfigInfoTool.ts +44 -0
  161. package/src/mcp/builtin/globals/findTool.ts +96 -0
  162. package/src/mcp/builtin/globals/getGlobalSchemaTool.ts +28 -0
  163. package/src/mcp/builtin/globals/updateTool.ts +115 -0
  164. package/src/mcp/builtin/validateEntityData.ts +132 -0
  165. package/src/mcp/builtinTools.ts +98 -0
  166. package/src/mcp/sanitizeMCPConfig.ts +260 -0
  167. package/src/stdio.ts +98 -0
  168. package/src/types.ts +290 -490
  169. package/src/utils/getLogger.ts +22 -0
  170. package/src/utils/getPluginConfig.ts +24 -0
  171. package/src/utils/localAPIDefaults.ts +22 -0
  172. package/src/utils/resolveProjectRoot.ts +17 -0
  173. package/src/utils/schemaConversion/getEntityInputSchema.ts +78 -0
  174. package/src/utils/schemaConversion/removeVirtualFieldsFromSchema.ts +3 -3
  175. package/src/utils/schemaConversion/sanitizeEntitySchema.spec.ts +103 -0
  176. package/src/utils/schemaConversion/sanitizeEntitySchema.ts +529 -0
  177. package/src/utils/toStandardSchema.ts +9 -0
  178. package/src/utils/whereSchema.ts +24 -0
  179. package/dist/collections/createApiKeysCollection.d.ts +0 -7
  180. package/dist/collections/createApiKeysCollection.d.ts.map +0 -1
  181. package/dist/collections/createApiKeysCollection.js +0 -317
  182. package/dist/collections/createApiKeysCollection.js.map +0 -1
  183. package/dist/defaults.d.ts +0 -4
  184. package/dist/defaults.d.ts.map +0 -1
  185. package/dist/defaults.js +0 -5
  186. package/dist/defaults.js.map +0 -1
  187. package/dist/endpoints/mcp.d.ts +0 -4
  188. package/dist/endpoints/mcp.d.ts.map +0 -1
  189. package/dist/endpoints/mcp.js +0 -71
  190. package/dist/endpoints/mcp.js.map +0 -1
  191. package/dist/mcp/createRequest.d.ts +0 -3
  192. package/dist/mcp/createRequest.d.ts.map +0 -1
  193. package/dist/mcp/createRequest.js +0 -14
  194. package/dist/mcp/createRequest.js.map +0 -1
  195. package/dist/mcp/getMcpHandler.d.ts +0 -4
  196. package/dist/mcp/getMcpHandler.d.ts.map +0 -1
  197. package/dist/mcp/getMcpHandler.js +0 -231
  198. package/dist/mcp/getMcpHandler.js.map +0 -1
  199. package/dist/mcp/helpers/config.d.ts +0 -22
  200. package/dist/mcp/helpers/config.d.ts.map +0 -1
  201. package/dist/mcp/helpers/config.js +0 -153
  202. package/dist/mcp/helpers/config.js.map +0 -1
  203. package/dist/mcp/helpers/fields.d.ts +0 -19
  204. package/dist/mcp/helpers/fields.d.ts.map +0 -1
  205. package/dist/mcp/helpers/fields.js +0 -102
  206. package/dist/mcp/helpers/fields.js.map +0 -1
  207. package/dist/mcp/helpers/fileValidation.d.ts +0 -67
  208. package/dist/mcp/helpers/fileValidation.d.ts.map +0 -1
  209. package/dist/mcp/helpers/fileValidation.js +0 -267
  210. package/dist/mcp/helpers/fileValidation.js.map +0 -1
  211. package/dist/mcp/registerTool.d.ts +0 -6
  212. package/dist/mcp/registerTool.d.ts.map +0 -1
  213. package/dist/mcp/registerTool.js +0 -18
  214. package/dist/mcp/registerTool.js.map +0 -1
  215. package/dist/mcp/tools/auth/auth.d.ts +0 -4
  216. package/dist/mcp/tools/auth/auth.d.ts.map +0 -1
  217. package/dist/mcp/tools/auth/auth.js +0 -57
  218. package/dist/mcp/tools/auth/auth.js.map +0 -1
  219. package/dist/mcp/tools/auth/forgotPassword.d.ts +0 -4
  220. package/dist/mcp/tools/auth/forgotPassword.d.ts.map +0 -1
  221. package/dist/mcp/tools/auth/forgotPassword.js +0 -48
  222. package/dist/mcp/tools/auth/forgotPassword.js.map +0 -1
  223. package/dist/mcp/tools/auth/login.d.ts +0 -4
  224. package/dist/mcp/tools/auth/login.d.ts.map +0 -1
  225. package/dist/mcp/tools/auth/login.js +0 -51
  226. package/dist/mcp/tools/auth/login.js.map +0 -1
  227. package/dist/mcp/tools/auth/resetPassword.d.ts +0 -4
  228. package/dist/mcp/tools/auth/resetPassword.d.ts.map +0 -1
  229. package/dist/mcp/tools/auth/resetPassword.js +0 -49
  230. package/dist/mcp/tools/auth/resetPassword.js.map +0 -1
  231. package/dist/mcp/tools/auth/unlock.d.ts +0 -4
  232. package/dist/mcp/tools/auth/unlock.d.ts.map +0 -1
  233. package/dist/mcp/tools/auth/unlock.js +0 -48
  234. package/dist/mcp/tools/auth/unlock.js.map +0 -1
  235. package/dist/mcp/tools/auth/verify.d.ts +0 -4
  236. package/dist/mcp/tools/auth/verify.d.ts.map +0 -1
  237. package/dist/mcp/tools/auth/verify.js +0 -45
  238. package/dist/mcp/tools/auth/verify.js.map +0 -1
  239. package/dist/mcp/tools/collection/create.d.ts +0 -10
  240. package/dist/mcp/tools/collection/create.d.ts.map +0 -1
  241. package/dist/mcp/tools/collection/create.js +0 -139
  242. package/dist/mcp/tools/collection/create.js.map +0 -1
  243. package/dist/mcp/tools/collection/delete.d.ts +0 -10
  244. package/dist/mcp/tools/collection/delete.d.ts.map +0 -1
  245. package/dist/mcp/tools/collection/delete.js +0 -154
  246. package/dist/mcp/tools/collection/delete.js.map +0 -1
  247. package/dist/mcp/tools/collection/find.d.ts +0 -10
  248. package/dist/mcp/tools/collection/find.d.ts.map +0 -1
  249. package/dist/mcp/tools/collection/find.js +0 -165
  250. package/dist/mcp/tools/collection/find.js.map +0 -1
  251. package/dist/mcp/tools/collection/update.d.ts +0 -10
  252. package/dist/mcp/tools/collection/update.d.ts.map +0 -1
  253. package/dist/mcp/tools/collection/update.js +0 -209
  254. package/dist/mcp/tools/collection/update.js.map +0 -1
  255. package/dist/mcp/tools/config/find.d.ts +0 -10
  256. package/dist/mcp/tools/config/find.d.ts.map +0 -1
  257. package/dist/mcp/tools/config/find.js +0 -97
  258. package/dist/mcp/tools/config/find.js.map +0 -1
  259. package/dist/mcp/tools/config/update.d.ts +0 -10
  260. package/dist/mcp/tools/config/update.d.ts.map +0 -1
  261. package/dist/mcp/tools/config/update.js +0 -215
  262. package/dist/mcp/tools/config/update.js.map +0 -1
  263. package/dist/mcp/tools/global/find.d.ts +0 -5
  264. package/dist/mcp/tools/global/find.d.ts.map +0 -1
  265. package/dist/mcp/tools/global/find.js +0 -82
  266. package/dist/mcp/tools/global/find.js.map +0 -1
  267. package/dist/mcp/tools/global/update.d.ts +0 -6
  268. package/dist/mcp/tools/global/update.d.ts.map +0 -1
  269. package/dist/mcp/tools/global/update.js +0 -124
  270. package/dist/mcp/tools/global/update.js.map +0 -1
  271. package/dist/mcp/tools/job/create.d.ts +0 -10
  272. package/dist/mcp/tools/job/create.d.ts.map +0 -1
  273. package/dist/mcp/tools/job/create.js +0 -293
  274. package/dist/mcp/tools/job/create.js.map +0 -1
  275. package/dist/mcp/tools/job/run.d.ts +0 -10
  276. package/dist/mcp/tools/job/run.d.ts.map +0 -1
  277. package/dist/mcp/tools/job/run.js +0 -129
  278. package/dist/mcp/tools/job/run.js.map +0 -1
  279. package/dist/mcp/tools/job/update.d.ts +0 -11
  280. package/dist/mcp/tools/job/update.d.ts.map +0 -1
  281. package/dist/mcp/tools/job/update.js +0 -186
  282. package/dist/mcp/tools/job/update.js.map +0 -1
  283. package/dist/mcp/tools/resource/create.d.ts +0 -6
  284. package/dist/mcp/tools/resource/create.d.ts.map +0 -1
  285. package/dist/mcp/tools/resource/create.js +0 -124
  286. package/dist/mcp/tools/resource/create.js.map +0 -1
  287. package/dist/mcp/tools/resource/delete.d.ts +0 -5
  288. package/dist/mcp/tools/resource/delete.d.ts.map +0 -1
  289. package/dist/mcp/tools/resource/delete.js +0 -151
  290. package/dist/mcp/tools/resource/delete.js.map +0 -1
  291. package/dist/mcp/tools/resource/find.d.ts +0 -5
  292. package/dist/mcp/tools/resource/find.d.ts.map +0 -1
  293. package/dist/mcp/tools/resource/find.js +0 -170
  294. package/dist/mcp/tools/resource/find.js.map +0 -1
  295. package/dist/mcp/tools/resource/update.d.ts +0 -6
  296. package/dist/mcp/tools/resource/update.d.ts.map +0 -1
  297. package/dist/mcp/tools/resource/update.js +0 -256
  298. package/dist/mcp/tools/resource/update.js.map +0 -1
  299. package/dist/mcp/tools/schemas.d.ts +0 -457
  300. package/dist/mcp/tools/schemas.d.ts.map +0 -1
  301. package/dist/mcp/tools/schemas.js +0 -243
  302. package/dist/mcp/tools/schemas.js.map +0 -1
  303. package/dist/utils/adminEntitySettings.d.ts +0 -17
  304. package/dist/utils/adminEntitySettings.d.ts.map +0 -1
  305. package/dist/utils/adminEntitySettings.js +0 -41
  306. package/dist/utils/adminEntitySettings.js.map +0 -1
  307. package/dist/utils/createApiKeyFields.d.ts +0 -15
  308. package/dist/utils/createApiKeyFields.d.ts.map +0 -1
  309. package/dist/utils/createApiKeyFields.js +0 -57
  310. package/dist/utils/createApiKeyFields.js.map +0 -1
  311. package/dist/utils/getEnabledSlugs.d.ts +0 -13
  312. package/dist/utils/getEnabledSlugs.d.ts.map +0 -1
  313. package/dist/utils/getEnabledSlugs.js +0 -32
  314. package/dist/utils/getEnabledSlugs.js.map +0 -1
  315. package/dist/utils/schemaConversion/convertCollectionSchemaToZod.d.ts +0 -3
  316. package/dist/utils/schemaConversion/convertCollectionSchemaToZod.d.ts.map +0 -1
  317. package/dist/utils/schemaConversion/convertCollectionSchemaToZod.js +0 -43
  318. package/dist/utils/schemaConversion/convertCollectionSchemaToZod.js.map +0 -1
  319. package/dist/utils/schemaConversion/sanitizeJsonSchema.d.ts +0 -13
  320. package/dist/utils/schemaConversion/sanitizeJsonSchema.d.ts.map +0 -1
  321. package/dist/utils/schemaConversion/sanitizeJsonSchema.js +0 -56
  322. package/dist/utils/schemaConversion/sanitizeJsonSchema.js.map +0 -1
  323. package/dist/utils/schemaConversion/simplifyRelationshipFields.d.ts +0 -20
  324. package/dist/utils/schemaConversion/simplifyRelationshipFields.d.ts.map +0 -1
  325. package/dist/utils/schemaConversion/simplifyRelationshipFields.js +0 -53
  326. package/dist/utils/schemaConversion/simplifyRelationshipFields.js.map +0 -1
  327. package/dist/utils/schemaConversion/transformPointFields.d.ts +0 -3
  328. package/dist/utils/schemaConversion/transformPointFields.d.ts.map +0 -1
  329. package/dist/utils/schemaConversion/transformPointFields.js +0 -51
  330. package/dist/utils/schemaConversion/transformPointFields.js.map +0 -1
  331. package/src/collections/createApiKeysCollection.ts +0 -373
  332. package/src/defaults.ts +0 -3
  333. package/src/endpoints/mcp.ts +0 -91
  334. package/src/mcp/createRequest.ts +0 -13
  335. package/src/mcp/getMcpHandler.ts +0 -545
  336. package/src/mcp/helpers/config.ts +0 -213
  337. package/src/mcp/helpers/fields.ts +0 -154
  338. package/src/mcp/helpers/fileValidation.ts +0 -362
  339. package/src/mcp/registerTool.ts +0 -22
  340. package/src/mcp/tools/auth/auth.ts +0 -71
  341. package/src/mcp/tools/auth/forgotPassword.ts +0 -70
  342. package/src/mcp/tools/auth/login.ts +0 -72
  343. package/src/mcp/tools/auth/resetPassword.ts +0 -61
  344. package/src/mcp/tools/auth/unlock.ts +0 -64
  345. package/src/mcp/tools/auth/verify.ts +0 -57
  346. package/src/mcp/tools/collection/create.ts +0 -210
  347. package/src/mcp/tools/collection/delete.ts +0 -211
  348. package/src/mcp/tools/collection/find.ts +0 -224
  349. package/src/mcp/tools/collection/update.ts +0 -290
  350. package/src/mcp/tools/config/find.ts +0 -128
  351. package/src/mcp/tools/config/update.ts +0 -280
  352. package/src/mcp/tools/global/find.ts +0 -128
  353. package/src/mcp/tools/global/update.ts +0 -207
  354. package/src/mcp/tools/job/create.ts +0 -416
  355. package/src/mcp/tools/job/run.ts +0 -167
  356. package/src/mcp/tools/job/update.ts +0 -274
  357. package/src/mcp/tools/resource/create.ts +0 -211
  358. package/src/mcp/tools/resource/delete.ts +0 -218
  359. package/src/mcp/tools/resource/find.ts +0 -246
  360. package/src/mcp/tools/resource/update.ts +0 -383
  361. package/src/mcp/tools/schemas.ts +0 -520
  362. package/src/utils/adminEntitySettings.ts +0 -40
  363. package/src/utils/createApiKeyFields.ts +0 -72
  364. package/src/utils/getEnabledSlugs.ts +0 -42
  365. package/src/utils/schemaConversion/convertCollectionSchemaToZod.ts +0 -52
  366. package/src/utils/schemaConversion/sanitizeJsonSchema.ts +0 -62
  367. package/src/utils/schemaConversion/simplifyRelationshipFields.ts +0 -65
  368. package/src/utils/schemaConversion/transformPointFields.ts +0 -55
@@ -0,0 +1,347 @@
1
+ 'use client'
2
+
3
+ import type { JSONFieldClientProps } from 'payload'
4
+
5
+ import { CheckboxInput, Collapsible, useField } from '@payloadcms/ui'
6
+ import React from 'react'
7
+
8
+ import type { ClientMCPPluginConfig, MCPAPIKeysDocAccessTree } from '../../types.js'
9
+
10
+ import './index.css'
11
+
12
+ const baseClass = 'mcp-access-field'
13
+
14
+ type ClientItem = ClientMCPPluginConfig['items'][number]
15
+ type ScopeKey = 'collections' | 'globals'
16
+ type FlatKey = 'prompts' | 'resources' | 'tools'
17
+
18
+ type Props = {
19
+ pluginConfig: ClientMCPPluginConfig
20
+ } & JSONFieldClientProps
21
+
22
+ /** Drop a key from an object and return a new object — or `undefined` if it'd be empty. */
23
+ const without = <T extends Record<string, unknown>>(
24
+ obj: T | undefined,
25
+ key: string,
26
+ ): T | undefined => {
27
+ if (!obj || !(key in obj)) {
28
+ return obj
29
+ }
30
+ const { [key]: _omitted, ...rest } = obj
31
+ return Object.keys(rest).length === 0 ? undefined : (rest as T)
32
+ }
33
+
34
+ const setKey = <T extends Record<string, unknown>>(
35
+ obj: T | undefined,
36
+ key: string,
37
+ value: unknown,
38
+ ): T => ({ ...(obj ?? {}), [key]: value }) as T
39
+
40
+ export const AccessField: React.FC<Props> = ({ path, pluginConfig }) => {
41
+ const { setValue, value } = useField<MCPAPIKeysDocAccessTree>({ path })
42
+ const access = value ?? {}
43
+
44
+ // Bucket items for rendering. (Bucketing is cheap and runs once per render;
45
+ // memoizing would mean managing inputs/refs for marginal benefit.)
46
+ const collectionsBySlug: Record<string, ClientItem[]> = {}
47
+ const globalsBySlug: Record<string, ClientItem[]> = {}
48
+ const tools: ClientItem[] = []
49
+ const prompts: ClientItem[] = []
50
+ const resources: ClientItem[] = []
51
+ for (const item of pluginConfig.items) {
52
+ switch (item.type) {
53
+ case 'collectionTool':
54
+ ;(collectionsBySlug[item.collectionSlug!] ??= []).push(item)
55
+ break
56
+ case 'globalTool':
57
+ ;(globalsBySlug[item.globalSlug!] ??= []).push(item)
58
+ break
59
+ case 'prompt':
60
+ prompts.push(item)
61
+ break
62
+ case 'resource':
63
+ resources.push(item)
64
+ break
65
+ case 'tool':
66
+ tools.push(item)
67
+ break
68
+ }
69
+ }
70
+
71
+ const isScopedAllowed = (scope: ScopeKey, slug: string, configKey: string): boolean =>
72
+ access[scope]?.[slug]?.[configKey] !== false
73
+
74
+ const isFlatAllowed = (scope: FlatKey, configKey: string): boolean =>
75
+ access[scope]?.[configKey] !== false
76
+
77
+ const toggleScoped = (scope: ScopeKey, slug: string, configKey: string, allow: boolean) => {
78
+ if (allow) {
79
+ const slugBucket = without(access[scope]?.[slug], configKey)
80
+ const scopeBucket = slugBucket
81
+ ? setKey(access[scope], slug, slugBucket)
82
+ : without(access[scope], slug)
83
+ setValue(scopeBucket ? setKey(access, scope, scopeBucket) : (without(access, scope) ?? {}))
84
+ } else {
85
+ setValue(
86
+ setKey(
87
+ access,
88
+ scope,
89
+ setKey(access[scope], slug, setKey(access[scope]?.[slug], configKey, false)),
90
+ ),
91
+ )
92
+ }
93
+ }
94
+
95
+ const toggleFlat = (scope: FlatKey, configKey: string, allow: boolean) => {
96
+ if (allow) {
97
+ const bucket = without(access[scope], configKey)
98
+ setValue(bucket ? setKey(access, scope, bucket) : (without(access, scope) ?? {}))
99
+ } else {
100
+ setValue(setKey(access, scope, setKey(access[scope], configKey, false)))
101
+ }
102
+ }
103
+
104
+ const setAllScoped = (scope: ScopeKey, slug: string, leaves: ClientItem[], allow: boolean) => {
105
+ if (allow) {
106
+ const scopeBucket = without(access[scope], slug)
107
+ setValue(scopeBucket ? setKey(access, scope, scopeBucket) : (without(access, scope) ?? {}))
108
+ } else {
109
+ const slugBucket = leaves.reduce<Record<string, boolean>>(
110
+ (acc, leaf) => ({ ...acc, [leaf.configKey]: false }),
111
+ {},
112
+ )
113
+ setValue(setKey(access, scope, setKey(access[scope], slug, slugBucket)))
114
+ }
115
+ }
116
+
117
+ const setAllFlat = (scope: FlatKey, leaves: ClientItem[], allow: boolean) => {
118
+ if (allow) {
119
+ setValue(without(access, scope) ?? {})
120
+ } else {
121
+ const bucket = leaves.reduce<Record<string, boolean>>(
122
+ (acc, leaf) => ({ ...acc, [leaf.configKey]: false }),
123
+ {},
124
+ )
125
+ setValue(setKey(access, scope, bucket))
126
+ }
127
+ }
128
+
129
+ const collectionSlugs = Object.keys(collectionsBySlug)
130
+ const globalSlugs = Object.keys(globalsBySlug)
131
+
132
+ return (
133
+ <div className={baseClass}>
134
+ {collectionSlugs.length > 0 && (
135
+ <section className={`${baseClass}__section`}>
136
+ <header className={`${baseClass}__section-header`}>
137
+ {/* TODO: needs i18n once design is finalized */}
138
+ <h4>Collection-level permissions</h4>
139
+ {/* TODO: needs i18n once design is finalized */}
140
+ <p>Allow MCP clients to perform the following actions within these collections:</p>
141
+ </header>
142
+ {collectionSlugs.map((slug) => {
143
+ const leaves = collectionsBySlug[slug]!
144
+ return (
145
+ <Collapsible
146
+ actions={
147
+ <GroupActions
148
+ onSetAll={(allow) => setAllScoped('collections', slug, leaves, allow)}
149
+ />
150
+ }
151
+ className={`${baseClass}__group`}
152
+ header={<span className={`${baseClass}__group-label`}>{titleCase(slug)}</span>}
153
+ initCollapsed
154
+ key={`collection-${slug}`}
155
+ >
156
+ <ul className={`${baseClass}__list`}>
157
+ {leaves.map((leaf) => (
158
+ <li key={leaf.configKey}>
159
+ <CheckboxInput
160
+ checked={isScopedAllowed('collections', slug, leaf.configKey)}
161
+ id={`${path}.collections.${slug}.${leaf.configKey}`}
162
+ label={leaf.label}
163
+ onToggle={(e) =>
164
+ toggleScoped('collections', slug, leaf.configKey, e.target.checked)
165
+ }
166
+ tooltip={leaf.description}
167
+ />
168
+ </li>
169
+ ))}
170
+ </ul>
171
+ </Collapsible>
172
+ )
173
+ })}
174
+ </section>
175
+ )}
176
+
177
+ {globalSlugs.length > 0 && (
178
+ <section className={`${baseClass}__section`}>
179
+ <header className={`${baseClass}__section-header`}>
180
+ {/* TODO: needs i18n once design is finalized */}
181
+ <h4>Global-level permissions</h4>
182
+ {/* TODO: needs i18n once design is finalized */}
183
+ <p>Allow MCP clients to perform the following actions on these globals:</p>
184
+ </header>
185
+ {globalSlugs.map((slug) => {
186
+ const leaves = globalsBySlug[slug]!
187
+ return (
188
+ <Collapsible
189
+ actions={
190
+ <GroupActions
191
+ onSetAll={(allow) => setAllScoped('globals', slug, leaves, allow)}
192
+ />
193
+ }
194
+ className={`${baseClass}__group`}
195
+ header={<span className={`${baseClass}__group-label`}>{titleCase(slug)}</span>}
196
+ initCollapsed
197
+ key={`global-${slug}`}
198
+ >
199
+ <ul className={`${baseClass}__list`}>
200
+ {leaves.map((leaf) => (
201
+ <li key={leaf.configKey}>
202
+ <CheckboxInput
203
+ checked={isScopedAllowed('globals', slug, leaf.configKey)}
204
+ id={`${path}.globals.${slug}.${leaf.configKey}`}
205
+ label={leaf.label}
206
+ onToggle={(e) =>
207
+ toggleScoped('globals', slug, leaf.configKey, e.target.checked)
208
+ }
209
+ tooltip={leaf.description}
210
+ />
211
+ </li>
212
+ ))}
213
+ </ul>
214
+ </Collapsible>
215
+ )
216
+ })}
217
+ </section>
218
+ )}
219
+
220
+ {(tools.length > 0 || prompts.length > 0 || resources.length > 0) && (
221
+ <section className={`${baseClass}__section`}>
222
+ <header className={`${baseClass}__section-header`}>
223
+ {/* TODO: needs i18n once design is finalized */}
224
+ <h4>Project-level permissions</h4>
225
+ {/* TODO: needs i18n once design is finalized */}
226
+ <p>Cross-cutting tools, prompts, and resources not scoped to a single collection.</p>
227
+ </header>
228
+ {tools.length > 0 && (
229
+ <Collapsible
230
+ actions={<GroupActions onSetAll={(allow) => setAllFlat('tools', tools, allow)} />}
231
+ className={`${baseClass}__group`}
232
+ header={
233
+ /* TODO: needs i18n once design is finalized */
234
+ <span className={`${baseClass}__group-label`}>Tools</span>
235
+ }
236
+ initCollapsed
237
+ >
238
+ <ul className={`${baseClass}__list`}>
239
+ {tools.map((leaf) => (
240
+ <li key={leaf.configKey}>
241
+ <CheckboxInput
242
+ checked={isFlatAllowed('tools', leaf.configKey)}
243
+ id={`${path}.tools.${leaf.configKey}`}
244
+ label={leaf.label}
245
+ onToggle={(e) => toggleFlat('tools', leaf.configKey, e.target.checked)}
246
+ tooltip={leaf.description}
247
+ />
248
+ </li>
249
+ ))}
250
+ </ul>
251
+ </Collapsible>
252
+ )}
253
+ {prompts.length > 0 && (
254
+ <Collapsible
255
+ actions={<GroupActions onSetAll={(allow) => setAllFlat('prompts', prompts, allow)} />}
256
+ className={`${baseClass}__group`}
257
+ header={
258
+ /* TODO: needs i18n once design is finalized */
259
+ <span className={`${baseClass}__group-label`}>Prompts</span>
260
+ }
261
+ initCollapsed
262
+ >
263
+ <ul className={`${baseClass}__list`}>
264
+ {prompts.map((leaf) => (
265
+ <li key={leaf.configKey}>
266
+ <CheckboxInput
267
+ checked={isFlatAllowed('prompts', leaf.configKey)}
268
+ id={`${path}.prompts.${leaf.configKey}`}
269
+ label={leaf.label}
270
+ onToggle={(e) => toggleFlat('prompts', leaf.configKey, e.target.checked)}
271
+ tooltip={leaf.description}
272
+ />
273
+ </li>
274
+ ))}
275
+ </ul>
276
+ </Collapsible>
277
+ )}
278
+ {resources.length > 0 && (
279
+ <Collapsible
280
+ actions={
281
+ <GroupActions onSetAll={(allow) => setAllFlat('resources', resources, allow)} />
282
+ }
283
+ className={`${baseClass}__group`}
284
+ header={
285
+ /* TODO: needs i18n once design is finalized */
286
+ <span className={`${baseClass}__group-label`}>Resources</span>
287
+ }
288
+ initCollapsed
289
+ >
290
+ <ul className={`${baseClass}__list`}>
291
+ {resources.map((leaf) => (
292
+ <li key={leaf.configKey}>
293
+ <CheckboxInput
294
+ checked={isFlatAllowed('resources', leaf.configKey)}
295
+ id={`${path}.resources.${leaf.configKey}`}
296
+ label={leaf.label}
297
+ onToggle={(e) => toggleFlat('resources', leaf.configKey, e.target.checked)}
298
+ tooltip={leaf.description}
299
+ />
300
+ </li>
301
+ ))}
302
+ </ul>
303
+ </Collapsible>
304
+ )}
305
+ </section>
306
+ )}
307
+ </div>
308
+ )
309
+ }
310
+
311
+ const GroupActions: React.FC<{ onSetAll: (allow: boolean) => void }> = ({ onSetAll }) => (
312
+ // TODO: button labels + aria-labels need i18n once design is finalized
313
+ <div className={`${baseClass}__group-actions`}>
314
+ <button
315
+ aria-label="Select all"
316
+ className={`${baseClass}__action`}
317
+ onClick={(e) => {
318
+ e.stopPropagation()
319
+ onSetAll(true)
320
+ }}
321
+ title="Select all"
322
+ type="button"
323
+ >
324
+ all
325
+ </button>
326
+ <span aria-hidden className={`${baseClass}__action-sep`}>
327
+ /
328
+ </span>
329
+ <button
330
+ aria-label="Clear all"
331
+ className={`${baseClass}__action`}
332
+ onClick={(e) => {
333
+ e.stopPropagation()
334
+ onSetAll(false)
335
+ }}
336
+ title="Clear all"
337
+ type="button"
338
+ >
339
+ none
340
+ </button>
341
+ </div>
342
+ )
343
+
344
+ const titleCase = (slug: string): string =>
345
+ slug.replace(/(^|[-_])(.)/g, (_, sep: string, ch: string) =>
346
+ sep ? ` ${ch.toUpperCase()}` : ch.toUpperCase(),
347
+ )
@@ -0,0 +1,93 @@
1
+ @layer payload-default {
2
+ .mcp-access-field {
3
+ display: flex;
4
+ flex-direction: column;
5
+ gap: var(--base);
6
+ }
7
+
8
+ .mcp-access-field__section {
9
+ display: flex;
10
+ flex-direction: column;
11
+ gap: calc(var(--base) / 2);
12
+ padding-bottom: var(--base);
13
+ /* Full-bleed separator: extend past the sidebar's horizontal gutter so the
14
+ border-block-end spans the entire sidebar width. */
15
+ margin-inline-start: calc(-1 * var(--sidebar-gutter-h-left, var(--gutter-h)));
16
+ margin-inline-end: calc(-1 * var(--sidebar-gutter-h-right, var(--gutter-h)));
17
+ padding-inline-start: var(--sidebar-gutter-h-left, var(--gutter-h));
18
+ padding-inline-end: var(--sidebar-gutter-h-right, var(--gutter-h));
19
+ border-block-end: 1px solid var(--theme-elevation-100);
20
+ }
21
+
22
+ .mcp-access-field__section:last-child {
23
+ border-block-end: none;
24
+ }
25
+
26
+ .mcp-access-field__section-header {
27
+ display: flex;
28
+ flex-direction: column;
29
+ }
30
+
31
+ .mcp-access-field__section-header h4 {
32
+ margin: 0;
33
+ color: var(--color-text);
34
+ font-family: var(--text-heading-small-font-family);
35
+ font-size: var(--text-heading-small-font-size);
36
+ font-weight: var(--text-heading-small-font-weight);
37
+ line-height: var(--text-heading-small-line-height);
38
+ letter-spacing: var(--text-heading-small-letter-spacing);
39
+ }
40
+
41
+ .mcp-access-field__section-header p {
42
+ margin: 0;
43
+ color: var(--color-text-secondary);
44
+ font-family: var(--text-body-medium-font-family);
45
+ font-size: var(--text-body-medium-font-size);
46
+ font-weight: var(--text-body-medium-font-weight);
47
+ line-height: var(--text-body-medium-line-height);
48
+ letter-spacing: var(--text-body-medium-letter-spacing);
49
+ }
50
+
51
+ .mcp-access-field__group {
52
+ margin-block-end: calc(var(--base) / 2);
53
+ }
54
+
55
+ .mcp-access-field__group-label {
56
+ font-weight: 600;
57
+ }
58
+
59
+ .mcp-access-field__group-actions {
60
+ display: flex;
61
+ align-items: center;
62
+ gap: calc(var(--base) / 6);
63
+ }
64
+
65
+ .mcp-access-field__action {
66
+ appearance: none;
67
+ background: none;
68
+ border: none;
69
+ color: var(--theme-elevation-500);
70
+ cursor: pointer;
71
+ font-size: 0.75rem;
72
+ padding: 0;
73
+ }
74
+
75
+ .mcp-access-field__action:hover {
76
+ color: var(--theme-text);
77
+ text-decoration: underline;
78
+ }
79
+
80
+ .mcp-access-field__action-sep {
81
+ color: var(--theme-elevation-300);
82
+ font-size: 0.75rem;
83
+ }
84
+
85
+ .mcp-access-field__list {
86
+ list-style: none;
87
+ margin: 0;
88
+ padding: 0;
89
+ display: flex;
90
+ flex-direction: column;
91
+ gap: calc(var(--base) / 3);
92
+ }
93
+ }
@@ -0,0 +1,44 @@
1
+ import type { CollectionTool, GlobalTool, Prompt, Tool, ToolInputSchema } from './types.js'
2
+
3
+ /**
4
+ * Two-stage builder: pass the schema/metadata first, then chain `.handler(fn)`. Splitting the
5
+ * call lets TypeScript resolve `TSchema` from `input` (call 1) before contextually typing the
6
+ * handler (call 2). A single-call API hit a TS limitation where property order in the literal
7
+ * decided whether `TSchema` was inferred or pinned to its default.
8
+ *
9
+ * defineCollectionTool({ description, input })
10
+ * .handler(({ input }) => …) // ← input is fully typed here regardless of order
11
+ *
12
+ * Config and handler signatures are derived from `Tool` / `CollectionTool` / `GlobalTool` /
13
+ * `Prompt` via `Omit` + indexed access so there's no duplication with `types.ts`.
14
+ */
15
+
16
+ export const defineTool = <
17
+ TSchema extends ToolInputSchema | undefined = ToolInputSchema | undefined,
18
+ >(
19
+ args: Omit<Tool<TSchema>, 'handler'>,
20
+ ): { handler: (fn: Tool<TSchema>['handler']) => Tool } => ({
21
+ handler: (fn) => ({ ...args, handler: fn }) as unknown as Tool,
22
+ })
23
+
24
+ export const defineCollectionTool = <
25
+ TSchema extends ToolInputSchema | undefined = ToolInputSchema | undefined,
26
+ >(
27
+ args: Omit<CollectionTool<TSchema>, 'handler'>,
28
+ ): { handler: (fn: CollectionTool<TSchema>['handler']) => CollectionTool } => ({
29
+ handler: (fn) => ({ ...args, handler: fn }) as unknown as CollectionTool,
30
+ })
31
+
32
+ export const defineGlobalTool = <
33
+ TSchema extends ToolInputSchema | undefined = ToolInputSchema | undefined,
34
+ >(
35
+ args: Omit<GlobalTool<TSchema>, 'handler'>,
36
+ ): { handler: (fn: GlobalTool<TSchema>['handler']) => GlobalTool } => ({
37
+ handler: (fn) => ({ ...args, handler: fn }) as unknown as GlobalTool,
38
+ })
39
+
40
+ export const definePrompt = <TSchema extends ToolInputSchema = ToolInputSchema>(
41
+ args: Omit<Prompt<TSchema>, 'handler'>,
42
+ ): { handler: (fn: Prompt<TSchema>['handler']) => Prompt } => ({
43
+ handler: (fn) => ({ ...args, handler: fn }) as unknown as Prompt,
44
+ })
@@ -0,0 +1,132 @@
1
+ import type { DefaultDocumentIDType, PayloadRequest, TypedUser } from 'payload'
2
+
3
+ import crypto from 'crypto'
4
+ import { UnauthorizedError } from 'payload'
5
+
6
+ import type { AuthorizedMCP, MCPAPIKeysDoc } from '../types.js'
7
+
8
+ import { getLogger } from '../utils/getLogger.js'
9
+ import { getPluginConfig } from '../utils/getPluginConfig.js'
10
+
11
+ /**
12
+ * Resolves the API key (or dev-mode session) and returns the items the caller
13
+ * may use. Denied items are dropped from the array.
14
+ */
15
+ export const getAuthorizedMCP: (args: { req: PayloadRequest }) => Promise<AuthorizedMCP> = async ({
16
+ req,
17
+ }) => {
18
+ const logger = getLogger({ payload: req.payload })
19
+ const pluginConfig = getPluginConfig({ config: req.payload.config })
20
+
21
+ const authHeader = req.headers.get('Authorization')
22
+ const hasBearerToken = authHeader?.startsWith('Bearer ')
23
+
24
+ const buildAuthorized = (apiKeyDoc: MCPAPIKeysDoc): AuthorizedMCP => ({
25
+ items: pluginConfig.items.filter((item) => {
26
+ switch (item.type) {
27
+ case 'collectionTool':
28
+ return apiKeyDoc.access.collections?.[item.collectionSlug]?.[item.configKey] !== false
29
+ case 'globalTool':
30
+ return apiKeyDoc.access.globals?.[item.globalSlug]?.[item.configKey] !== false
31
+ case 'prompt':
32
+ return apiKeyDoc.access.prompts?.[item.configKey] !== false
33
+ case 'resource':
34
+ return apiKeyDoc.access.resources?.[item.configKey] !== false
35
+ case 'tool':
36
+ return apiKeyDoc.access.tools?.[item.configKey] !== false
37
+ }
38
+ }),
39
+ overrideAccess:
40
+ typeof apiKeyDoc.overrideAccess === 'boolean' ? apiKeyDoc.overrideAccess : false,
41
+ user: apiKeyDoc.user,
42
+ })
43
+
44
+ if (pluginConfig.overrideAuth) {
45
+ return await pluginConfig.overrideAuth({
46
+ getAPIKeyDoc: (overrideApiKey) => getAPIKeyDoc({ logger, overrideApiKey, pluginConfig, req }),
47
+ getAuthorizedMCP: ({ apiKeyDoc }) => buildAuthorized(apiKeyDoc),
48
+ pluginConfig,
49
+ req,
50
+ })
51
+ }
52
+
53
+ if (process.env.NODE_ENV === 'development' && !hasBearerToken) {
54
+ logger.info('Dev mode: skipping API key check, using session user')
55
+ return buildAuthorized({
56
+ id: -1,
57
+ access: {},
58
+ overrideAccess: true,
59
+ user: req.user ?? null,
60
+ })
61
+ }
62
+
63
+ return buildAuthorized(await getAPIKeyDoc({ logger, pluginConfig, req }))
64
+ }
65
+
66
+ const getAPIKeyDoc = async ({
67
+ logger,
68
+ overrideApiKey,
69
+ pluginConfig,
70
+ req,
71
+ }: {
72
+ logger: ReturnType<typeof getLogger>
73
+ overrideApiKey?: string
74
+ pluginConfig: ReturnType<typeof getPluginConfig>
75
+ req: PayloadRequest
76
+ }): Promise<MCPAPIKeysDoc> => {
77
+ const authHeader = req.headers.get('Authorization')
78
+ const hasBearerToken = authHeader?.startsWith('Bearer ')
79
+
80
+ const apiKey =
81
+ overrideApiKey ?? (hasBearerToken ? authHeader?.replace('Bearer ', '').trim() || null : null)
82
+
83
+ if (!apiKey) {
84
+ throw new UnauthorizedError()
85
+ }
86
+
87
+ const sha256APIKeyIndex = crypto
88
+ .createHmac('sha256', req.payload.secret)
89
+ .update(apiKey)
90
+ .digest('hex')
91
+
92
+ const doc = await req.payload.db.findOne<MCPAPIKeysDoc>({
93
+ collection: 'payload-mcp-api-keys',
94
+ req,
95
+ where: {
96
+ apiKeyIndex: { equals: sha256APIKeyIndex },
97
+ },
98
+ })
99
+
100
+ if (!doc || !doc.user) {
101
+ throw new UnauthorizedError()
102
+ }
103
+
104
+ logger.info('API Key is valid')
105
+
106
+ const userRef = doc.user
107
+ const userID =
108
+ typeof userRef === 'object' && userRef !== null && 'id' in userRef
109
+ ? userRef.id
110
+ : (userRef as unknown as DefaultDocumentIDType)
111
+
112
+ const user = (await req.payload.findByID({
113
+ id: userID,
114
+ collection: pluginConfig.userCollection,
115
+ depth: 0,
116
+ disableErrors: true,
117
+ req,
118
+ })) as null | TypedUser
119
+
120
+ if (!user) {
121
+ throw new UnauthorizedError()
122
+ }
123
+
124
+ return {
125
+ ...doc,
126
+ user: {
127
+ ...user,
128
+ _strategy: 'mcp-api-key' as const,
129
+ collection: pluginConfig.userCollection,
130
+ },
131
+ }
132
+ }
@@ -0,0 +1,35 @@
1
+ import { WebStandardStreamableHTTPServerTransport } from '@modelcontextprotocol/server'
2
+ import { APIError, type PayloadHandler } from 'payload'
3
+
4
+ import { buildMcpServer } from '../mcp/buildMcpServer.js'
5
+ import { getPluginConfig } from '../utils/getPluginConfig.js'
6
+ import { getAuthorizedMCP } from './access.js'
7
+
8
+ export const mcpEndpoint: PayloadHandler = async (req) => {
9
+ if (!req.url) {
10
+ throw new APIError('Missing request URL', 400)
11
+ }
12
+
13
+ req.payloadAPI = 'MCP' as const
14
+
15
+ const pluginConfig = getPluginConfig({ config: req.payload.config })
16
+ const authorizedMCP = await getAuthorizedMCP({ req })
17
+
18
+ const server = buildMcpServer({ authorizedMCP, pluginConfig, req })
19
+
20
+ const transport = new WebStandardStreamableHTTPServerTransport({
21
+ enableJsonResponse: true,
22
+ sessionIdGenerator: undefined, // stateless mode
23
+ })
24
+
25
+ await server.connect(transport)
26
+
27
+ const mcpRequest = new Request(req.url, {
28
+ body: req.body,
29
+ duplex: 'half',
30
+ headers: req.headers,
31
+ method: req.method,
32
+ } as { duplex: 'half' } & RequestInit)
33
+
34
+ return await transport.handleRequest(mcpRequest)
35
+ }
@@ -0,0 +1,2 @@
1
+ 'use client'
2
+ export { AccessField } from '../components/AccessField/index.client.js'