@payloadcms/plugin-mcp 4.0.0-internal.1f9ae9a → 4.0.0-internal.2fddfc0

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 (227) hide show
  1. package/dist/@types/assets.d.js +2 -0
  2. package/dist/@types/assets.d.js.map +1 -0
  3. package/dist/defaultAccess.d.ts +3 -0
  4. package/dist/defaultAccess.d.ts.map +1 -0
  5. package/dist/defaultAccess.js +3 -0
  6. package/dist/defaultAccess.js.map +1 -0
  7. package/dist/endpoint/access.d.ts +17 -5
  8. package/dist/endpoint/access.d.ts.map +1 -1
  9. package/dist/endpoint/access.js +82 -88
  10. package/dist/endpoint/access.js.map +1 -1
  11. package/dist/endpoint/index.d.ts.map +1 -1
  12. package/dist/endpoint/index.js +11 -0
  13. package/dist/endpoint/index.js.map +1 -1
  14. package/dist/exports/client.d.ts +1 -1
  15. package/dist/exports/client.d.ts.map +1 -1
  16. package/dist/exports/client.js +1 -1
  17. package/dist/exports/client.js.map +1 -1
  18. package/dist/exports/internal.d.ts +2 -0
  19. package/dist/exports/internal.d.ts.map +1 -0
  20. package/dist/exports/internal.js +3 -0
  21. package/dist/exports/internal.js.map +1 -0
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/index.js +13 -18
  24. package/dist/index.js.map +1 -1
  25. package/dist/mcp/buildMcpServer.d.ts.map +1 -1
  26. package/dist/mcp/buildMcpServer.js +102 -64
  27. package/dist/mcp/buildMcpServer.js.map +1 -1
  28. package/dist/mcp/builtin/collections/authTools.d.ts.map +1 -1
  29. package/dist/mcp/builtin/collections/authTools.js +44 -6
  30. package/dist/mcp/builtin/collections/authTools.js.map +1 -1
  31. package/dist/mcp/builtin/collections/countTool.d.ts +2 -0
  32. package/dist/mcp/builtin/collections/countTool.d.ts.map +1 -0
  33. package/dist/mcp/builtin/collections/countTool.js +69 -0
  34. package/dist/mcp/builtin/collections/countTool.js.map +1 -0
  35. package/dist/mcp/builtin/collections/countVersionsTool.d.ts +2 -0
  36. package/dist/mcp/builtin/collections/countVersionsTool.d.ts.map +1 -0
  37. package/dist/mcp/builtin/collections/countVersionsTool.js +65 -0
  38. package/dist/mcp/builtin/collections/countVersionsTool.js.map +1 -0
  39. package/dist/mcp/builtin/collections/createTool.d.ts +1 -1
  40. package/dist/mcp/builtin/collections/createTool.d.ts.map +1 -1
  41. package/dist/mcp/builtin/collections/createTool.js +38 -38
  42. package/dist/mcp/builtin/collections/createTool.js.map +1 -1
  43. package/dist/mcp/builtin/collections/deleteTool.d.ts +1 -1
  44. package/dist/mcp/builtin/collections/deleteTool.d.ts.map +1 -1
  45. package/dist/mcp/builtin/collections/deleteTool.js +14 -20
  46. package/dist/mcp/builtin/collections/deleteTool.js.map +1 -1
  47. package/dist/mcp/builtin/collections/duplicateTool.d.ts +2 -0
  48. package/dist/mcp/builtin/collections/duplicateTool.d.ts.map +1 -0
  49. package/dist/mcp/builtin/collections/duplicateTool.js +97 -0
  50. package/dist/mcp/builtin/collections/duplicateTool.js.map +1 -0
  51. package/dist/mcp/builtin/collections/findDistinctTool.d.ts +2 -0
  52. package/dist/mcp/builtin/collections/findDistinctTool.d.ts.map +1 -0
  53. package/dist/mcp/builtin/collections/findDistinctTool.js +93 -0
  54. package/dist/mcp/builtin/collections/findDistinctTool.js.map +1 -0
  55. package/dist/mcp/builtin/collections/findTool.d.ts +1 -1
  56. package/dist/mcp/builtin/collections/findTool.d.ts.map +1 -1
  57. package/dist/mcp/builtin/collections/findTool.js +49 -43
  58. package/dist/mcp/builtin/collections/findTool.js.map +1 -1
  59. package/dist/mcp/builtin/collections/findVersionByIDTool.d.ts +2 -0
  60. package/dist/mcp/builtin/collections/findVersionByIDTool.d.ts.map +1 -0
  61. package/dist/mcp/builtin/collections/findVersionByIDTool.js +84 -0
  62. package/dist/mcp/builtin/collections/findVersionByIDTool.js.map +1 -0
  63. package/dist/mcp/builtin/collections/findVersionsTool.d.ts +2 -0
  64. package/dist/mcp/builtin/collections/findVersionsTool.d.ts.map +1 -0
  65. package/dist/mcp/builtin/collections/findVersionsTool.js +99 -0
  66. package/dist/mcp/builtin/collections/findVersionsTool.js.map +1 -0
  67. package/dist/mcp/builtin/collections/formatCollectionError.d.ts +9 -0
  68. package/dist/mcp/builtin/collections/formatCollectionError.d.ts.map +1 -0
  69. package/dist/mcp/builtin/collections/formatCollectionError.js +60 -0
  70. package/dist/mcp/builtin/collections/formatCollectionError.js.map +1 -0
  71. package/dist/mcp/builtin/collections/getCollectionSchemaTool.d.ts +2 -0
  72. package/dist/mcp/builtin/collections/getCollectionSchemaTool.d.ts.map +1 -0
  73. package/dist/mcp/builtin/collections/getCollectionSchemaTool.js +47 -0
  74. package/dist/mcp/builtin/collections/getCollectionSchemaTool.js.map +1 -0
  75. package/dist/mcp/builtin/collections/restoreVersionTool.d.ts +2 -0
  76. package/dist/mcp/builtin/collections/restoreVersionTool.d.ts.map +1 -0
  77. package/dist/mcp/builtin/collections/restoreVersionTool.js +82 -0
  78. package/dist/mcp/builtin/collections/restoreVersionTool.js.map +1 -0
  79. package/dist/mcp/builtin/collections/updateTool.d.ts +1 -1
  80. package/dist/mcp/builtin/collections/updateTool.d.ts.map +1 -1
  81. package/dist/mcp/builtin/collections/updateTool.js +87 -82
  82. package/dist/mcp/builtin/collections/updateTool.js.map +1 -1
  83. package/dist/mcp/builtin/getConfigInfoTool.d.ts +2 -0
  84. package/dist/mcp/builtin/getConfigInfoTool.d.ts.map +1 -0
  85. package/dist/mcp/builtin/getConfigInfoTool.js +71 -0
  86. package/dist/mcp/builtin/getConfigInfoTool.js.map +1 -0
  87. package/dist/mcp/builtin/globals/countVersionsTool.d.ts +2 -0
  88. package/dist/mcp/builtin/globals/countVersionsTool.d.ts.map +1 -0
  89. package/dist/mcp/builtin/globals/countVersionsTool.js +65 -0
  90. package/dist/mcp/builtin/globals/countVersionsTool.js.map +1 -0
  91. package/dist/mcp/builtin/globals/findTool.d.ts.map +1 -1
  92. package/dist/mcp/builtin/globals/findTool.js +18 -21
  93. package/dist/mcp/builtin/globals/findTool.js.map +1 -1
  94. package/dist/mcp/builtin/globals/findVersionByIDTool.d.ts +2 -0
  95. package/dist/mcp/builtin/globals/findVersionByIDTool.d.ts.map +1 -0
  96. package/dist/mcp/builtin/globals/findVersionByIDTool.js +80 -0
  97. package/dist/mcp/builtin/globals/findVersionByIDTool.js.map +1 -0
  98. package/dist/mcp/builtin/globals/findVersionsTool.d.ts +2 -0
  99. package/dist/mcp/builtin/globals/findVersionsTool.d.ts.map +1 -0
  100. package/dist/mcp/builtin/globals/findVersionsTool.js +95 -0
  101. package/dist/mcp/builtin/globals/findVersionsTool.js.map +1 -0
  102. package/dist/mcp/builtin/globals/getGlobalSchemaTool.d.ts +2 -0
  103. package/dist/mcp/builtin/globals/getGlobalSchemaTool.d.ts.map +1 -0
  104. package/dist/mcp/builtin/globals/getGlobalSchemaTool.js +47 -0
  105. package/dist/mcp/builtin/globals/getGlobalSchemaTool.js.map +1 -0
  106. package/dist/mcp/builtin/globals/restoreVersionTool.d.ts +2 -0
  107. package/dist/mcp/builtin/globals/restoreVersionTool.d.ts.map +1 -0
  108. package/dist/mcp/builtin/globals/restoreVersionTool.js +78 -0
  109. package/dist/mcp/builtin/globals/restoreVersionTool.js.map +1 -0
  110. package/dist/mcp/builtin/globals/updateTool.d.ts.map +1 -1
  111. package/dist/mcp/builtin/globals/updateTool.js +31 -36
  112. package/dist/mcp/builtin/globals/updateTool.js.map +1 -1
  113. package/dist/mcp/builtin/validateEntityData.d.ts +14 -0
  114. package/dist/mcp/builtin/validateEntityData.d.ts.map +1 -0
  115. package/dist/mcp/builtin/validateEntityData.js +82 -0
  116. package/dist/mcp/builtin/validateEntityData.js.map +1 -0
  117. package/dist/mcp/builtinTools.d.ts +144 -19
  118. package/dist/mcp/builtinTools.d.ts.map +1 -1
  119. package/dist/mcp/builtinTools.js +119 -20
  120. package/dist/mcp/builtinTools.js.map +1 -1
  121. package/dist/mcp/sanitizeMCPConfig.d.ts +0 -1
  122. package/dist/mcp/sanitizeMCPConfig.d.ts.map +1 -1
  123. package/dist/mcp/sanitizeMCPConfig.js +120 -58
  124. package/dist/mcp/sanitizeMCPConfig.js.map +1 -1
  125. package/dist/stdio.d.ts +3 -2
  126. package/dist/stdio.d.ts.map +1 -1
  127. package/dist/stdio.js +27 -8
  128. package/dist/stdio.js.map +1 -1
  129. package/dist/types.d.ts +62 -108
  130. package/dist/types.d.ts.map +1 -1
  131. package/dist/types.js +4 -4
  132. package/dist/types.js.map +1 -1
  133. package/dist/utils/getPluginConfig.d.ts +1 -1
  134. package/dist/utils/getPluginConfig.js +1 -1
  135. package/dist/utils/getPluginConfig.js.map +1 -1
  136. package/dist/utils/schemaConversion/getEntityInputSchema.d.ts +11 -0
  137. package/dist/utils/schemaConversion/getEntityInputSchema.d.ts.map +1 -0
  138. package/dist/utils/schemaConversion/getEntityInputSchema.js +34 -0
  139. package/dist/utils/schemaConversion/getEntityInputSchema.js.map +1 -0
  140. package/dist/utils/schemaConversion/sanitizeEntitySchema.d.ts +15 -0
  141. package/dist/utils/schemaConversion/sanitizeEntitySchema.d.ts.map +1 -0
  142. package/dist/utils/schemaConversion/sanitizeEntitySchema.js +464 -0
  143. package/dist/utils/schemaConversion/sanitizeEntitySchema.js.map +1 -0
  144. package/dist/utils/schemaConversion/sanitizeEntitySchema.spec.js +158 -0
  145. package/dist/utils/schemaConversion/sanitizeEntitySchema.spec.js.map +1 -0
  146. package/dist/utils/whereSchema.d.ts +9 -0
  147. package/dist/utils/whereSchema.d.ts.map +1 -0
  148. package/dist/utils/whereSchema.js +13 -0
  149. package/dist/utils/whereSchema.js.map +1 -0
  150. package/package.json +8 -11
  151. package/src/@types/assets.d.ts +3 -0
  152. package/src/defaultAccess.ts +3 -0
  153. package/src/endpoint/access.ts +88 -101
  154. package/src/endpoint/index.ts +14 -1
  155. package/src/exports/client.ts +2 -1
  156. package/src/exports/internal.ts +1 -0
  157. package/src/index.ts +8 -16
  158. package/src/mcp/buildMcpServer.ts +130 -90
  159. package/src/mcp/builtin/collections/authTools.ts +45 -9
  160. package/src/mcp/builtin/collections/countTool.ts +74 -0
  161. package/src/mcp/builtin/collections/countVersionsTool.ts +70 -0
  162. package/src/mcp/builtin/collections/createTool.ts +55 -59
  163. package/src/mcp/builtin/collections/deleteTool.ts +19 -16
  164. package/src/mcp/builtin/collections/duplicateTool.ts +135 -0
  165. package/src/mcp/builtin/collections/findDistinctTool.ts +120 -0
  166. package/src/mcp/builtin/collections/findTool.ts +63 -33
  167. package/src/mcp/builtin/collections/findVersionByIDTool.ts +110 -0
  168. package/src/mcp/builtin/collections/findVersionsTool.ts +155 -0
  169. package/src/mcp/builtin/collections/formatCollectionError.ts +84 -0
  170. package/src/mcp/builtin/collections/getCollectionSchemaTool.ts +46 -0
  171. package/src/mcp/builtin/collections/restoreVersionTool.ts +108 -0
  172. package/src/mcp/builtin/collections/updateTool.ts +111 -105
  173. package/src/mcp/builtin/getConfigInfoTool.ts +69 -0
  174. package/src/mcp/builtin/globals/countVersionsTool.ts +69 -0
  175. package/src/mcp/builtin/globals/findTool.ts +26 -17
  176. package/src/mcp/builtin/globals/findVersionByIDTool.ts +104 -0
  177. package/src/mcp/builtin/globals/findVersionsTool.ts +148 -0
  178. package/src/mcp/builtin/globals/getGlobalSchemaTool.ts +41 -0
  179. package/src/mcp/builtin/globals/restoreVersionTool.ts +100 -0
  180. package/src/mcp/builtin/globals/updateTool.ts +50 -53
  181. package/src/mcp/builtin/validateEntityData.ts +132 -0
  182. package/src/mcp/builtinTools.ts +111 -41
  183. package/src/mcp/sanitizeMCPConfig.ts +116 -78
  184. package/src/stdio.ts +23 -8
  185. package/src/types.ts +77 -112
  186. package/src/utils/getPluginConfig.ts +1 -1
  187. package/src/utils/schemaConversion/getEntityInputSchema.ts +78 -0
  188. package/src/utils/schemaConversion/sanitizeEntitySchema.spec.ts +103 -0
  189. package/src/utils/schemaConversion/sanitizeEntitySchema.ts +529 -0
  190. package/src/utils/whereSchema.ts +24 -0
  191. package/dist/collection/getAccessField.d.ts +0 -12
  192. package/dist/collection/getAccessField.d.ts.map +0 -1
  193. package/dist/collection/getAccessField.js +0 -57
  194. package/dist/collection/getAccessField.js.map +0 -1
  195. package/dist/collection/index.d.ts +0 -6
  196. package/dist/collection/index.d.ts.map +0 -1
  197. package/dist/collection/index.js +0 -59
  198. package/dist/collection/index.js.map +0 -1
  199. package/dist/components/AccessField/index.client.d.ts +0 -10
  200. package/dist/components/AccessField/index.client.d.ts.map +0 -1
  201. package/dist/components/AccessField/index.client.js +0 -305
  202. package/dist/components/AccessField/index.client.js.map +0 -1
  203. package/dist/components/AccessField/index.css +0 -93
  204. package/dist/utils/schemaConversion/prepareCollectionSchema.d.ts +0 -7
  205. package/dist/utils/schemaConversion/prepareCollectionSchema.d.ts.map +0 -1
  206. package/dist/utils/schemaConversion/prepareCollectionSchema.js +0 -37
  207. package/dist/utils/schemaConversion/prepareCollectionSchema.js.map +0 -1
  208. package/dist/utils/schemaConversion/sanitizeJsonSchema.d.ts +0 -13
  209. package/dist/utils/schemaConversion/sanitizeJsonSchema.d.ts.map +0 -1
  210. package/dist/utils/schemaConversion/sanitizeJsonSchema.js +0 -56
  211. package/dist/utils/schemaConversion/sanitizeJsonSchema.js.map +0 -1
  212. package/dist/utils/schemaConversion/simplifyRelationshipFields.d.ts +0 -20
  213. package/dist/utils/schemaConversion/simplifyRelationshipFields.d.ts.map +0 -1
  214. package/dist/utils/schemaConversion/simplifyRelationshipFields.js +0 -56
  215. package/dist/utils/schemaConversion/simplifyRelationshipFields.js.map +0 -1
  216. package/dist/utils/schemaConversion/transformPointFields.d.ts +0 -3
  217. package/dist/utils/schemaConversion/transformPointFields.d.ts.map +0 -1
  218. package/dist/utils/schemaConversion/transformPointFields.js +0 -57
  219. package/dist/utils/schemaConversion/transformPointFields.js.map +0 -1
  220. package/src/collection/getAccessField.ts +0 -64
  221. package/src/collection/index.ts +0 -63
  222. package/src/components/AccessField/index.client.tsx +0 -344
  223. package/src/components/AccessField/index.css +0 -93
  224. package/src/utils/schemaConversion/prepareCollectionSchema.ts +0 -39
  225. package/src/utils/schemaConversion/sanitizeJsonSchema.ts +0 -62
  226. package/src/utils/schemaConversion/simplifyRelationshipFields.ts +0 -70
  227. package/src/utils/schemaConversion/transformPointFields.ts +0 -56
