@payloadcms/plugin-mcp 4.0.0-internal.293e026 → 4.0.0-internal.2a3c3bc

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 (242) hide show
  1. package/LICENSE.md +1 -1
  2. package/dist/defaultAccess.d.ts +3 -0
  3. package/dist/defaultAccess.d.ts.map +1 -0
  4. package/dist/defaultAccess.js +3 -0
  5. package/dist/defaultAccess.js.map +1 -0
  6. package/dist/defineTool.d.ts +8 -8
  7. package/dist/defineTool.d.ts.map +1 -1
  8. package/dist/endpoint/access.d.ts +12 -5
  9. package/dist/endpoint/access.d.ts.map +1 -1
  10. package/dist/endpoint/access.js +76 -88
  11. package/dist/endpoint/access.js.map +1 -1
  12. package/dist/endpoint/index.d.ts +1 -1
  13. package/dist/endpoint/index.d.ts.map +1 -1
  14. package/dist/endpoint/index.js +102 -16
  15. package/dist/endpoint/index.js.map +1 -1
  16. package/dist/endpoint/oauth.d.ts +27 -0
  17. package/dist/endpoint/oauth.d.ts.map +1 -0
  18. package/dist/endpoint/oauth.js +61 -0
  19. package/dist/endpoint/oauth.js.map +1 -0
  20. package/dist/exports/client.d.ts +1 -1
  21. package/dist/exports/client.d.ts.map +1 -1
  22. package/dist/exports/client.js +1 -1
  23. package/dist/exports/client.js.map +1 -1
  24. package/dist/exports/internal.d.ts +2 -0
  25. package/dist/exports/internal.d.ts.map +1 -0
  26. package/dist/exports/internal.js +3 -0
  27. package/dist/exports/internal.js.map +1 -0
  28. package/dist/index.d.ts +3 -2
  29. package/dist/index.d.ts.map +1 -1
  30. package/dist/index.js +22 -20
  31. package/dist/index.js.map +1 -1
  32. package/dist/mcp/buildMcpServer.d.ts +6 -6
  33. package/dist/mcp/buildMcpServer.d.ts.map +1 -1
  34. package/dist/mcp/buildMcpServer.js +146 -81
  35. package/dist/mcp/buildMcpServer.js.map +1 -1
  36. package/dist/mcp/builtin/collections/authTools.d.ts.map +1 -1
  37. package/dist/mcp/builtin/collections/authTools.js +123 -61
  38. package/dist/mcp/builtin/collections/authTools.js.map +1 -1
  39. package/dist/mcp/builtin/collections/countTool.d.ts +2 -0
  40. package/dist/mcp/builtin/collections/countTool.d.ts.map +1 -0
  41. package/dist/mcp/builtin/collections/countTool.js +63 -0
  42. package/dist/mcp/builtin/collections/countTool.js.map +1 -0
  43. package/dist/mcp/builtin/collections/countVersionsTool.d.ts +2 -0
  44. package/dist/mcp/builtin/collections/countVersionsTool.d.ts.map +1 -0
  45. package/dist/mcp/builtin/collections/countVersionsTool.js +60 -0
  46. package/dist/mcp/builtin/collections/countVersionsTool.js.map +1 -0
  47. package/dist/mcp/builtin/collections/createTool.d.ts +1 -1
  48. package/dist/mcp/builtin/collections/createTool.d.ts.map +1 -1
  49. package/dist/mcp/builtin/collections/createTool.js +114 -68
  50. package/dist/mcp/builtin/collections/createTool.js.map +1 -1
  51. package/dist/mcp/builtin/collections/deleteTool.d.ts +1 -1
  52. package/dist/mcp/builtin/collections/deleteTool.d.ts.map +1 -1
  53. package/dist/mcp/builtin/collections/deleteTool.js +55 -61
  54. package/dist/mcp/builtin/collections/deleteTool.js.map +1 -1
  55. package/dist/mcp/builtin/collections/duplicateTool.d.ts +2 -0
  56. package/dist/mcp/builtin/collections/duplicateTool.d.ts.map +1 -0
  57. package/dist/mcp/builtin/collections/duplicateTool.js +90 -0
  58. package/dist/mcp/builtin/collections/duplicateTool.js.map +1 -0
  59. package/dist/mcp/builtin/collections/fileInput.d.ts +28 -0
  60. package/dist/mcp/builtin/collections/fileInput.d.ts.map +1 -0
  61. package/dist/mcp/builtin/collections/fileInput.js +88 -0
  62. package/dist/mcp/builtin/collections/fileInput.js.map +1 -0
  63. package/dist/mcp/builtin/collections/findDistinctTool.d.ts +2 -0
  64. package/dist/mcp/builtin/collections/findDistinctTool.d.ts.map +1 -0
  65. package/dist/mcp/builtin/collections/findDistinctTool.js +77 -0
  66. package/dist/mcp/builtin/collections/findDistinctTool.js.map +1 -0
  67. package/dist/mcp/builtin/collections/findTool.d.ts +1 -1
  68. package/dist/mcp/builtin/collections/findTool.d.ts.map +1 -1
  69. package/dist/mcp/builtin/collections/findTool.js +61 -74
  70. package/dist/mcp/builtin/collections/findTool.js.map +1 -1
  71. package/dist/mcp/builtin/collections/findVersionByIDTool.d.ts +2 -0
  72. package/dist/mcp/builtin/collections/findVersionByIDTool.d.ts.map +1 -0
  73. package/dist/mcp/builtin/collections/findVersionByIDTool.js +74 -0
  74. package/dist/mcp/builtin/collections/findVersionByIDTool.js.map +1 -0
  75. package/dist/mcp/builtin/collections/findVersionsTool.d.ts +2 -0
  76. package/dist/mcp/builtin/collections/findVersionsTool.d.ts.map +1 -0
  77. package/dist/mcp/builtin/collections/findVersionsTool.js +84 -0
  78. package/dist/mcp/builtin/collections/findVersionsTool.js.map +1 -0
  79. package/dist/mcp/builtin/collections/getCollectionSchemaTool.d.ts +2 -0
  80. package/dist/mcp/builtin/collections/getCollectionSchemaTool.d.ts.map +1 -0
  81. package/dist/mcp/builtin/collections/getCollectionSchemaTool.js +103 -0
  82. package/dist/mcp/builtin/collections/getCollectionSchemaTool.js.map +1 -0
  83. package/dist/mcp/builtin/collections/restoreVersionTool.d.ts +2 -0
  84. package/dist/mcp/builtin/collections/restoreVersionTool.d.ts.map +1 -0
  85. package/dist/mcp/builtin/collections/restoreVersionTool.js +69 -0
  86. package/dist/mcp/builtin/collections/restoreVersionTool.js.map +1 -0
  87. package/dist/mcp/builtin/collections/updateTool.d.ts +1 -1
  88. package/dist/mcp/builtin/collections/updateTool.d.ts.map +1 -1
  89. package/dist/mcp/builtin/collections/updateTool.js +118 -137
  90. package/dist/mcp/builtin/collections/updateTool.js.map +1 -1
  91. package/dist/mcp/builtin/collections/uploadInstructionsTool.d.ts +2 -0
  92. package/dist/mcp/builtin/collections/uploadInstructionsTool.d.ts.map +1 -0
  93. package/dist/mcp/builtin/collections/uploadInstructionsTool.js +55 -0
  94. package/dist/mcp/builtin/collections/uploadInstructionsTool.js.map +1 -0
  95. package/dist/mcp/builtin/formatEntityError.d.ts +16 -0
  96. package/dist/mcp/builtin/formatEntityError.d.ts.map +1 -0
  97. package/dist/mcp/builtin/formatEntityError.js +55 -0
  98. package/dist/mcp/builtin/formatEntityError.js.map +1 -0
  99. package/dist/mcp/builtin/getConfigInfoTool.d.ts +2 -0
  100. package/dist/mcp/builtin/getConfigInfoTool.d.ts.map +1 -0
  101. package/dist/mcp/builtin/getConfigInfoTool.js +69 -0
  102. package/dist/mcp/builtin/getConfigInfoTool.js.map +1 -0
  103. package/dist/mcp/builtin/globals/countVersionsTool.d.ts +2 -0
  104. package/dist/mcp/builtin/globals/countVersionsTool.d.ts.map +1 -0
  105. package/dist/mcp/builtin/globals/countVersionsTool.js +60 -0
  106. package/dist/mcp/builtin/globals/countVersionsTool.js.map +1 -0
  107. package/dist/mcp/builtin/globals/findTool.d.ts.map +1 -1
  108. package/dist/mcp/builtin/globals/findTool.js +27 -36
  109. package/dist/mcp/builtin/globals/findTool.js.map +1 -1
  110. package/dist/mcp/builtin/globals/findVersionByIDTool.d.ts +2 -0
  111. package/dist/mcp/builtin/globals/findVersionByIDTool.d.ts.map +1 -0
  112. package/dist/mcp/builtin/globals/findVersionByIDTool.js +68 -0
  113. package/dist/mcp/builtin/globals/findVersionByIDTool.js.map +1 -0
  114. package/dist/mcp/builtin/globals/findVersionsTool.d.ts +2 -0
  115. package/dist/mcp/builtin/globals/findVersionsTool.d.ts.map +1 -0
  116. package/dist/mcp/builtin/globals/findVersionsTool.js +78 -0
  117. package/dist/mcp/builtin/globals/findVersionsTool.js.map +1 -0
  118. package/dist/mcp/builtin/globals/getGlobalSchemaTool.d.ts +2 -0
  119. package/dist/mcp/builtin/globals/getGlobalSchemaTool.d.ts.map +1 -0
  120. package/dist/mcp/builtin/globals/getGlobalSchemaTool.js +81 -0
  121. package/dist/mcp/builtin/globals/getGlobalSchemaTool.js.map +1 -0
  122. package/dist/mcp/builtin/globals/restoreVersionTool.d.ts +2 -0
  123. package/dist/mcp/builtin/globals/restoreVersionTool.d.ts.map +1 -0
  124. package/dist/mcp/builtin/globals/restoreVersionTool.js +70 -0
  125. package/dist/mcp/builtin/globals/restoreVersionTool.js.map +1 -0
  126. package/dist/mcp/builtin/globals/updateTool.d.ts.map +1 -1
  127. package/dist/mcp/builtin/globals/updateTool.js +44 -62
  128. package/dist/mcp/builtin/globals/updateTool.js.map +1 -1
  129. package/dist/mcp/builtinTools.d.ts +150 -19
  130. package/dist/mcp/builtinTools.d.ts.map +1 -1
  131. package/dist/mcp/builtinTools.js +125 -20
  132. package/dist/mcp/builtinTools.js.map +1 -1
  133. package/dist/mcp/sanitizeMCPConfig.d.ts +0 -1
  134. package/dist/mcp/sanitizeMCPConfig.d.ts.map +1 -1
  135. package/dist/mcp/sanitizeMCPConfig.js +125 -58
  136. package/dist/mcp/sanitizeMCPConfig.js.map +1 -1
  137. package/dist/stdio.d.ts +3 -3
  138. package/dist/stdio.d.ts.map +1 -1
  139. package/dist/stdio.js +86 -47
  140. package/dist/stdio.js.map +1 -1
  141. package/dist/types.d.ts +138 -114
  142. package/dist/types.d.ts.map +1 -1
  143. package/dist/types.js +2 -4
  144. package/dist/types.js.map +1 -1
  145. package/dist/utils/camelCase.d.ts.map +1 -1
  146. package/dist/utils/getPluginConfig.d.ts +1 -1
  147. package/dist/utils/getPluginConfig.js +1 -1
  148. package/dist/utils/getPluginConfig.js.map +1 -1
  149. package/dist/utils/resolveProjectRoot.d.ts.map +1 -1
  150. package/dist/utils/toStandardSchema.d.ts.map +1 -1
  151. package/package.json +11 -18
  152. package/src/defaultAccess.ts +3 -0
  153. package/src/endpoint/access.ts +81 -101
  154. package/src/endpoint/index.ts +93 -15
  155. package/src/endpoint/oauth.ts +72 -0
  156. package/src/exports/client.ts +2 -1
  157. package/src/exports/internal.ts +1 -0
  158. package/src/index.ts +19 -20
  159. package/src/mcp/buildMcpServer.ts +181 -116
  160. package/src/mcp/builtin/collections/authTools.ts +122 -75
  161. package/src/mcp/builtin/collections/countTool.ts +61 -0
  162. package/src/mcp/builtin/collections/countVersionsTool.ts +60 -0
  163. package/src/mcp/builtin/collections/createTool.ts +117 -88
  164. package/src/mcp/builtin/collections/deleteTool.ts +48 -74
  165. package/src/mcp/builtin/collections/duplicateTool.ts +84 -0
  166. package/src/mcp/builtin/collections/fileInput.spec.ts +93 -0
  167. package/src/mcp/builtin/collections/fileInput.ts +127 -0
  168. package/src/mcp/builtin/collections/findDistinctTool.ts +67 -0
  169. package/src/mcp/builtin/collections/findTool.ts +57 -110
  170. package/src/mcp/builtin/collections/findVersionByIDTool.ts +66 -0
  171. package/src/mcp/builtin/collections/findVersionsTool.ts +83 -0
  172. package/src/mcp/builtin/collections/getCollectionSchemaTool.ts +91 -0
  173. package/src/mcp/builtin/collections/restoreVersionTool.ts +65 -0
  174. package/src/mcp/builtin/collections/updateTool.ts +106 -143
  175. package/src/mcp/builtin/collections/uploadInstructionsTool.ts +64 -0
  176. package/src/mcp/builtin/formatEntityError.ts +77 -0
  177. package/src/mcp/builtin/getConfigInfoTool.ts +68 -0
  178. package/src/mcp/builtin/globals/countVersionsTool.ts +60 -0
  179. package/src/mcp/builtin/globals/findTool.ts +27 -57
  180. package/src/mcp/builtin/globals/findVersionByIDTool.ts +64 -0
  181. package/src/mcp/builtin/globals/findVersionsTool.ts +69 -0
  182. package/src/mcp/builtin/globals/getGlobalSchemaTool.ts +73 -0
  183. package/src/mcp/builtin/globals/restoreVersionTool.ts +68 -0
  184. package/src/mcp/builtin/globals/updateTool.ts +51 -79
  185. package/src/mcp/builtinTools.ts +118 -41
  186. package/src/mcp/sanitizeMCPConfig.ts +121 -78
  187. package/src/stdio.ts +80 -47
  188. package/src/types.ts +156 -120
  189. package/src/utils/getPluginConfig.ts +1 -1
  190. package/dist/@types/assets.d.js +0 -2
  191. package/dist/@types/assets.d.js.map +0 -1
  192. package/dist/collection/getAccessField.d.ts +0 -12
  193. package/dist/collection/getAccessField.d.ts.map +0 -1
  194. package/dist/collection/getAccessField.js +0 -57
  195. package/dist/collection/getAccessField.js.map +0 -1
  196. package/dist/collection/index.d.ts +0 -6
  197. package/dist/collection/index.d.ts.map +0 -1
  198. package/dist/collection/index.js +0 -60
  199. package/dist/collection/index.js.map +0 -1
  200. package/dist/components/AccessField/index.client.d.ts +0 -10
  201. package/dist/components/AccessField/index.client.d.ts.map +0 -1
  202. package/dist/components/AccessField/index.client.js +0 -305
  203. package/dist/components/AccessField/index.client.js.map +0 -1
  204. package/dist/components/AccessField/index.css +0 -93
  205. package/dist/utils/getVirtualFieldNames.d.ts +0 -14
  206. package/dist/utils/getVirtualFieldNames.d.ts.map +0 -1
  207. package/dist/utils/getVirtualFieldNames.js +0 -35
  208. package/dist/utils/getVirtualFieldNames.js.map +0 -1
  209. package/dist/utils/localAPIDefaults.d.ts +0 -20
  210. package/dist/utils/localAPIDefaults.d.ts.map +0 -1
  211. package/dist/utils/localAPIDefaults.js +0 -19
  212. package/dist/utils/localAPIDefaults.js.map +0 -1
  213. package/dist/utils/schemaConversion/buildToolInput.d.ts +0 -29
  214. package/dist/utils/schemaConversion/buildToolInput.d.ts.map +0 -1
  215. package/dist/utils/schemaConversion/buildToolInput.js +0 -51
  216. package/dist/utils/schemaConversion/buildToolInput.js.map +0 -1
  217. package/dist/utils/schemaConversion/removeVirtualFieldsFromSchema.d.ts +0 -7
  218. package/dist/utils/schemaConversion/removeVirtualFieldsFromSchema.d.ts.map +0 -1
  219. package/dist/utils/schemaConversion/removeVirtualFieldsFromSchema.js +0 -20
  220. package/dist/utils/schemaConversion/removeVirtualFieldsFromSchema.js.map +0 -1
  221. package/dist/utils/schemaConversion/sanitizeEntitySchema.d.ts +0 -15
  222. package/dist/utils/schemaConversion/sanitizeEntitySchema.d.ts.map +0 -1
  223. package/dist/utils/schemaConversion/sanitizeEntitySchema.js +0 -464
  224. package/dist/utils/schemaConversion/sanitizeEntitySchema.js.map +0 -1
  225. package/dist/utils/schemaConversion/sanitizeEntitySchema.spec.js +0 -158
  226. package/dist/utils/schemaConversion/sanitizeEntitySchema.spec.js.map +0 -1
  227. package/dist/utils/transformPointDataToPayload.d.ts +0 -7
  228. package/dist/utils/transformPointDataToPayload.d.ts.map +0 -1
  229. package/dist/utils/transformPointDataToPayload.js +0 -28
  230. package/dist/utils/transformPointDataToPayload.js.map +0 -1
  231. package/src/@types/assets.d.ts +0 -3
  232. package/src/collection/getAccessField.ts +0 -64
  233. package/src/collection/index.ts +0 -64
  234. package/src/components/AccessField/index.client.tsx +0 -344
  235. package/src/components/AccessField/index.css +0 -93
  236. package/src/utils/getVirtualFieldNames.ts +0 -53
  237. package/src/utils/localAPIDefaults.ts +0 -22
  238. package/src/utils/schemaConversion/buildToolInput.ts +0 -68
  239. package/src/utils/schemaConversion/removeVirtualFieldsFromSchema.ts +0 -27
  240. package/src/utils/schemaConversion/sanitizeEntitySchema.spec.ts +0 -103
  241. package/src/utils/schemaConversion/sanitizeEntitySchema.ts +0 -529
  242. package/src/utils/transformPointDataToPayload.ts +0 -40