@@ -0,0 +1,158 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { sanitizeEntitySchema } from './sanitizeEntitySchema.js';
3
+ describe('sanitizeEntitySchema', ()=>{
4
+ it('keeps a Lexical node union strict (oneOf) while simplifying relationship values to IDs', ()=>{
5
+ // Shaped like the schema the MCP server prepares for a collection with a Lexical richText field:
6
+ // a `$defs` node union (a `oneOf` of node shapes) where a relationship node's `value` is either
7
+ // an ID or a `$ref` to the populated related collection.
8
+ const standalone = {
9
+ type: 'object',
10
+ $defs: {
11
+ LexicalNodes_ABCDEF12: {
12
+ oneOf: [
13
+ {
14
+ type: 'object',
15
+ additionalProperties: false,
16
+ properties: {
17
+ type: {
18
+ const: 'paragraph'
19
+ }
20
+ },
21
+ required: [
22
+ 'type'
23
+ ]
24
+ },
25
+ {
26
+ type: 'object',
27
+ additionalProperties: false,
28
+ properties: {
29
+ type: {
30
+ const: 'relationship'
31
+ },
32
+ value: {
33
+ oneOf: [
34
+ {
35
+ type: 'string'
36
+ },
37
+ {
38
+ $ref: '#/$defs/posts'
39
+ }
40
+ ]
41
+ }
42
+ },
43
+ required: [
44
+ 'type'
45
+ ]
46
+ }
47
+ ]
48
+ },
49
+ posts: {
50
+ type: 'object',
51
+ additionalProperties: false,
52
+ properties: {
53
+ id: {
54
+ type: 'string'
55
+ },
56
+ title: {
57
+ type: 'string'
58
+ }
59
+ }
60
+ }
61
+ },
62
+ properties: {
63
+ id: {
64
+ type: 'string'
65
+ },
66
+ content: {
67
+ type: 'object',
68
+ properties: {
69
+ root: {
70
+ type: 'object',
71
+ properties: {
72
+ children: {
73
+ type: 'array',
74
+ items: {
75
+ $ref: '#/$defs/LexicalNodes_ABCDEF12'
76
+ }
77
+ }
78
+ }
79
+ }
80
+ }
81
+ }
82
+ }
83
+ };
84
+ expect(sanitizeEntitySchema(standalone)).toStrictEqual({
85
+ type: 'object',
86
+ $defs: {
87
+ // The node union is renamed to a short, readable `node`, and stays a strict discriminated
88
+ // `oneOf` - not loosened to `anyOf`...
89
+ node: {
90
+ oneOf: [
91
+ {
92
+ type: 'object',
93
+ additionalProperties: false,
94
+ properties: {
95
+ type: {
96
+ const: 'paragraph'
97
+ }
98
+ },
99
+ required: [
100
+ 'type'
101
+ ]
102
+ },
103
+ {
104
+ type: 'object',
105
+ additionalProperties: false,
106
+ properties: {
107
+ type: {
108
+ const: 'relationship'
109
+ },
110
+ // ...while the relationship `value` is simplified to a bare ID (the populated-doc `$ref` is dropped).
111
+ value: {
112
+ type: 'string',
113
+ description: 'The ID of the related "posts" document.'
114
+ }
115
+ },
116
+ required: [
117
+ 'type'
118
+ ]
119
+ }
120
+ ]
121
+ },
122
+ posts: {
123
+ type: 'object',
124
+ additionalProperties: false,
125
+ properties: {
126
+ id: {
127
+ type: 'string'
128
+ },
129
+ title: {
130
+ type: 'string'
131
+ }
132
+ }
133
+ }
134
+ },
135
+ properties: {
136
+ // `id` is dropped - it's a Payload-managed field MCP clients never set.
137
+ content: {
138
+ type: 'object',
139
+ properties: {
140
+ root: {
141
+ type: 'object',
142
+ properties: {
143
+ children: {
144
+ type: 'array',
145
+ items: {
146
+ $ref: '#/$defs/node'
147
+ }
148
+ }
149
+ }
150
+ }
151
+ }
152
+ }
153
+ }
154
+ });
155
+ });
156
+ });
157
+
158
+ //# sourceMappingURL=sanitizeEntitySchema.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/utils/schemaConversion/sanitizeEntitySchema.spec.ts"],"sourcesContent":["import { describe, expect, it } from 'vitest'\n\nimport type { JsonSchemaType } from '../../types.js'\n\nimport { sanitizeEntitySchema } from './sanitizeEntitySchema.js'\n\ndescribe('sanitizeEntitySchema', () => {\n it('keeps a Lexical node union strict (oneOf) while simplifying relationship values to IDs', () => {\n // Shaped like the schema the MCP server prepares for a collection with a Lexical richText field:\n // a `$defs` node union (a `oneOf` of node shapes) where a relationship node's `value` is either\n // an ID or a `$ref` to the populated related collection.\n const standalone: JsonSchemaType = {\n type: 'object',\n $defs: {\n LexicalNodes_ABCDEF12: {\n oneOf: [\n {\n type: 'object',\n additionalProperties: false,\n properties: { type: { const: 'paragraph' } },\n required: ['type'],\n },\n {\n type: 'object',\n additionalProperties: false,\n properties: {\n type: { const: 'relationship' },\n value: { oneOf: [{ type: 'string' }, { $ref: '#/$defs/posts' }] },\n },\n required: ['type'],\n },\n ],\n },\n posts: {\n type: 'object',\n additionalProperties: false,\n properties: { id: { type: 'string' }, title: { type: 'string' } },\n },\n },\n properties: {\n id: { type: 'string' },\n content: {\n type: 'object',\n properties: {\n root: {\n type: 'object',\n properties: {\n children: { type: 'array', items: { $ref: '#/$defs/LexicalNodes_ABCDEF12' } },\n },\n },\n },\n },\n },\n }\n\n expect(sanitizeEntitySchema(standalone)).toStrictEqual({\n type: 'object',\n $defs: {\n // The node union is renamed to a short, readable `node`, and stays a strict discriminated\n // `oneOf` - not loosened to `anyOf`...\n node: {\n oneOf: [\n {\n type: 'object',\n additionalProperties: false,\n properties: { type: { const: 'paragraph' } },\n required: ['type'],\n },\n {\n type: 'object',\n additionalProperties: false,\n properties: {\n type: { const: 'relationship' },\n // ...while the relationship `value` is simplified to a bare ID (the populated-doc `$ref` is dropped).\n value: { type: 'string', description: 'The ID of the related \"posts\" document.' },\n },\n required: ['type'],\n },\n ],\n },\n posts: {\n type: 'object',\n additionalProperties: false,\n properties: { id: { type: 'string' }, title: { type: 'string' } },\n },\n },\n properties: {\n // `id` is dropped - it's a Payload-managed field MCP clients never set.\n content: {\n type: 'object',\n properties: {\n root: {\n type: 'object',\n properties: {\n children: { type: 'array', items: { $ref: '#/$defs/node' } },\n },\n },\n },\n },\n },\n })\n })\n})\n"],"names":["describe","expect","it","sanitizeEntitySchema","standalone","type","$defs","LexicalNodes_ABCDEF12","oneOf","additionalProperties","properties","const","required","value","$ref","posts","id","title","content","root","children","items","toStrictEqual","node","description"],"mappings":"AAAA,SAASA,QAAQ,EAAEC,MAAM,EAAEC,EAAE,QAAQ,SAAQ;AAI7C,SAASC,oBAAoB,QAAQ,4BAA2B;AAEhEH,SAAS,wBAAwB;IAC/BE,GAAG,0FAA0F;QAC3F,iGAAiG;QACjG,gGAAgG;QAChG,yDAAyD;QACzD,MAAME,aAA6B;YACjCC,MAAM;YACNC,OAAO;gBACLC,uBAAuB;oBACrBC,OAAO;wBACL;4BACEH,MAAM;4BACNI,sBAAsB;4BACtBC,YAAY;gCAAEL,MAAM;oCAAEM,OAAO;gCAAY;4BAAE;4BAC3CC,UAAU;gCAAC;6BAAO;wBACpB;wBACA;4BACEP,MAAM;4BACNI,sBAAsB;4BACtBC,YAAY;gCACVL,MAAM;oCAAEM,OAAO;gCAAe;gCAC9BE,OAAO;oCAAEL,OAAO;wCAAC;4CAAEH,MAAM;wCAAS;wCAAG;4CAAES,MAAM;wCAAgB;qCAAE;gCAAC;4BAClE;4BACAF,UAAU;gCAAC;6BAAO;wBACpB;qBACD;gBACH;gBACAG,OAAO;oBACLV,MAAM;oBACNI,sBAAsB;oBACtBC,YAAY;wBAAEM,IAAI;4BAAEX,MAAM;wBAAS;wBAAGY,OAAO;4BAAEZ,MAAM;wBAAS;oBAAE;gBAClE;YACF;YACAK,YAAY;gBACVM,IAAI;oBAAEX,MAAM;gBAAS;gBACrBa,SAAS;oBACPb,MAAM;oBACNK,YAAY;wBACVS,MAAM;4BACJd,MAAM;4BACNK,YAAY;gCACVU,UAAU;oCAAEf,MAAM;oCAASgB,OAAO;wCAAEP,MAAM;oCAAgC;gCAAE;4BAC9E;wBACF;oBACF;gBACF;YACF;QACF;QAEAb,OAAOE,qBAAqBC,aAAakB,aAAa,CAAC;YACrDjB,MAAM;YACNC,OAAO;gBACL,0FAA0F;gBAC1F,uCAAuC;gBACvCiB,MAAM;oBACJf,OAAO;wBACL;4BACEH,MAAM;4BACNI,sBAAsB;4BACtBC,YAAY;gCAAEL,MAAM;oCAAEM,OAAO;gCAAY;4BAAE;4BAC3CC,UAAU;gCAAC;6BAAO;wBACpB;wBACA;4BACEP,MAAM;4BACNI,sBAAsB;4BACtBC,YAAY;gCACVL,MAAM;oCAAEM,OAAO;gCAAe;gCAC9B,sGAAsG;gCACtGE,OAAO;oCAAER,MAAM;oCAAUmB,aAAa;gCAA0C;4BAClF;4BACAZ,UAAU;gCAAC;6BAAO;wBACpB;qBACD;gBACH;gBACAG,OAAO;oBACLV,MAAM;oBACNI,sBAAsB;oBACtBC,YAAY;wBAAEM,IAAI;4BAAEX,MAAM;wBAAS;wBAAGY,OAAO;4BAAEZ,MAAM;wBAAS;oBAAE;gBAClE;YACF;YACAK,YAAY;gBACV,wEAAwE;gBACxEQ,SAAS;oBACPb,MAAM;oBACNK,YAAY;wBACVS,MAAM;4BACJd,MAAM;4BACNK,YAAY;gCACVU,UAAU;oCAAEf,MAAM;oCAASgB,OAAO;wCAAEP,MAAM;oCAAe;gCAAE;4BAC7D;wBACF;oBACF;gBACF;YACF;QACF;IACF;AACF"}
@@ -0,0 +1,9 @@
1
+ import type { Where } from 'payload';
2
+ import { z } from 'zod';
3
+ /**
4
+ * - Validates the `where` input of collection tools against Payload's `Where` shape
5
+ * - Field keys map to operator objects restricted to `validOperators`
6
+ * - `and` / `or` nest recursively
7
+ */
8
+ export declare const whereSchema: z.ZodType<Where>;
9
+ //# sourceMappingURL=whereSchema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"whereSchema.d.ts","sourceRoot":"","sources":["../../src/utils/whereSchema.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAGpC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAMvB;;;;GAIG;AACH,eAAO,MAAM,WAAW,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CASqD,CAAA"}
@@ -0,0 +1,13 @@
1
+ import { validOperators } from 'payload/shared';
2
+ import { z } from 'zod';
3
+ const whereFieldSchema = z.partialRecord(z.enum(validOperators), z.unknown()).describe('Field query operators');
4
+ /**
5
+ * - Validates the `where` input of collection tools against Payload's `Where` shape
6
+ * - Field keys map to operator objects restricted to `validOperators`
7
+ * - `and` / `or` nest recursively
8
+ */ export const whereSchema = z.lazy(()=>z.object({
9
+ and: z.array(whereSchema).optional(),
10
+ or: z.array(whereSchema).optional()
11
+ }).catchall(whereFieldSchema)).describe('Where clause using field names with Payload query operators, plus and/or groups');
12
+
13
+ //# sourceMappingURL=whereSchema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/utils/whereSchema.ts"],"sourcesContent":["import type { Where } from 'payload'\n\nimport { validOperators } from 'payload/shared'\nimport { z } from 'zod'\n\nconst whereFieldSchema = z\n .partialRecord(z.enum(validOperators), z.unknown())\n .describe('Field query operators')\n\n/**\n * - Validates the `where` input of collection tools against Payload's `Where` shape\n * - Field keys map to operator objects restricted to `validOperators`\n * - `and` / `or` nest recursively\n */\nexport const whereSchema: z.ZodType<Where> = z\n .lazy(() =>\n z\n .object({\n and: z.array(whereSchema).optional(),\n or: z.array(whereSchema).optional(),\n })\n .catchall(whereFieldSchema),\n )\n .describe('Where clause using field names with Payload query operators, plus and/or groups')\n"],"names":["validOperators","z","whereFieldSchema","partialRecord","enum","unknown","describe","whereSchema","lazy","object","and","array","optional","or","catchall"],"mappings":"AAEA,SAASA,cAAc,QAAQ,iBAAgB;AAC/C,SAASC,CAAC,QAAQ,MAAK;AAEvB,MAAMC,mBAAmBD,EACtBE,aAAa,CAACF,EAAEG,IAAI,CAACJ,iBAAiBC,EAAEI,OAAO,IAC/CC,QAAQ,CAAC;AAEZ;;;;CAIC,GACD,OAAO,MAAMC,cAAgCN,EAC1CO,IAAI,CAAC,IACJP,EACGQ,MAAM,CAAC;QACNC,KAAKT,EAAEU,KAAK,CAACJ,aAAaK,QAAQ;QAClCC,IAAIZ,EAAEU,KAAK,CAACJ,aAAaK,QAAQ;IACnC,GACCE,QAAQ,CAACZ,mBAEbI,QAAQ,CAAC,mFAAkF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@payloadcms/plugin-mcp",
3
- "version": "4.0.0-internal.1f9ae9a",
3
+ "version": "4.0.0-internal.2fddfc0",
4
4
  "description": "MCP (Model Context Protocol) capabilities with Payload",
5
5
  "keywords": [
6
6
  "plugin",
@@ -21,9 +21,6 @@
21
21
  "url": "https://payloadcms.com"
22
22
  }
23
23
  ],
24
- "sideEffects": [
25
- "*.css"
26
- ],
27
24
  "type": "module",
28
25
  "exports": {
29
26
  ".": {
@@ -40,6 +37,11 @@
40
37
  "import": "./dist/stdio.js",
41
38
  "types": "./dist/stdio.d.ts",
42
39
  "default": "./dist/stdio.js"
40
+ },
41
+ "./internal": {
42
+ "import": "./dist/internal.js",
43
+ "types": "./dist/internal.d.ts",
44
+ "default": "./dist/internal.js"
43
45
  }
44
46
  },
45
47
  "main": "./dist/index.js",
@@ -59,16 +61,11 @@
59
61
  "zod": "^4.0.0"
60
62
  },
61
63
  "devDependencies": {
62
- "@types/react": "19.2.14",
63
- "react": "^19.0.1 || ^19.1.2 || ^19.2.1",
64
64
  "@payloadcms/eslint-config": "3.28.0",
65
- "payload": "4.0.0-internal.1f9ae9a",
66
- "@payloadcms/ui": "4.0.0-internal.1f9ae9a"
65
+ "payload": "4.0.0-internal.2fddfc0"
67
66
  },