package/LICENSE.md CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2018-2024 Payload CMS, Inc. <info@payloadcms.com>
3
+ Copyright (c) 2018-2026 Payload CMS, LLC <info@payloadcms.com>
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining
6
6
  a copy of this software and associated documentation files (the
@@ -0,0 +1,3 @@
1
+ import type { MCPAccessArgs } from './types.js';
2
+ export declare const defaultAccess: ({ req }: MCPAccessArgs) => boolean;
3
+ //# sourceMappingURL=defaultAccess.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"defaultAccess.d.ts","sourceRoot":"","sources":["../src/defaultAccess.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAE/C,eAAO,MAAM,aAAa,YAAa,aAAa,KAAG,OAA4B,CAAA"}
@@ -0,0 +1,3 @@
1
+ export const defaultAccess = ({ req })=>Boolean(req.user);
2
+
3
+ //# sourceMappingURL=defaultAccess.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/defaultAccess.ts"],"sourcesContent":["import type { MCPAccessArgs } from './types.js'\n\nexport const defaultAccess = ({ req }: MCPAccessArgs): boolean => Boolean(req.user)\n"],"names":["defaultAccess","req","Boolean","user"],"mappings":"AAEA,OAAO,MAAMA,gBAAgB,CAAC,EAAEC,GAAG,EAAiB,GAAcC,QAAQD,IAAIE,IAAI,EAAC"}
@@ -11,16 +11,16 @@ import type { CollectionTool, GlobalTool, Prompt, Tool, ToolInputSchema } from '
11
11
  * Config and handler signatures are derived from `Tool` / `CollectionTool` / `GlobalTool` /
12
12
  * `Prompt` via `Omit` + indexed access so there's no duplication with `types.ts`.
13
13
  */
14
- export declare const defineTool: <TSchema extends ToolInputSchema | undefined = ToolInputSchema | undefined>(args: Omit<Tool<TSchema>, "handler">) => {
15
- handler: (fn: Tool<TSchema>["handler"]) => Tool;
14
+ export declare const defineTool: <TSchema extends ToolInputSchema | undefined = ToolInputSchema | undefined>(args: Omit<Tool<TSchema>, 'handler'>) => {
15
+ handler: (fn: Tool<TSchema>['handler']) => Tool;
16
16
  };
17
- export declare const defineCollectionTool: <TSchema extends ToolInputSchema | undefined = ToolInputSchema | undefined>(args: Omit<CollectionTool<TSchema>, "handler">) => {
18
- handler: (fn: CollectionTool<TSchema>["handler"]) => CollectionTool;
17
+ export declare const defineCollectionTool: <TSchema extends ToolInputSchema | undefined = ToolInputSchema | undefined>(args: Omit<CollectionTool<TSchema>, 'handler'>) => {
18
+ handler: (fn: CollectionTool<TSchema>['handler']) => CollectionTool;
19
19
  };
20
- export declare const defineGlobalTool: <TSchema extends ToolInputSchema | undefined = ToolInputSchema | undefined>(args: Omit<GlobalTool<TSchema>, "handler">) => {
21
- handler: (fn: GlobalTool<TSchema>["handler"]) => GlobalTool;
20
+ export declare const defineGlobalTool: <TSchema extends ToolInputSchema | undefined = ToolInputSchema | undefined>(args: Omit<GlobalTool<TSchema>, 'handler'>) => {
21
+ handler: (fn: GlobalTool<TSchema>['handler']) => GlobalTool;
22
22
  };
23
- export declare const definePrompt: <TSchema extends ToolInputSchema = ToolInputSchema>(args: Omit<Prompt<TSchema>, "handler">) => {
24
- handler: (fn: Prompt<TSchema>["handler"]) => Prompt;
23
+ export declare const definePrompt: <TSchema extends ToolInputSchema = ToolInputSchema>(args: Omit<Prompt<TSchema>, 'handler'>) => {
24
+ handler: (fn: Prompt<TSchema>['handler']) => Prompt;
25
25
  };
26
26
  //# sourceMappingURL=defineTool.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"defineTool.d.ts","sourceRoot":"","sources":["../src/defineTool.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAE3F;;;;;;;;;;;GAWG;AAEH,eAAO,MAAM,UAAU,GACrB,OAAO,SAAS,eAAe,GAAG,SAAS,GAAG,eAAe,GAAG,SAAS,EAEzE,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,SAAS,CAAC,KACnC;IAAE,OAAO,EAAE,CAAC,EAAE,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,KAAK,IAAI,CAAA;CAElD,CAAA;AAEF,eAAO,MAAM,oBAAoB,GAC/B,OAAO,SAAS,eAAe,GAAG,SAAS,GAAG,eAAe,GAAG,SAAS,EAEzE,MAAM,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,EAAE,SAAS,CAAC,KAC7C;IAAE,OAAO,EAAE,CAAC,EAAE,EAAE,cAAc,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,KAAK,cAAc,CAAA;CAEtE,CAAA;AAEF,eAAO,MAAM,gBAAgB,GAC3B,OAAO,SAAS,eAAe,GAAG,SAAS,GAAG,eAAe,GAAG,SAAS,EAEzE,MAAM,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,SAAS,CAAC,KACzC;IAAE,OAAO,EAAE,CAAC,EAAE,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,KAAK,UAAU,CAAA;CAE9D,CAAA;AAEF,eAAO,MAAM,YAAY,GAAI,OAAO,SAAS,eAAe,GAAG,eAAe,EAC5E,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,SAAS,CAAC,KACrC;IAAE,OAAO,EAAE,CAAC,EAAE,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,KAAK,MAAM,CAAA;CAEtD,CAAA"}
1
+ {"version":3,"file":"defineTool.d.ts","sourceRoot":"","sources":["../src/defineTool.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAE3F;;;;;;;;;;;GAWG;AAEH,eAAO,MAAM,UAAU,GACrB,OAAO,SAAS,eAAe,GAAG,SAAS,GAAG,eAAe,GAAG,SAAS,QAEnE,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,SAAS,CAAC,KACnC;IAAE,OAAO,EAAE,CAAC,EAAE,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,KAAK,IAAI,CAAA;CAElD,CAAA;AAEF,eAAO,MAAM,oBAAoB,GAC/B,OAAO,SAAS,eAAe,GAAG,SAAS,GAAG,eAAe,GAAG,SAAS,QAEnE,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,EAAE,SAAS,CAAC,KAC7C;IAAE,OAAO,EAAE,CAAC,EAAE,EAAE,cAAc,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,KAAK,cAAc,CAAA;CAEtE,CAAA;AAEF,eAAO,MAAM,gBAAgB,GAC3B,OAAO,SAAS,eAAe,GAAG,SAAS,GAAG,eAAe,GAAG,SAAS,QAEnE,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,SAAS,CAAC,KACzC;IAAE,OAAO,EAAE,CAAC,EAAE,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,KAAK,UAAU,CAAA;CAE9D,CAAA;AAEF,eAAO,MAAM,YAAY,GAAI,OAAO,SAAS,eAAe,GAAG,eAAe,QACtE,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,SAAS,CAAC,KACrC;IAAE,OAAO,EAAE,CAAC,EAAE,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,KAAK,MAAM,CAAA;CAEtD,CAAA"}
@@ -1,10 +1,17 @@
1
1
  import type { PayloadRequest } from 'payload';
2
- import type { AuthorizedMCP } from '../types.js';
2
+ import type { AuthorizedMCP, MCPItem } from '../types.js';
3
+ export type GetAuthorizedMCPArgs = {
4
+ overrideAccess: boolean;
5
+ req: PayloadRequest;
6
+ };
3
7
  /**
4
- * Resolves the API key (or dev-mode session) and returns the items the caller
5
- * may use. Denied items are dropped from the array.
8
+ * Authenticates an MCP request and removes items the user cannot access.
9
+ * `overrideAccess` skips Payload and MCP item access checks.
6
10
  */
7
- export declare const getAuthorizedMCP: (args: {
11
+ export declare const getAuthorizedMCP: (args: GetAuthorizedMCPArgs) => Promise<AuthorizedMCP>;
12
+ export declare const filterMCPItems: ({ items, overrideAccess, req, }: {
13
+ items: MCPItem[];
14
+ overrideAccess: boolean;
8
15
  req: PayloadRequest;
9
- }) => Promise<AuthorizedMCP>;
16
+ }) => Promise<MCPItem[]>;
10
17
  //# sourceMappingURL=access.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"access.d.ts","sourceRoot":"","sources":["../../src/endpoint/access.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAyB,cAAc,EAAa,MAAM,SAAS,CAAA;AAK/E,OAAO,KAAK,EAAE,aAAa,EAAiB,MAAM,aAAa,CAAA;AAK/D;;;GAGG;AACH,eAAO,MAAM,gBAAgB,EAAE,CAAC,IAAI,EAAE;IAAE,GAAG,EAAE,cAAc,CAAA;CAAE,KAAK,OAAO,CAAC,aAAa,CAiDtF,CAAA"}
1
+ {"version":3,"file":"access.d.ts","sourceRoot":"","sources":["../../src/endpoint/access.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAwB,MAAM,SAAS,CAAA;AAInE,OAAO,KAAK,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,aAAa,CAAA;AAIzD,MAAM,MAAM,oBAAoB,GAAG;IACjC,cAAc,EAAE,OAAO,CAAA;IACvB,GAAG,EAAE,cAAc,CAAA;CACpB,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,gBAAgB,EAAE,CAAC,IAAI,EAAE,oBAAoB,KAAK,OAAO,CAAC,aAAa,CAmCnF,CAAA;AAED,eAAO,MAAM,cAAc,oCAIxB;IACD,KAAK,EAAE,OAAO,EAAE,CAAA;IAChB,cAAc,EAAE,OAAO,CAAA;IACvB,GAAG,EAAE,cAAc,CAAA;CACpB,KAAG,OAAO,CAAC,OAAO,EAAE,CAkBpB,CAAA"}
@@ -1,106 +1,94 @@
1
- import crypto from 'crypto';
2
- import { UnauthorizedError } from 'payload';
3
- import { getLogger } from '../utils/getLogger.js';
1
+ import { getAccessResults, UnauthorizedError } from 'payload';
4
2
  import { getPluginConfig } from '../utils/getPluginConfig.js';
5
3
  /**
6
- * Resolves the API key (or dev-mode session) and returns the items the caller
7
- * may use. Denied items are dropped from the array.
8
- */ export const getAuthorizedMCP = async ({ req })=>{
9
- const logger = getLogger({
10
- payload: req.payload
11
- });
4
+ * Authenticates an MCP request and removes items the user cannot access.
5
+ * `overrideAccess` skips Payload and MCP item access checks.
6
+ */ export const getAuthorizedMCP = async ({ overrideAccess, req })=>{
12
7
  const pluginConfig = getPluginConfig({
13
8
  config: req.payload.config
14
9
  });
15
- const authHeader = req.headers.get('Authorization');
16
- const hasBearerToken = authHeader?.startsWith('Bearer ');
17
- const buildAuthorized = (apiKeyDoc)=>({
18
- items: pluginConfig.items.filter((item)=>{
19
- switch(item.type){
20
- case 'collectionTool':
21
- return apiKeyDoc.access.collections?.[item.collectionSlug]?.[item.key] !== false;
22
- case 'globalTool':
23
- return apiKeyDoc.access.globals?.[item.globalSlug]?.[item.key] !== false;
24
- case 'prompt':
25
- return apiKeyDoc.access.prompts?.[item.key] !== false;
26
- case 'resource':
27
- return apiKeyDoc.access.resources?.[item.key] !== false;
28
- case 'tool':
29
- return apiKeyDoc.access.tools?.[item.key] !== false;
30
- }
31
- }),
32
- overrideAccess: typeof apiKeyDoc.overrideAccess === 'boolean' ? apiKeyDoc.overrideAccess : false,
33
- user: apiKeyDoc.user
34
- });
35
- if (pluginConfig.overrideAuth) {
36
- return await pluginConfig.overrideAuth({
37
- getAPIKeyDoc: (overrideApiKey)=>getAPIKeyDoc({
38
- logger,
39
- overrideApiKey,
40
- pluginConfig,
41
- req
42
- }),
43
- getAuthorizedMCP: ({ apiKeyDoc })=>buildAuthorized(apiKeyDoc),
10
+ if (pluginConfig.overrideGetAuthorizedMCP) {
11
+ return await pluginConfig.overrideGetAuthorizedMCP({
12
+ overrideAccess,
44
13
  pluginConfig,
45
14
  req
46
15
  });
47
16
  }
48
- if (process.env.NODE_ENV === 'development' && !hasBearerToken) {
49
- logger.info('Dev mode: skipping API key check, using session user');
50
- return buildAuthorized({
51
- id: -1,
52
- access: {},
53
- overrideAccess: true,
54
- user: req.user ?? null
55
- });
17
+ if (req.headers) {
18
+ const headers = new Headers(req.headers);
19
+ const hasAuthorization = headers.has('Authorization');
20
+ headers.set('DisableAutologin', 'true');
21
+ req.user = (await req.payload.auth({
22
+ headers,
23
+ req
24
+ })).user;
25
+ // With OAuth, the endpoint answers with a challenge that starts the client's sign-in
26
+ if (hasAuthorization && !req.user && !pluginConfig.oauth) {
27
+ throw new UnauthorizedError(req.t);
28
+ }
56
29
  }
57
- return buildAuthorized(await getAPIKeyDoc({
58
- logger,
59
- pluginConfig,
60
- req
61
- }));
30
+ return {
31
+ items: await filterMCPItems({
32
+ items: pluginConfig.items,
33
+ overrideAccess,
34
+ req
35
+ }),
36
+ overrideAccess
37
+ };
62
38
  };
63
- const getAPIKeyDoc = async ({ logger, overrideApiKey, pluginConfig, req })=>{
64
- const authHeader = req.headers.get('Authorization');
65
- const hasBearerToken = authHeader?.startsWith('Bearer ');
66
- const apiKey = overrideApiKey ?? (hasBearerToken ? authHeader?.replace('Bearer ', '').trim() || null : null);
67
- if (!apiKey) {
68
- throw new UnauthorizedError();
69
- }
70
- const sha256APIKeyIndex = crypto.createHmac('sha256', req.payload.secret).update(apiKey).digest('hex');
71
- const doc = await req.payload.db.findOne({
72
- collection: 'payload-mcp-api-keys',
73
- req,
74
- where: {
75
- apiKeyIndex: {
76
- equals: sha256APIKeyIndex
77
- }
78
- }
79
- });
80
- if (!doc || !doc.user) {
81
- throw new UnauthorizedError();
39
+ export const filterMCPItems = async ({ items, overrideAccess, req })=>{
40
+ // Match Payload core: overrideAccess bypasses access evaluation
41
+ if (overrideAccess) {
42
+ return items;
82
43
  }
83
- logger.info('API Key is valid');
84
- const userRef = doc.user;
85
- const userID = typeof userRef === 'object' && userRef !== null && 'id' in userRef ? userRef.id : userRef;
86
- const user = await req.payload.findByID({
87
- id: userID,
88
- collection: pluginConfig.userCollection,
89
- depth: 0,
90
- disableErrors: true,
44
+ const authorizedItems = [];
45
+ const permissions = await getAccessResults({
91
46
  req
92
47
  });
93
- if (!user) {
94
- throw new UnauthorizedError();
95
- }
96
- return {
97
- ...doc,
98
- user: {
99
- ...user,
100
- _strategy: 'mcp-api-key',
101
- collection: pluginConfig.userCollection
48
+ for (const item of items){
49
+ if (!await checkItemAccess({
50
+ item,
51
+ permissions,
52
+ req
53
+ })) {
54
+ continue;
102
55
  }
103
- };
56
+ authorizedItems.push(item);
57
+ }
58
+ return authorizedItems;
59
+ };
60
+ /**
61
+ * Runs MCP item access callbacks
62
+ */ const checkItemAccess = async ({ item, permissions, req })=>{
63
+ switch(item.type){
64
+ case 'collectionTool':
65
+ return !item.tool.access || await item.tool.access({
66
+ slug: item.collectionSlug,
67
+ permissions,
68
+ req
69
+ });
70
+ case 'globalTool':
71
+ return !item.tool.access || await item.tool.access({
72
+ slug: item.globalSlug,
73
+ permissions,
74
+ req
75
+ });
76
+ case 'prompt':
77
+ return !item.prompt.access || await item.prompt.access({
78
+ permissions,
79
+ req
80
+ });
81
+ case 'resource':
82
+ return !item.resource.access || await item.resource.access({
83
+ permissions,
84
+ req
85
+ });
86
+ case 'tool':
87
+ return !item.tool.access || await item.tool.access({
88
+ permissions,
89
+ req
90
+ });
91
+ }
104
92
  };
105
93
 
106
94
  //# sourceMappingURL=access.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/endpoint/access.ts"],"sourcesContent":["import type { DefaultDocumentIDType, PayloadRequest, TypedUser } from 'payload'\n\nimport crypto from 'crypto'\nimport { UnauthorizedError } from 'payload'\n\nimport type { AuthorizedMCP, MCPAPIKeysDoc } from '../types.js'\n\nimport { getLogger } from '../utils/getLogger.js'\nimport { getPluginConfig } from '../utils/getPluginConfig.js'\n\n/**\n * Resolves the API key (or dev-mode session) and returns the items the caller\n * may use. Denied items are dropped from the array.\n */\nexport const getAuthorizedMCP: (args: { req: PayloadRequest }) => Promise<AuthorizedMCP> = async ({\n req,\n}) => {\n const logger = getLogger({ payload: req.payload })\n const pluginConfig = getPluginConfig({ config: req.payload.config })\n\n const authHeader = req.headers.get('Authorization')\n const hasBearerToken = authHeader?.startsWith('Bearer ')\n\n const buildAuthorized = (apiKeyDoc: MCPAPIKeysDoc): AuthorizedMCP => ({\n items: pluginConfig.items.filter((item) => {\n switch (item.type) {\n case 'collectionTool':\n return apiKeyDoc.access.collections?.[item.collectionSlug]?.[item.key] !== false\n case 'globalTool':\n return apiKeyDoc.access.globals?.[item.globalSlug]?.[item.key] !== false\n case 'prompt':\n return apiKeyDoc.access.prompts?.[item.key] !== false\n case 'resource':\n return apiKeyDoc.access.resources?.[item.key] !== false\n case 'tool':\n return apiKeyDoc.access.tools?.[item.key] !== false\n }\n }),\n overrideAccess:\n typeof apiKeyDoc.overrideAccess === 'boolean' ? apiKeyDoc.overrideAccess : false,\n user: apiKeyDoc.user,\n })\n\n if (pluginConfig.overrideAuth) {\n return await pluginConfig.overrideAuth({\n getAPIKeyDoc: (overrideApiKey) => getAPIKeyDoc({ logger, overrideApiKey, pluginConfig, req }),\n getAuthorizedMCP: ({ apiKeyDoc }) => buildAuthorized(apiKeyDoc),\n pluginConfig,\n req,\n })\n }\n\n if (process.env.NODE_ENV === 'development' && !hasBearerToken) {\n logger.info('Dev mode: skipping API key check, using session user')\n return buildAuthorized({\n id: -1,\n access: {},\n overrideAccess: true,\n user: req.user ?? null,\n })\n }\n\n return buildAuthorized(await getAPIKeyDoc({ logger, pluginConfig, req }))\n}\n\nconst getAPIKeyDoc = async ({\n logger,\n overrideApiKey,\n pluginConfig,\n req,\n}: {\n logger: ReturnType<typeof getLogger>\n overrideApiKey?: string\n pluginConfig: ReturnType<typeof getPluginConfig>\n req: PayloadRequest\n}): Promise<MCPAPIKeysDoc> => {\n const authHeader = req.headers.get('Authorization')\n const hasBearerToken = authHeader?.startsWith('Bearer ')\n\n const apiKey =\n overrideApiKey ?? (hasBearerToken ? authHeader?.replace('Bearer ', '').trim() || null : null)\n\n if (!apiKey) {\n throw new UnauthorizedError()\n }\n\n const sha256APIKeyIndex = crypto\n .createHmac('sha256', req.payload.secret)\n .update(apiKey)\n .digest('hex')\n\n const doc = await req.payload.db.findOne<MCPAPIKeysDoc>({\n collection: 'payload-mcp-api-keys',\n req,\n where: {\n apiKeyIndex: { equals: sha256APIKeyIndex },\n },\n })\n\n if (!doc || !doc.user) {\n throw new UnauthorizedError()\n }\n\n logger.info('API Key is valid')\n\n const userRef = doc.user\n const userID =\n typeof userRef === 'object' && userRef !== null && 'id' in userRef\n ? userRef.id\n : (userRef as unknown as DefaultDocumentIDType)\n\n const user = (await req.payload.findByID({\n id: userID,\n collection: pluginConfig.userCollection,\n depth: 0,\n disableErrors: true,\n req,\n })) as null | TypedUser\n\n if (!user) {\n throw new UnauthorizedError()\n }\n\n return {\n ...doc,\n user: {\n ...user,\n _strategy: 'mcp-api-key' as const,\n collection: pluginConfig.userCollection,\n },\n }\n}\n"],"names":["crypto","UnauthorizedError","getLogger","getPluginConfig","getAuthorizedMCP","req","logger","payload","pluginConfig","config","authHeader","headers","get","hasBearerToken","startsWith","buildAuthorized","apiKeyDoc","items","filter","item","type","access","collections","collectionSlug","key","globals","globalSlug","prompts","resources","tools","overrideAccess","user","overrideAuth","getAPIKeyDoc","overrideApiKey","process","env","NODE_ENV","info","id","apiKey","replace","trim","sha256APIKeyIndex","createHmac","secret","update","digest","doc","db","findOne","collection","where","apiKeyIndex","equals","userRef","userID","findByID","userCollection","depth","disableErrors","_strategy"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/endpoint/access.ts"],"sourcesContent":["import type { PayloadRequest, SanitizedPermissions } from 'payload'\n\nimport { getAccessResults, UnauthorizedError } from 'payload'\n\nimport type { AuthorizedMCP, MCPItem } from '../types.js'\n\nimport { getPluginConfig } from '../utils/getPluginConfig.js'\n\nexport type GetAuthorizedMCPArgs = {\n overrideAccess: boolean\n req: PayloadRequest\n}\n\n/**\n * Authenticates an MCP request and removes items the user cannot access.\n * `overrideAccess` skips Payload and MCP item access checks.\n */\nexport const getAuthorizedMCP: (args: GetAuthorizedMCPArgs) => Promise<AuthorizedMCP> = async ({\n overrideAccess,\n req,\n}) => {\n const pluginConfig = getPluginConfig({ config: req.payload.config })\n\n if (pluginConfig.overrideGetAuthorizedMCP) {\n return await pluginConfig.overrideGetAuthorizedMCP({\n overrideAccess,\n pluginConfig,\n req,\n })\n }\n\n if (req.headers) {\n const headers = new Headers(req.headers)\n const hasAuthorization = headers.has('Authorization')\n\n headers.set('DisableAutologin', 'true')\n req.user = (await req.payload.auth({ headers, req })).user\n\n // With OAuth, the endpoint answers with a challenge that starts the client's sign-in\n if (hasAuthorization && !req.user && !pluginConfig.oauth) {\n throw new UnauthorizedError(req.t)\n }\n }\n\n return {\n items: await filterMCPItems({\n items: pluginConfig.items,\n overrideAccess,\n req,\n }),\n overrideAccess,\n }\n}\n\nexport const filterMCPItems = async ({\n items,\n overrideAccess,\n req,\n}: {\n items: MCPItem[]\n overrideAccess: boolean\n req: PayloadRequest\n}): Promise<MCPItem[]> => {\n // Match Payload core: overrideAccess bypasses access evaluation\n if (overrideAccess) {\n return items\n }\n\n const authorizedItems: MCPItem[] = []\n\n const permissions = await getAccessResults({ req })\n\n for (const item of items) {\n if (!(await checkItemAccess({ item, permissions, req }))) {\n continue\n }\n authorizedItems.push(item)\n }\n\n return authorizedItems\n}\n\n/**\n * Runs MCP item access callbacks\n */\nconst checkItemAccess = async ({\n item,\n permissions,\n req,\n}: {\n item: MCPItem\n permissions?: SanitizedPermissions\n req: PayloadRequest\n}): Promise<boolean> => {\n switch (item.type) {\n case 'collectionTool':\n return (\n !item.tool.access ||\n (await item.tool.access({ slug: item.collectionSlug, permissions, req }))\n )\n case 'globalTool':\n return (\n !item.tool.access || (await item.tool.access({ slug: item.globalSlug, permissions, req }))\n )\n case 'prompt':\n return !item.prompt.access || (await item.prompt.access({ permissions, req }))\n case 'resource':\n return !item.resource.access || (await item.resource.access({ permissions, req }))\n case 'tool':\n return !item.tool.access || (await item.tool.access({ permissions, req }))\n }\n}\n"],"names":["getAccessResults","UnauthorizedError","getPluginConfig","getAuthorizedMCP","overrideAccess","req","pluginConfig","config","payload","overrideGetAuthorizedMCP","headers","Headers","hasAuthorization","has","set","user","auth","oauth","t","items","filterMCPItems","authorizedItems","permissions","item","checkItemAccess","push","type","tool","access","slug","collectionSlug","globalSlug","prompt","resource"],"mappings":"AAEA,SAASA,gBAAgB,EAAEC,iBAAiB,QAAQ,UAAS;AAI7D,SAASC,eAAe,QAAQ,8BAA6B;AAO7D;;;CAGC,GACD,OAAO,MAAMC,mBAA2E,OAAO,EAC7FC,cAAc,EACdC,GAAG,EACJ;IACC,MAAMC,eAAeJ,gBAAgB;QAAEK,QAAQF,IAAIG,OAAO,CAACD,MAAM;IAAC;IAElE,IAAID,aAAaG,wBAAwB,EAAE;QACzC,OAAO,MAAMH,aAAaG,wBAAwB,CAAC;YACjDL;YACAE;YACAD;QACF;IACF;IAEA,IAAIA,IAAIK,OAAO,EAAE;QACf,MAAMA,UAAU,IAAIC,QAAQN,IAAIK,OAAO;QACvC,MAAME,mBAAmBF,QAAQG,GAAG,CAAC;QAErCH,QAAQI,GAAG,CAAC,oBAAoB;QAChCT,IAAIU,IAAI,GAAG,AAAC,CAAA,MAAMV,IAAIG,OAAO,CAACQ,IAAI,CAAC;YAAEN;YAASL;QAAI,EAAC,EAAGU,IAAI;QAE1D,qFAAqF;QACrF,IAAIH,oBAAoB,CAACP,IAAIU,IAAI,IAAI,CAACT,aAAaW,KAAK,EAAE;YACxD,MAAM,IAAIhB,kBAAkBI,IAAIa,CAAC;QACnC;IACF;IAEA,OAAO;QACLC,OAAO,MAAMC,eAAe;YAC1BD,OAAOb,aAAaa,KAAK;YACzBf;YACAC;QACF;QACAD;IACF;AACF,EAAC;AAED,OAAO,MAAMgB,iBAAiB,OAAO,EACnCD,KAAK,EACLf,cAAc,EACdC,GAAG,EAKJ;IACC,gEAAgE;IAChE,IAAID,gBAAgB;QAClB,OAAOe;IACT;IAEA,MAAME,kBAA6B,EAAE;IAErC,MAAMC,cAAc,MAAMtB,iBAAiB;QAAEK;IAAI;IAEjD,KAAK,MAAMkB,QAAQJ,MAAO;QACxB,IAAI,CAAE,MAAMK,gBAAgB;YAAED;YAAMD;YAAajB;QAAI,IAAK;YACxD;QACF;QACAgB,gBAAgBI,IAAI,CAACF;IACvB;IAEA,OAAOF;AACT,EAAC;AAED;;CAEC,GACD,MAAMG,kBAAkB,OAAO,EAC7BD,IAAI,EACJD,WAAW,EACXjB,GAAG,EAKJ;IACC,OAAQkB,KAAKG,IAAI;QACf,KAAK;YACH,OACE,CAACH,KAAKI,IAAI,CAACC,MAAM,IAChB,MAAML,KAAKI,IAAI,CAACC,MAAM,CAAC;gBAAEC,MAAMN,KAAKO,cAAc;gBAAER;gBAAajB;YAAI;QAE1E,KAAK;YACH,OACE,CAACkB,KAAKI,IAAI,CAACC,MAAM,IAAK,MAAML,KAAKI,IAAI,CAACC,MAAM,CAAC;gBAAEC,MAAMN,KAAKQ,UAAU;gBAAET;gBAAajB;YAAI;QAE3F,KAAK;YACH,OAAO,CAACkB,KAAKS,MAAM,CAACJ,MAAM,IAAK,MAAML,KAAKS,MAAM,CAACJ,MAAM,CAAC;gBAAEN;gBAAajB;YAAI;QAC7E,KAAK;YACH,OAAO,CAACkB,KAAKU,QAAQ,CAACL,MAAM,IAAK,MAAML,KAAKU,QAAQ,CAACL,MAAM,CAAC;gBAAEN;gBAAajB;YAAI;QACjF,KAAK;YACH,OAAO,CAACkB,KAAKI,IAAI,CAACC,MAAM,IAAK,MAAML,KAAKI,IAAI,CAACC,MAAM,CAAC;gBAAEN;gBAAajB;YAAI;IAC3E;AACF"}
@@ -1,3 +1,3 @@
1
- import { type PayloadHandler } from 'payload';
1
+ import type { PayloadHandler } from 'payload';
2
2
  export declare const mcpEndpoint: PayloadHandler;
3
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/endpoint/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAY,KAAK,cAAc,EAAE,MAAM,SAAS,CAAA;AAMvD,eAAO,MAAM,WAAW,EAAE,cA2BzB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/endpoint/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAkB,MAAM,SAAS,CAAA;AAe7D,eAAO,MAAM,WAAW,EAAE,cAwEzB,CAAA"}
@@ -1,8 +1,9 @@
1
- import { WebStandardStreamableHTTPServerTransport } from '@modelcontextprotocol/server';
1
+ import { createMcpHandler, isLegacyRequest, readRequestBody, WebStandardStreamableHTTPServerTransport } from '@modelcontextprotocol/server';
2
2
  import { APIError } from 'payload';
3
3
  import { buildMcpServer } from '../mcp/buildMcpServer.js';
4
4
  import { getPluginConfig } from '../utils/getPluginConfig.js';
5
5
  import { getAuthorizedMCP } from './access.js';
6
+ import { oauthChallenge } from './oauth.js';
6
7
  export const mcpEndpoint = async (req)=>{
7
8
  if (!req.url) {
8
9
  throw new APIError('Missing request URL', 400);
@@ -11,26 +12,111 @@ export const mcpEndpoint = async (req)=>{
11
12
  const pluginConfig = getPluginConfig({
12
13
  config: req.payload.config
13
14
  });
15
+ const overrideAccessParam = new URL(req.url).searchParams.get('overrideAccess');
16
+ if (overrideAccessParam !== null && process.env.NODE_ENV !== 'development') {
17
+ throw new APIError('MCP overrideAccess is only available in development.', 400);
18
+ }
19
+ let overrideAccess = false;
20
+ if (overrideAccessParam === 'true') {
21
+ overrideAccess = true;
22
+ } else if (overrideAccessParam !== null && overrideAccessParam !== 'false') {
23
+ throw new APIError('MCP overrideAccess must be "true" or "false".', 400);
24
+ }
14
25
  const authorizedMCP = await getAuthorizedMCP({
26
+ overrideAccess,
15
27
  req
16
28
  });
17
- const server = buildMcpServer({
18
- authorizedMCP,
19
- pluginConfig,
20
- req
21
- });
22
- const transport = new WebStandardStreamableHTTPServerTransport({
23
- enableJsonResponse: true,
24
- sessionIdGenerator: undefined
29
+ if (pluginConfig.oauth && !req.user) {
30
+ return oauthChallenge({
31
+ req
32
+ });
33
+ }
34
+ const maxRequestBodySize = pluginConfig.mcp?.maxRequestBodySize;
35
+ // Payload augments the original web-standard Request in place.
36
+ const mcpRequest = req;
37
+ const parsedBody = await parseRequestBody({
38
+ maxRequestBodySize,
39
+ request: mcpRequest
25
40
  });
26
- await server.connect(transport);
27
- const mcpRequest = new Request(req.url, {
28
- body: req.body,
29
- duplex: 'half',
30
- headers: req.headers,
31
- method: req.method
41
+ // Keep the old JSON-only, stateless behavior because the SDK's 2025 fallback uses SSE.
42
+ if (await isLegacyRequest(mcpRequest, parsedBody, {
43
+ maxRequestBodySize
44
+ })) {
45
+ const server = buildMcpServer({
46
+ authorizedMCP,
47
+ pluginConfig,
48
+ req
49
+ });
50
+ const transport = new WebStandardStreamableHTTPServerTransport({
51
+ enableJsonResponse: true,
52
+ maxRequestBodySize,
53
+ sessionIdGenerator: undefined
54
+ });
55
+ transport.onerror = (err)=>{
56
+ req.payload.logger.error({
57
+ err,
58
+ msg: 'Error serving legacy MCP request'
59
+ });
60
+ };
61
+ try {
62
+ await server.connect(transport);
63
+ return await transport.handleRequest(mcpRequest, {
64
+ parsedBody
65
+ });
66
+ } finally{
67
+ await server.close().catch((err)=>{
68
+ req.payload.logger.error({
69
+ err,
70
+ msg: 'Error closing MCP server'
71
+ });
72
+ });
73
+ }
74
+ }
75
+ const handler = createMcpHandler(()=>buildMcpServer({
76
+ authorizedMCP,
77
+ pluginConfig,
78
+ req
79
+ }), {
80
+ legacy: 'reject',
81
+ maxRequestBodySize,
82
+ // SDK subscriptions always use SSE, so disable them to keep every response JSON-only.
83
+ maxSubscriptions: 0,
84
+ onerror: (err)=>{
85
+ req.payload.logger.error({
86
+ err,
87
+ msg: 'Error serving modern MCP request'
88
+ });
89
+ },
90
+ responseMode: 'json'
32
91
  });
33
- return await transport.handleRequest(mcpRequest);
92
+ try {
93
+ return await handler.fetch(mcpRequest, {
94
+ parsedBody
95
+ });
96
+ } finally{
97
+ await handler.close().catch((err)=>{
98
+ req.payload.logger.error({
99
+ err,
100
+ msg: 'Error closing modern MCP handler'
101
+ });
102
+ });
103
+ }
104
+ };
105
+ /**
106
+ * Parses a POST body once so the era check and the SDK handler can share it. The SDK
107
+ * skips its size limit for a pre-parsed body, so this reads with the same limit. It reads
108
+ * a clone and returns `undefined` for any body the SDK should reject (too large, unreadable,
109
+ * or not JSON), leaving the original request for the SDK to read and answer.
110
+ */ const parseRequestBody = async ({ maxRequestBodySize, request })=>{
111
+ if (request.method.toUpperCase() !== 'POST') {
112
+ return undefined;
113
+ }
114
+ try {
115
+ const body = await readRequestBody(request.clone(), maxRequestBodySize);
116
+ return body.tooLarge ? undefined : JSON.parse(body.text);
117
+ } catch {
118
+ return undefined;
119
+ }
34
120
  };
35
121
 
36
122
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/endpoint/index.ts"],"sourcesContent":["import { WebStandardStreamableHTTPServerTransport } from '@modelcontextprotocol/server'\nimport { APIError, type PayloadHandler } from 'payload'\n\nimport { buildMcpServer } from '../mcp/buildMcpServer.js'\nimport { getPluginConfig } from '../utils/getPluginConfig.js'\nimport { getAuthorizedMCP } from './access.js'\n\nexport const mcpEndpoint: PayloadHandler = async (req) => {\n if (!req.url) {\n throw new APIError('Missing request URL', 400)\n }\n\n req.payloadAPI = 'MCP' as const\n\n const pluginConfig = getPluginConfig({ config: req.payload.config })\n const authorizedMCP = await getAuthorizedMCP({ req })\n\n const server = buildMcpServer({ authorizedMCP, pluginConfig, req })\n\n const transport = new WebStandardStreamableHTTPServerTransport({\n enableJsonResponse: true,\n sessionIdGenerator: undefined, // stateless mode\n })\n\n await server.connect(transport)\n\n const mcpRequest = new Request(req.url, {\n body: req.body,\n duplex: 'half',\n headers: req.headers,\n method: req.method,\n } as { duplex: 'half' } & RequestInit)\n\n return await transport.handleRequest(mcpRequest)\n}\n"],"names":["WebStandardStreamableHTTPServerTransport","APIError","buildMcpServer","getPluginConfig","getAuthorizedMCP","mcpEndpoint","req","url","payloadAPI","pluginConfig","config","payload","authorizedMCP","server","transport","enableJsonResponse","sessionIdGenerator","undefined","connect","mcpRequest","Request","body","duplex","headers","method","handleRequest"],"mappings":"AAAA,SAASA,wCAAwC,QAAQ,+BAA8B;AACvF,SAASC,QAAQ,QAA6B,UAAS;AAEvD,SAASC,cAAc,QAAQ,2BAA0B;AACzD,SAASC,eAAe,QAAQ,8BAA6B;AAC7D,SAASC,gBAAgB,QAAQ,cAAa;AAE9C,OAAO,MAAMC,cAA8B,OAAOC;IAChD,IAAI,CAACA,IAAIC,GAAG,EAAE;QACZ,MAAM,IAAIN,SAAS,uBAAuB;IAC5C;IAEAK,IAAIE,UAAU,GAAG;IAEjB,MAAMC,eAAeN,gBAAgB;QAAEO,QAAQJ,IAAIK,OAAO,CAACD,MAAM;IAAC;IAClE,MAAME,gBAAgB,MAAMR,iBAAiB;QAAEE;IAAI;IAEnD,MAAMO,SAASX,eAAe;QAAEU;QAAeH;QAAcH;IAAI;IAEjE,MAAMQ,YAAY,IAAId,yCAAyC;QAC7De,oBAAoB;QACpBC,oBAAoBC;IACtB;IAEA,MAAMJ,OAAOK,OAAO,CAACJ;IAErB,MAAMK,aAAa,IAAIC,QAAQd,IAAIC,GAAG,EAAE;QACtCc,MAAMf,IAAIe,IAAI;QACdC,QAAQ;QACRC,SAASjB,IAAIiB,OAAO;QACpBC,QAAQlB,IAAIkB,MAAM;IACpB;IAEA,OAAO,MAAMV,UAAUW,aAAa,CAACN;AACvC,EAAC"}
1
+ {"version":3,"sources":["../../src/endpoint/index.ts"],"sourcesContent":["import type { PayloadHandler, PayloadRequest } from 'payload'\n\nimport {\n createMcpHandler,\n isLegacyRequest,\n readRequestBody,\n WebStandardStreamableHTTPServerTransport,\n} from '@modelcontextprotocol/server'\nimport { APIError } from 'payload'\n\nimport { buildMcpServer } from '../mcp/buildMcpServer.js'\nimport { getPluginConfig } from '../utils/getPluginConfig.js'\nimport { getAuthorizedMCP } from './access.js'\nimport { oauthChallenge } from './oauth.js'\n\nexport const mcpEndpoint: PayloadHandler = async (req) => {\n if (!req.url) {\n throw new APIError('Missing request URL', 400)\n }\n\n req.payloadAPI = 'MCP' as const\n\n const pluginConfig = getPluginConfig({ config: req.payload.config })\n const overrideAccessParam = new URL(req.url).searchParams.get('overrideAccess')\n\n if (overrideAccessParam !== null && process.env.NODE_ENV !== 'development') {\n throw new APIError('MCP overrideAccess is only available in development.', 400)\n }\n\n let overrideAccess = false\n if (overrideAccessParam === 'true') {\n overrideAccess = true\n } else if (overrideAccessParam !== null && overrideAccessParam !== 'false') {\n throw new APIError('MCP overrideAccess must be \"true\" or \"false\".', 400)\n }\n\n const authorizedMCP = await getAuthorizedMCP({ overrideAccess, req })\n\n if (pluginConfig.oauth && !req.user) {\n return oauthChallenge({ req })\n }\n\n const maxRequestBodySize = pluginConfig.mcp?.maxRequestBodySize\n // Payload augments the original web-standard Request in place.\n const mcpRequest = req as PayloadRequest & Request\n const parsedBody = await parseRequestBody({ maxRequestBodySize, request: mcpRequest })\n\n // Keep the old JSON-only, stateless behavior because the SDK's 2025 fallback uses SSE.\n if (await isLegacyRequest(mcpRequest, parsedBody, { maxRequestBodySize })) {\n const server = buildMcpServer({ authorizedMCP, pluginConfig, req })\n const transport = new WebStandardStreamableHTTPServerTransport({\n enableJsonResponse: true,\n maxRequestBodySize,\n sessionIdGenerator: undefined, // stateless mode\n })\n transport.onerror = (err) => {\n req.payload.logger.error({ err, msg: 'Error serving legacy MCP request' })\n }\n\n try {\n await server.connect(transport)\n return await transport.handleRequest(mcpRequest, { parsedBody })\n } finally {\n await server.close().catch((err) => {\n req.payload.logger.error({ err, msg: 'Error closing MCP server' })\n })\n }\n }\n\n const handler = createMcpHandler(() => buildMcpServer({ authorizedMCP, pluginConfig, req }), {\n legacy: 'reject',\n maxRequestBodySize,\n // SDK subscriptions always use SSE, so disable them to keep every response JSON-only.\n maxSubscriptions: 0,\n onerror: (err) => {\n req.payload.logger.error({ err, msg: 'Error serving modern MCP request' })\n },\n responseMode: 'json',\n })\n\n try {\n return await handler.fetch(mcpRequest, { parsedBody })\n } finally {\n await handler.close().catch((err) => {\n req.payload.logger.error({ err, msg: 'Error closing modern MCP handler' })\n })\n }\n}\n\n/**\n * Parses a POST body once so the era check and the SDK handler can share it. The SDK\n * skips its size limit for a pre-parsed body, so this reads with the same limit. It reads\n * a clone and returns `undefined` for any body the SDK should reject (too large, unreadable,\n * or not JSON), leaving the original request for the SDK to read and answer.\n */\nconst parseRequestBody = async ({\n maxRequestBodySize,\n request,\n}: {\n maxRequestBodySize?: number\n request: Request\n}): Promise<unknown> => {\n if (request.method.toUpperCase() !== 'POST') {\n return undefined\n }\n\n try {\n const body = await readRequestBody(request.clone(), maxRequestBodySize)\n return body.tooLarge ? undefined : JSON.parse(body.text)\n } catch {\n return undefined\n }\n}\n"],"names":["createMcpHandler","isLegacyRequest","readRequestBody","WebStandardStreamableHTTPServerTransport","APIError","buildMcpServer","getPluginConfig","getAuthorizedMCP","oauthChallenge","mcpEndpoint","req","url","payloadAPI","pluginConfig","config","payload","overrideAccessParam","URL","searchParams","get","process","env","NODE_ENV","overrideAccess","authorizedMCP","oauth","user","maxRequestBodySize","mcp","mcpRequest","parsedBody","parseRequestBody","request","server","transport","enableJsonResponse","sessionIdGenerator","undefined","onerror","err","logger","error","msg","connect","handleRequest","close","catch","handler","legacy","maxSubscriptions","responseMode","fetch","method","toUpperCase","body","clone","tooLarge","JSON","parse","text"],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ import type { PayloadHandler, PayloadRequest, SanitizedConfig } from 'payload';
2
+ /**
3
+ * Serves the OAuth protected resource metadata (RFC 9728) at `/api/mcp/oauth-protected-resource`.
4
+ * The OAuth challenge links here, so MCP clients find the authorization server without setup.
5
+ */
6
+ export declare const oauthProtectedResourceEndpoint: PayloadHandler;
7
+ /**
8
+ * Serves the same metadata for clients that ignore the challenge's link and only look at
9
+ * `/.well-known/oauth-protected-resource`. Mount it at the site root, e.g. in Next.js at
10
+ * `app/.well-known/oauth-protected-resource/[[...path]]/route.ts`:
11
+ *
12
+ * ```ts
13
+ * import config from '@payload-config'
14
+ * import { oauthProtectedResourceHandler } from '@payloadcms/plugin-mcp'
15
+ *
16
+ * export const GET = oauthProtectedResourceHandler(config)
17
+ * ```
18
+ */
19
+ export declare const oauthProtectedResourceHandler: (config: Promise<SanitizedConfig> | SanitizedConfig) => (request: Request) => Promise<Response>;
20
+ /**
21
+ * Answers an unauthenticated MCP request with a challenge linking to the protected resource
22
+ * metadata, which starts the client's OAuth flow.
23
+ */
24
+ export declare const oauthChallenge: ({ req }: {
25
+ req: PayloadRequest;
26
+ }) => Response;
27
+ //# sourceMappingURL=oauth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oauth.d.ts","sourceRoot":"","sources":["../../src/endpoint/oauth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAU9E;;;GAGG;AACH,eAAO,MAAM,8BAA8B,EAAE,cACuB,CAAA;AAEpE;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,6BAA6B,WAC/B,OAAO,CAAC,eAAe,CAAC,GAAG,eAAe,eACnC,OAAO,KAAG,OAAO,CAAC,QAAQ,CACuB,CAAA;AAEnE;;;GAGG;AACH,eAAO,MAAM,cAAc,YAAa;IAAE,GAAG,EAAE,cAAc,CAAA;CAAE,KAAG,QAM/D,CAAA"}
@@ -0,0 +1,61 @@
1
+ import { bearerAuthChallengeResponse, OAuthError, OAuthErrorCode } from '@modelcontextprotocol/server';
2
+ import { getPluginConfig } from '../utils/getPluginConfig.js';
3
+ /**
4
+ * Serves the OAuth protected resource metadata (RFC 9728) at `/api/mcp/oauth-protected-resource`.
5
+ * The OAuth challenge links here, so MCP clients find the authorization server without setup.
6
+ */ export const oauthProtectedResourceEndpoint = (req)=>getMetadataResponse({
7
+ config: req.payload.config,
8
+ url: req.url
9
+ });
10
+ /**
11
+ * Serves the same metadata for clients that ignore the challenge's link and only look at
12
+ * `/.well-known/oauth-protected-resource`. Mount it at the site root, e.g. in Next.js at
13
+ * `app/.well-known/oauth-protected-resource/[[...path]]/route.ts`:
14
+ *
15
+ * ```ts
16
+ * import config from '@payload-config'
17
+ * import { oauthProtectedResourceHandler } from '@payloadcms/plugin-mcp'
18
+ *
19
+ * export const GET = oauthProtectedResourceHandler(config)
20
+ * ```
21
+ */ export const oauthProtectedResourceHandler = (config)=>async (request)=>getMetadataResponse({
22
+ config: await config,
23
+ url: request.url
24
+ });
25
+ /**
26
+ * Answers an unauthenticated MCP request with a challenge linking to the protected resource
27
+ * metadata, which starts the client's OAuth flow.
28
+ */ export const oauthChallenge = ({ req })=>bearerAuthChallengeResponse(new OAuthError(OAuthErrorCode.InvalidToken, req.t('error:unauthorized')), {
29
+ resourceMetadataUrl: `${getMCPURL({
30
+ config: req.payload.config,
31
+ url: req.url
32
+ })}/oauth-protected-resource`
33
+ });
34
+ const getMCPURL = ({ config, url })=>new URL(`${config.routes.api}/mcp`, config.serverURL || url).href;
35
+ const getMetadataResponse = ({ config, url })=>{
36
+ const pluginConfig = getPluginConfig({
37
+ config
38
+ });
39
+ if (!pluginConfig.oauth) {
40
+ return new Response(null, {
41
+ status: 404
42
+ });
43
+ }
44
+ return Response.json({
45
+ authorization_servers: pluginConfig.oauth.authorizationServers,
46
+ bearer_methods_supported: [
47
+ 'header'
48
+ ],
49
+ resource: pluginConfig.oauth.resource ?? getMCPURL({
50
+ config,
51
+ url
52
+ })
53
+ }, // Public document, readable by browser-based MCP clients on any origin
54
+ {
55
+ headers: {
56
+ 'Access-Control-Allow-Origin': '*'
57
+ }
58
+ });
59
+ };
60
+
61
+ //# sourceMappingURL=oauth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/endpoint/oauth.ts"],"sourcesContent":["import type { PayloadHandler, PayloadRequest, SanitizedConfig } from 'payload'\n\nimport {\n bearerAuthChallengeResponse,\n OAuthError,\n OAuthErrorCode,\n} from '@modelcontextprotocol/server'\n\nimport { getPluginConfig } from '../utils/getPluginConfig.js'\n\n/**\n * Serves the OAuth protected resource metadata (RFC 9728) at `/api/mcp/oauth-protected-resource`.\n * The OAuth challenge links here, so MCP clients find the authorization server without setup.\n */\nexport const oauthProtectedResourceEndpoint: PayloadHandler = (req) =>\n getMetadataResponse({ config: req.payload.config, url: req.url! })\n\n/**\n * Serves the same metadata for clients that ignore the challenge's link and only look at\n * `/.well-known/oauth-protected-resource`. Mount it at the site root, e.g. in Next.js at\n * `app/.well-known/oauth-protected-resource/[[...path]]/route.ts`:\n *\n * ```ts\n * import config from '@payload-config'\n * import { oauthProtectedResourceHandler } from '@payloadcms/plugin-mcp'\n *\n * export const GET = oauthProtectedResourceHandler(config)\n * ```\n */\nexport const oauthProtectedResourceHandler =\n (config: Promise<SanitizedConfig> | SanitizedConfig) =>\n async (request: Request): Promise<Response> =>\n getMetadataResponse({ config: await config, url: request.url })\n\n/**\n * Answers an unauthenticated MCP request with a challenge linking to the protected resource\n * metadata, which starts the client's OAuth flow.\n */\nexport const oauthChallenge = ({ req }: { req: PayloadRequest }): Response =>\n bearerAuthChallengeResponse(\n new OAuthError(OAuthErrorCode.InvalidToken, req.t('error:unauthorized')),\n {\n resourceMetadataUrl: `${getMCPURL({ config: req.payload.config, url: req.url! })}/oauth-protected-resource`,\n },\n )\n\nconst getMCPURL = ({ config, url }: { config: SanitizedConfig; url: string }): string =>\n new URL(`${config.routes.api}/mcp`, config.serverURL || url).href\n\nconst getMetadataResponse = ({\n config,\n url,\n}: {\n config: SanitizedConfig\n url: string\n}): Response => {\n const pluginConfig = getPluginConfig({ config })\n\n if (!pluginConfig.oauth) {\n return new Response(null, { status: 404 })\n }\n\n return Response.json(\n {\n authorization_servers: pluginConfig.oauth.authorizationServers,\n bearer_methods_supported: ['header'],\n resource: pluginConfig.oauth.resource ?? getMCPURL({ config, url }),\n },\n // Public document, readable by browser-based MCP clients on any origin\n { headers: { 'Access-Control-Allow-Origin': '*' } },\n )\n}\n"],"names":["bearerAuthChallengeResponse","OAuthError","OAuthErrorCode","getPluginConfig","oauthProtectedResourceEndpoint","req","getMetadataResponse","config","payload","url","oauthProtectedResourceHandler","request","oauthChallenge","InvalidToken","t","resourceMetadataUrl","getMCPURL","URL","routes","api","serverURL","href","pluginConfig","oauth","Response","status","json","authorization_servers","authorizationServers","bearer_methods_supported","resource","headers"],"mappings":"AAEA,SACEA,2BAA2B,EAC3BC,UAAU,EACVC,cAAc,QACT,+BAA8B;AAErC,SAASC,eAAe,QAAQ,8BAA6B;AAE7D;;;CAGC,GACD,OAAO,MAAMC,iCAAiD,CAACC,MAC7DC,oBAAoB;QAAEC,QAAQF,IAAIG,OAAO,CAACD,MAAM;QAAEE,KAAKJ,IAAII,GAAG;IAAE,GAAE;AAEpE;;;;;;;;;;;CAWC,GACD,OAAO,MAAMC,gCACX,CAACH,SACD,OAAOI,UACLL,oBAAoB;YAAEC,QAAQ,MAAMA;YAAQE,KAAKE,QAAQF,GAAG;QAAC,GAAE;AAEnE;;;CAGC,GACD,OAAO,MAAMG,iBAAiB,CAAC,EAAEP,GAAG,EAA2B,GAC7DL,4BACE,IAAIC,WAAWC,eAAeW,YAAY,EAAER,IAAIS,CAAC,CAAC,wBAClD;QACEC,qBAAqB,GAAGC,UAAU;YAAET,QAAQF,IAAIG,OAAO,CAACD,MAAM;YAAEE,KAAKJ,IAAII,GAAG;QAAE,GAAG,yBAAyB,CAAC;IAC7G,GACD;AAEH,MAAMO,YAAY,CAAC,EAAET,MAAM,EAAEE,GAAG,EAA4C,GAC1E,IAAIQ,IAAI,GAAGV,OAAOW,MAAM,CAACC,GAAG,CAAC,IAAI,CAAC,EAAEZ,OAAOa,SAAS,IAAIX,KAAKY,IAAI;AAEnE,MAAMf,sBAAsB,CAAC,EAC3BC,MAAM,EACNE,GAAG,EAIJ;IACC,MAAMa,eAAenB,gBAAgB;QAAEI;IAAO;IAE9C,IAAI,CAACe,aAAaC,KAAK,EAAE;QACvB,OAAO,IAAIC,SAAS,MAAM;YAAEC,QAAQ;QAAI;IAC1C;IAEA,OAAOD,SAASE,IAAI,CAClB;QACEC,uBAAuBL,aAAaC,KAAK,CAACK,oBAAoB;QAC9DC,0BAA0B;YAAC;SAAS;QACpCC,UAAUR,aAAaC,KAAK,CAACO,QAAQ,IAAId,UAAU;YAAET;YAAQE;QAAI;IACnE,GACA,uEAAuE;IACvE;QAAEsB,SAAS;YAAE,+BAA+B;QAAI;IAAE;AAEtD"}
@@ -1,2 +1,2 @@
1
- export { AccessField } from '../components/AccessField/index.client.js';
1
+ export {};
2
2
  //# sourceMappingURL=client.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/exports/client.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,2CAA2C,CAAA"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/exports/client.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,CAAA"}