68
67
  "peerDependencies": {
69
- "react": "^19.0.1 || ^19.1.2 || ^19.2.1",
70
- "@payloadcms/ui": "4.0.0-internal.1f9ae9a",
71
- "payload": "4.0.0-internal.1f9ae9a"
68
+ "payload": "4.0.0-internal.2fddfc0"
72
69
  },
73
70
  "//deps_notes": {
74
71
  "zod": "zod is a hard dependency of @modelcontextprotocol/server, thus we can safely use it without it impacting bundle size. Make extra sure the zod version here matches exactly what's defined in the dependencies of @modelcontextprotocol/server to avoid duplicate versions being installed.",
@@ -0,0 +1,3 @@
1
+ declare module '*.css'
2
+
3
+ declare module '*.scss'
@@ -0,0 +1,3 @@
1
+ import type { MCPAccessArgs } from './types.js'
2
+
3
+ export const defaultAccess = ({ req }: MCPAccessArgs): boolean => Boolean(req.user)
@@ -1,132 +1,119 @@
1
- import type { DefaultDocumentIDType, PayloadRequest, TypedUser } from 'payload'
1
+ import type { PayloadRequest, SanitizedPermissions } from 'payload'
2
2
 
3
- import crypto from 'crypto'
4
- import { UnauthorizedError } from 'payload'
3
+ import { getAccessResults, UnauthorizedError } from 'payload'
5
4
 
6
- import type { AuthorizedMCP, MCPAPIKeysDoc } from '../types.js'
5
+ import type { AuthorizedMCP, MCPItem } from '../types.js'
7
6
 
8
- import { getLogger } from '../utils/getLogger.js'
9
7
  import { getPluginConfig } from '../utils/getPluginConfig.js'
10
8
 
9
+ export type GetAuthorizedMCPArgs = {
10
+ overrideAccess: boolean
11
+ req: PayloadRequest
12
+ }
13
+
11
14
  /**
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.
15
+ * Resolves the MCP caller and returns the MCP surface authorized for that request.
16
+ *
17
+ * Authorization has two layers:
18
+ * 1. Payload collection/global permissions determine whether built-in operation tools are shown.
19
+ * 2. MCP `access` callbacks can further hide any configured tool, prompt, or resource.
20
+ *
21
+ * Like Payload core operations, `overrideAccess` skips both layers.
14
22
  */
15
- export const getAuthorizedMCP: (args: { req: PayloadRequest }) => Promise<AuthorizedMCP> = async ({
23
+ export const getAuthorizedMCP: (args: GetAuthorizedMCPArgs) => Promise<AuthorizedMCP> = async ({
24
+ overrideAccess,
16
25
  req,
17
26
  }) => {
18
- const logger = getLogger({ payload: req.payload })
19
27
  const pluginConfig = getPluginConfig({ config: req.payload.config })
20
28
 
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.key] !== false
29
- case 'globalTool':
30
- return apiKeyDoc.access.globals?.[item.globalSlug]?.[item.key] !== false
31
- case 'prompt':
32
- return apiKeyDoc.access.prompts?.[item.key] !== false
33
- case 'resource':
34
- return apiKeyDoc.access.resources?.[item.key] !== false
35
- case 'tool':
36
- return apiKeyDoc.access.tools?.[item.key] !== 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),
29
+ if (pluginConfig.overrideGetAuthorizedMCP) {
30
+ return await pluginConfig.overrideGetAuthorizedMCP({
31
+ overrideAccess,
48
32
  pluginConfig,
49
33
  req,
50
34
  })
51
35
  }
52
36
 
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
- })
37
+ if (req.headers) {
38
+ const headers = new Headers(req.headers)
39
+ const hasAuthorization = headers.has('Authorization')
40
+
41
+ headers.set('DisableAutologin', 'true')
42
+ req.user = (await req.payload.auth({ headers, req })).user
43
+
44
+ if (hasAuthorization && !req.user) {
45
+ throw new UnauthorizedError(req.t)
46
+ }
61
47
  }
62
48
 
63
- return buildAuthorized(await getAPIKeyDoc({ logger, pluginConfig, req }))
49
+ return {
50
+ items: await filterMCPItems({
51
+ items: pluginConfig.items,
52
+ overrideAccess,
53
+ req,
54
+ }),
55
+ overrideAccess,
56
+ user: req.user,
57
+ }
64
58
  }
65
59
 
66
- const getAPIKeyDoc = async ({
67
- logger,
68
- overrideApiKey,
69
- pluginConfig,
60
+ export const filterMCPItems = async ({
61
+ items,
62
+ overrideAccess,
70
63
  req,
71
64
  }: {
72
- logger: ReturnType<typeof getLogger>
73
- overrideApiKey?: string
74
- pluginConfig: ReturnType<typeof getPluginConfig>
65
+ items: MCPItem[]
66
+ overrideAccess: boolean
75
67
  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()
68
+ }): Promise<MCPItem[]> => {
69
+ // Match Payload core: overrideAccess bypasses access evaluation instead of
70
+ // forcing each access function to return true.
71
+ if (overrideAccess) {
72
+ return items
102
73
  }
103
74
 
104
- logger.info('API Key is valid')
75
+ const authorizedItems: MCPItem[] = []
105
76
 
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)
77
+ const permissions = await getAccessResults({ req })
111
78
 
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()
79
+ for (const item of items) {
80
+ if (!(await checkItemAccess({ item, permissions, req }))) {
81
+ continue
82
+ }
83
+ authorizedItems.push(item)
122
84
  }
123
85
 
124
- return {
125
- ...doc,
126
- user: {
127
- ...user,
128
- _strategy: 'mcp-api-key' as const,
129
- collection: pluginConfig.userCollection,
130
- },
86
+ return authorizedItems
87
+ }
88
+
89
+ /**
90
+ * Runs MCP item access callbacks
91
+ */
92
+ const checkItemAccess = async ({
93
+ item,
94
+ permissions,
95
+ req,
96
+ }: {
97
+ item: MCPItem
98
+ permissions?: SanitizedPermissions
99
+ req: PayloadRequest
100
+ }): Promise<boolean> => {
101
+ switch (item.type) {
102
+ case 'collectionTool':
103
+ return (
104
+ !item.tool.access ||
105
+ (await item.tool.access({ collectionSlug: item.collectionSlug, permissions, req }))
106
+ )
107
+ case 'globalTool':
108
+ return (
109
+ !item.tool.access ||
110
+ (await item.tool.access({ globalSlug: item.globalSlug, permissions, req }))
111
+ )
112
+ case 'prompt':
113
+ return !item.prompt.access || (await item.prompt.access({ permissions, req }))
114
+ case 'resource':
115
+ return !item.resource.access || (await item.resource.access({ permissions, req }))
116
+ case 'tool':
117
+ return !item.tool.access || (await item.tool.access({ permissions, req }))
131
118
  }
132
119
  }
@@ -13,7 +13,20 @@ export const mcpEndpoint: PayloadHandler = async (req) => {
13
13
  req.payloadAPI = 'MCP' as const
14
14
 
15
15
  const pluginConfig = getPluginConfig({ config: req.payload.config })
16
- const authorizedMCP = await getAuthorizedMCP({ req })
16
+ const overrideAccessParam = new URL(req.url).searchParams.get('overrideAccess')
17
+
18
+ if (overrideAccessParam !== null && process.env.NODE_ENV !== 'development') {
19
+ throw new APIError('MCP overrideAccess is only available in development.', 400)
20
+ }
21
+
22
+ let overrideAccess = false
23
+ if (overrideAccessParam === 'true') {
24
+ overrideAccess = true
25
+ } else if (overrideAccessParam !== null && overrideAccessParam !== 'false') {
26
+ throw new APIError('MCP overrideAccess must be "true" or "false".', 400)
27
+ }
28
+
29
+ const authorizedMCP = await getAuthorizedMCP({ overrideAccess, req })
17
30
 
18
31
  const server = buildMcpServer({ authorizedMCP, pluginConfig, req })
19
32
 
@@ -1,2 +1,3 @@
1
1
  'use client'
2
- export { AccessField } from '../components/AccessField/index.client.js'
2
+
3
+ export {}
@@ -0,0 +1 @@
1
+ export { filterMCPItems, getAuthorizedMCP } from '../endpoint/access.js'
package/src/index.ts CHANGED
@@ -1,8 +1,7 @@
1
- import { defaultUserCollection, definePlugin } from 'payload'
1
+ import { definePlugin } from 'payload'
2
2
 
3
3
  import type { AuthorizedMCP, MCPPluginConfig, SanitizedMCPPluginConfig } from './types.js'
4
4
 
5
- import { getAPIKeysCollection } from './collection/index.js'
6
5
  import { mcpEndpoint } from './endpoint/index.js'
7
6
  import { sanitizeMCPConfig } from './mcp/sanitizeMCPConfig.js'
8
7
 
@@ -24,16 +23,6 @@ export const mcpPlugin = definePlugin<MCPPluginConfig>({
24
23
  slug: '@payloadcms/plugin-mcp',
25
24
  order: 10,
26
25
  plugin: ({ config, plugins, ...rawConfig }) => {
27
- // Our `payload-mcp-api-keys` is auth-enabled; if it'd be the only auth
28
- // collection, Payload's later sanitize would pick it as `admin.user`.
29
- // Pre-seed the default user collection to prevent that.
30
- if (!config.admin?.user) {
31
- const firstCollectionWithAuth = (config.collections ?? []).find(({ auth }) => Boolean(auth))
32
- if (!firstCollectionWithAuth) {
33
- ;(config.collections ??= []).push(defaultUserCollection)
34
- }
35
- }
36
-
37
26
  const pluginConfig = sanitizeMCPConfig({ config, pluginConfig: rawConfig })
38
27
 
39
28
  // Stash the sanitized config on plugin options so `getPluginConfig()` reads it.
@@ -43,10 +32,6 @@ export const mcpPlugin = definePlugin<MCPPluginConfig>({
43
32
  registered.sanitizedOptions = pluginConfig as unknown as typeof registered.options
44
33
  }
45
34
 
46
- ;(config.collections ??= []).push(getAPIKeysCollection({ pluginConfig }))
47
-
48
- // Keep the API-keys collection registered even when disabled, so DB schema
49
- // and generated types don't drift between enabled/disabled environments.
50
35
  if (pluginConfig.disabled) {
51
36
  return config
52
37
  }
@@ -57,6 +42,13 @@ export const mcpPlugin = definePlugin<MCPPluginConfig>({
57
42
  ...(config.endpoints ?? []),
58
43
  // Payload prefixes /api, so the full path is /api/mcp.
59
44
  { handler: mcpEndpoint, method: 'post', path: '/mcp' },
45
+ // Streamable HTTP's optional server=>client GET stream. We don't offer
46
+ // one, so answer 405 per spec-— clients then skip it cleanly
47
+ {
48
+ handler: () => new Response(null, { headers: { Allow: 'POST' }, status: 405 }),
49
+ method: 'get',
50
+ path: '/mcp',
51
+ },
60
52
  ],
61
53
  }
62
54
  },