@payloadcms/plugin-mcp 4.0.0-canary.0 → 4.0.0-canary.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (122) hide show
  1. package/dist/collection/getAccessField.js +1 -1
  2. package/dist/collection/getAccessField.js.map +1 -1
  3. package/dist/collection/index.d.ts.map +1 -1
  4. package/dist/collection/index.js +2 -1
  5. package/dist/collection/index.js.map +1 -1
  6. package/dist/components/AccessField/index.client.d.ts.map +1 -1
  7. package/dist/components/AccessField/index.client.js +30 -30
  8. package/dist/components/AccessField/index.client.js.map +1 -1
  9. package/dist/endpoint/access.js +5 -5
  10. package/dist/endpoint/access.js.map +1 -1
  11. package/dist/mcp/buildMcpServer.d.ts.map +1 -1
  12. package/dist/mcp/buildMcpServer.js +100 -64
  13. package/dist/mcp/buildMcpServer.js.map +1 -1
  14. package/dist/mcp/builtin/collections/createTool.d.ts +1 -1
  15. package/dist/mcp/builtin/collections/createTool.d.ts.map +1 -1
  16. package/dist/mcp/builtin/collections/createTool.js +28 -21
  17. package/dist/mcp/builtin/collections/createTool.js.map +1 -1
  18. package/dist/mcp/builtin/collections/deleteTool.d.ts +1 -1
  19. package/dist/mcp/builtin/collections/deleteTool.d.ts.map +1 -1
  20. package/dist/mcp/builtin/collections/deleteTool.js +5 -20
  21. package/dist/mcp/builtin/collections/deleteTool.js.map +1 -1
  22. package/dist/mcp/builtin/collections/findTool.d.ts +1 -1
  23. package/dist/mcp/builtin/collections/findTool.d.ts.map +1 -1
  24. package/dist/mcp/builtin/collections/findTool.js +6 -21
  25. package/dist/mcp/builtin/collections/findTool.js.map +1 -1
  26. package/dist/mcp/builtin/collections/formatCollectionError.d.ts +9 -0
  27. package/dist/mcp/builtin/collections/formatCollectionError.d.ts.map +1 -0
  28. package/dist/mcp/builtin/collections/formatCollectionError.js +60 -0
  29. package/dist/mcp/builtin/collections/formatCollectionError.js.map +1 -0
  30. package/dist/mcp/builtin/collections/getCollectionSchemaTool.d.ts +2 -0
  31. package/dist/mcp/builtin/collections/getCollectionSchemaTool.d.ts.map +1 -0
  32. package/dist/mcp/builtin/collections/getCollectionSchemaTool.js +35 -0
  33. package/dist/mcp/builtin/collections/getCollectionSchemaTool.js.map +1 -0
  34. package/dist/mcp/builtin/collections/updateTool.d.ts +1 -1
  35. package/dist/mcp/builtin/collections/updateTool.d.ts.map +1 -1
  36. package/dist/mcp/builtin/collections/updateTool.js +74 -62
  37. package/dist/mcp/builtin/collections/updateTool.js.map +1 -1
  38. package/dist/mcp/builtin/getConfigInfoTool.d.ts +2 -0
  39. package/dist/mcp/builtin/getConfigInfoTool.d.ts.map +1 -0
  40. package/dist/mcp/builtin/getConfigInfoTool.js +49 -0
  41. package/dist/mcp/builtin/getConfigInfoTool.js.map +1 -0
  42. package/dist/mcp/builtin/globals/findTool.js +1 -1
  43. package/dist/mcp/builtin/globals/findTool.js.map +1 -1
  44. package/dist/mcp/builtin/globals/getGlobalSchemaTool.d.ts +2 -0
  45. package/dist/mcp/builtin/globals/getGlobalSchemaTool.d.ts.map +1 -0
  46. package/dist/mcp/builtin/globals/getGlobalSchemaTool.js +35 -0
  47. package/dist/mcp/builtin/globals/getGlobalSchemaTool.js.map +1 -0
  48. package/dist/mcp/builtin/globals/updateTool.d.ts.map +1 -1
  49. package/dist/mcp/builtin/globals/updateTool.js +21 -19
  50. package/dist/mcp/builtin/globals/updateTool.js.map +1 -1
  51. package/dist/mcp/builtin/validateEntityData.d.ts +14 -0
  52. package/dist/mcp/builtin/validateEntityData.d.ts.map +1 -0
  53. package/dist/mcp/builtin/validateEntityData.js +82 -0
  54. package/dist/mcp/builtin/validateEntityData.js.map +1 -0
  55. package/dist/mcp/builtinTools.d.ts +84 -16
  56. package/dist/mcp/builtinTools.d.ts.map +1 -1
  57. package/dist/mcp/builtinTools.js +54 -11
  58. package/dist/mcp/builtinTools.js.map +1 -1
  59. package/dist/mcp/sanitizeMCPConfig.d.ts.map +1 -1
  60. package/dist/mcp/sanitizeMCPConfig.js +61 -40
  61. package/dist/mcp/sanitizeMCPConfig.js.map +1 -1
  62. package/dist/types.d.ts +16 -27
  63. package/dist/types.d.ts.map +1 -1
  64. package/dist/types.js.map +1 -1
  65. package/dist/utils/schemaConversion/getEntityInputSchema.d.ts +11 -0
  66. package/dist/utils/schemaConversion/getEntityInputSchema.d.ts.map +1 -0
  67. package/dist/utils/schemaConversion/getEntityInputSchema.js +34 -0
  68. package/dist/utils/schemaConversion/getEntityInputSchema.js.map +1 -0
  69. package/dist/utils/schemaConversion/sanitizeEntitySchema.d.ts +15 -0
  70. package/dist/utils/schemaConversion/sanitizeEntitySchema.d.ts.map +1 -0
  71. package/dist/utils/schemaConversion/sanitizeEntitySchema.js +464 -0
  72. package/dist/utils/schemaConversion/sanitizeEntitySchema.js.map +1 -0
  73. package/dist/utils/schemaConversion/sanitizeEntitySchema.spec.js +158 -0
  74. package/dist/utils/schemaConversion/sanitizeEntitySchema.spec.js.map +1 -0
  75. package/dist/utils/whereSchema.d.ts +9 -0
  76. package/dist/utils/whereSchema.d.ts.map +1 -0
  77. package/dist/utils/whereSchema.js +13 -0
  78. package/dist/utils/whereSchema.js.map +1 -0
  79. package/package.json +5 -5
  80. package/src/collection/getAccessField.ts +1 -1
  81. package/src/collection/index.ts +1 -0
  82. package/src/components/AccessField/index.client.tsx +34 -31
  83. package/src/endpoint/access.ts +5 -5
  84. package/src/mcp/buildMcpServer.ts +123 -90
  85. package/src/mcp/builtin/collections/createTool.ts +46 -50
  86. package/src/mcp/builtin/collections/deleteTool.ts +9 -16
  87. package/src/mcp/builtin/collections/findTool.ts +7 -17
  88. package/src/mcp/builtin/collections/formatCollectionError.ts +84 -0
  89. package/src/mcp/builtin/collections/getCollectionSchemaTool.ts +28 -0
  90. package/src/mcp/builtin/collections/updateTool.ts +97 -91
  91. package/src/mcp/builtin/getConfigInfoTool.ts +44 -0
  92. package/src/mcp/builtin/globals/findTool.ts +1 -1
  93. package/src/mcp/builtin/globals/getGlobalSchemaTool.ts +28 -0
  94. package/src/mcp/builtin/globals/updateTool.ts +40 -43
  95. package/src/mcp/builtin/validateEntityData.ts +132 -0
  96. package/src/mcp/builtinTools.ts +52 -38
  97. package/src/mcp/sanitizeMCPConfig.ts +78 -57
  98. package/src/types.ts +24 -29
  99. package/src/utils/schemaConversion/getEntityInputSchema.ts +78 -0
  100. package/src/utils/schemaConversion/sanitizeEntitySchema.spec.ts +103 -0
  101. package/src/utils/schemaConversion/sanitizeEntitySchema.ts +529 -0
  102. package/src/utils/whereSchema.ts +24 -0
  103. package/dist/utils/schemaConversion/prepareCollectionSchema.d.ts +0 -7
  104. package/dist/utils/schemaConversion/prepareCollectionSchema.d.ts.map +0 -1
  105. package/dist/utils/schemaConversion/prepareCollectionSchema.js +0 -37
  106. package/dist/utils/schemaConversion/prepareCollectionSchema.js.map +0 -1
  107. package/dist/utils/schemaConversion/sanitizeJsonSchema.d.ts +0 -13
  108. package/dist/utils/schemaConversion/sanitizeJsonSchema.d.ts.map +0 -1
  109. package/dist/utils/schemaConversion/sanitizeJsonSchema.js +0 -56
  110. package/dist/utils/schemaConversion/sanitizeJsonSchema.js.map +0 -1
  111. package/dist/utils/schemaConversion/simplifyRelationshipFields.d.ts +0 -20
  112. package/dist/utils/schemaConversion/simplifyRelationshipFields.d.ts.map +0 -1
  113. package/dist/utils/schemaConversion/simplifyRelationshipFields.js +0 -56
  114. package/dist/utils/schemaConversion/simplifyRelationshipFields.js.map +0 -1
  115. package/dist/utils/schemaConversion/transformPointFields.d.ts +0 -3
  116. package/dist/utils/schemaConversion/transformPointFields.d.ts.map +0 -1
  117. package/dist/utils/schemaConversion/transformPointFields.js +0 -57
  118. package/dist/utils/schemaConversion/transformPointFields.js.map +0 -1
  119. package/src/utils/schemaConversion/prepareCollectionSchema.ts +0 -39
  120. package/src/utils/schemaConversion/sanitizeJsonSchema.ts +0 -62
  121. package/src/utils/schemaConversion/simplifyRelationshipFields.ts +0 -70
  122. 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-canary.0",
3
+ "version": "4.0.0-canary.1",
4
4
  "description": "MCP (Model Context Protocol) capabilities with Payload",
5
5
  "keywords": [
6
6
  "plugin",
@@ -62,13 +62,13 @@
62
62
  "@types/react": "19.2.14",
63
63
  "react": "^19.0.1 || ^19.1.2 || ^19.2.1",
64
64
  "@payloadcms/eslint-config": "3.28.0",
65
- "payload": "4.0.0-canary.0",
66
- "@payloadcms/ui": "4.0.0-canary.0"
65
+ "@payloadcms/ui": "4.0.0-canary.1",
66
+ "payload": "4.0.0-canary.1"
67
67
  },
68
68
  "peerDependencies": {
69
69
  "react": "^19.0.1 || ^19.1.2 || ^19.2.1",
70
- "@payloadcms/ui": "4.0.0-canary.0",
71
- "payload": "4.0.0-canary.0"
70
+ "@payloadcms/ui": "4.0.0-canary.1",
71
+ "payload": "4.0.0-canary.1"
72
72
  },
73
73
  "//deps_notes": {
74
74
  "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.",
@@ -47,8 +47,8 @@ const sanitizeClientPluginConfig = (
47
47
  ...(item.type === 'collectionTool' ? { collectionSlug: item.collectionSlug } : {}),
48
48
  ...(item.type === 'globalTool' ? { globalSlug: item.globalSlug } : {}),
49
49
  type: item.type,
50
+ configKey: item.configKey,
50
51
  description: itemDescription(item),
51
- key: item.key,
52
52
  label: item.label,
53
53
  })),
54
54
  })
@@ -55,6 +55,7 @@ export const getAPIKeysCollection = ({
55
55
  plural: 'API Keys',
56
56
  singular: 'API Key',
57
57
  },
58
+ versions: false,
58
59
  }
59
60
 
60
61
  return pluginConfig.overrideApiKeyCollection
@@ -68,14 +68,15 @@ export const AccessField: React.FC<Props> = ({ path, pluginConfig }) => {
68
68
  }
69
69
  }
70
70
 
71
- const isScopedAllowed = (scope: ScopeKey, slug: string, key: string): boolean =>
72
- access[scope]?.[slug]?.[key] !== false
71
+ const isScopedAllowed = (scope: ScopeKey, slug: string, configKey: string): boolean =>
72
+ access[scope]?.[slug]?.[configKey] !== false
73
73
 
74
- const isFlatAllowed = (scope: FlatKey, key: string): boolean => access[scope]?.[key] !== false
74
+ const isFlatAllowed = (scope: FlatKey, configKey: string): boolean =>
75
+ access[scope]?.[configKey] !== false
75
76
 
76
- const toggleScoped = (scope: ScopeKey, slug: string, key: string, allow: boolean) => {
77
+ const toggleScoped = (scope: ScopeKey, slug: string, configKey: string, allow: boolean) => {
77
78
  if (allow) {
78
- const slugBucket = without(access[scope]?.[slug], key)
79
+ const slugBucket = without(access[scope]?.[slug], configKey)
79
80
  const scopeBucket = slugBucket
80
81
  ? setKey(access[scope], slug, slugBucket)
81
82
  : without(access[scope], slug)
@@ -85,18 +86,18 @@ export const AccessField: React.FC<Props> = ({ path, pluginConfig }) => {
85
86
  setKey(
86
87
  access,
87
88
  scope,
88
- setKey(access[scope], slug, setKey(access[scope]?.[slug], key, false)),
89
+ setKey(access[scope], slug, setKey(access[scope]?.[slug], configKey, false)),
89
90
  ),
90
91
  )
91
92
  }
92
93
  }
93
94
 
94
- const toggleFlat = (scope: FlatKey, key: string, allow: boolean) => {
95
+ const toggleFlat = (scope: FlatKey, configKey: string, allow: boolean) => {
95
96
  if (allow) {
96
- const bucket = without(access[scope], key)
97
+ const bucket = without(access[scope], configKey)
97
98
  setValue(bucket ? setKey(access, scope, bucket) : (without(access, scope) ?? {}))
98
99
  } else {
99
- setValue(setKey(access, scope, setKey(access[scope], key, false)))
100
+ setValue(setKey(access, scope, setKey(access[scope], configKey, false)))
100
101
  }
101
102
  }
102
103
 
@@ -106,7 +107,7 @@ export const AccessField: React.FC<Props> = ({ path, pluginConfig }) => {
106
107
  setValue(scopeBucket ? setKey(access, scope, scopeBucket) : (without(access, scope) ?? {}))
107
108
  } else {
108
109
  const slugBucket = leaves.reduce<Record<string, boolean>>(
109
- (acc, leaf) => ({ ...acc, [leaf.key]: false }),
110
+ (acc, leaf) => ({ ...acc, [leaf.configKey]: false }),
110
111
  {},
111
112
  )
112
113
  setValue(setKey(access, scope, setKey(access[scope], slug, slugBucket)))
@@ -118,7 +119,7 @@ export const AccessField: React.FC<Props> = ({ path, pluginConfig }) => {
118
119
  setValue(without(access, scope) ?? {})
119
120
  } else {
120
121
  const bucket = leaves.reduce<Record<string, boolean>>(
121
- (acc, leaf) => ({ ...acc, [leaf.key]: false }),
122
+ (acc, leaf) => ({ ...acc, [leaf.configKey]: false }),
122
123
  {},
123
124
  )
124
125
  setValue(setKey(access, scope, bucket))
@@ -154,13 +155,13 @@ export const AccessField: React.FC<Props> = ({ path, pluginConfig }) => {
154
155
  >
155
156
  <ul className={`${baseClass}__list`}>
156
157
  {leaves.map((leaf) => (
157
- <li key={leaf.key}>
158
+ <li key={leaf.configKey}>
158
159
  <CheckboxInput
159
- checked={isScopedAllowed('collections', slug, leaf.key)}
160
- id={`${path}.collections.${slug}.${leaf.key}`}
160
+ checked={isScopedAllowed('collections', slug, leaf.configKey)}
161
+ id={`${path}.collections.${slug}.${leaf.configKey}`}
161
162
  label={leaf.label}
162
163
  onToggle={(e) =>
163
- toggleScoped('collections', slug, leaf.key, e.target.checked)
164
+ toggleScoped('collections', slug, leaf.configKey, e.target.checked)
164
165
  }
165
166
  tooltip={leaf.description}
166
167
  />
@@ -197,12 +198,14 @@ export const AccessField: React.FC<Props> = ({ path, pluginConfig }) => {
197
198
  >
198
199
  <ul className={`${baseClass}__list`}>
199
200
  {leaves.map((leaf) => (
200
- <li key={leaf.key}>
201
+ <li key={leaf.configKey}>
201
202
  <CheckboxInput
202
- checked={isScopedAllowed('globals', slug, leaf.key)}
203
- id={`${path}.globals.${slug}.${leaf.key}`}
203
+ checked={isScopedAllowed('globals', slug, leaf.configKey)}
204
+ id={`${path}.globals.${slug}.${leaf.configKey}`}
204
205
  label={leaf.label}
205
- onToggle={(e) => toggleScoped('globals', slug, leaf.key, e.target.checked)}
206
+ onToggle={(e) =>
207
+ toggleScoped('globals', slug, leaf.configKey, e.target.checked)
208
+ }
206
209
  tooltip={leaf.description}
207
210
  />
208
211
  </li>
@@ -234,12 +237,12 @@ export const AccessField: React.FC<Props> = ({ path, pluginConfig }) => {
234
237
  >
235
238
  <ul className={`${baseClass}__list`}>
236
239
  {tools.map((leaf) => (
237
- <li key={leaf.key}>
240
+ <li key={leaf.configKey}>
238
241
  <CheckboxInput
239
- checked={isFlatAllowed('tools', leaf.key)}
240
- id={`${path}.tools.${leaf.key}`}
242
+ checked={isFlatAllowed('tools', leaf.configKey)}
243
+ id={`${path}.tools.${leaf.configKey}`}
241
244
  label={leaf.label}
242
- onToggle={(e) => toggleFlat('tools', leaf.key, e.target.checked)}
245
+ onToggle={(e) => toggleFlat('tools', leaf.configKey, e.target.checked)}
243
246
  tooltip={leaf.description}
244
247
  />
245
248
  </li>
@@ -259,12 +262,12 @@ export const AccessField: React.FC<Props> = ({ path, pluginConfig }) => {
259
262
  >
260
263
  <ul className={`${baseClass}__list`}>
261
264
  {prompts.map((leaf) => (
262
- <li key={leaf.key}>
265
+ <li key={leaf.configKey}>
263
266
  <CheckboxInput
264
- checked={isFlatAllowed('prompts', leaf.key)}
265
- id={`${path}.prompts.${leaf.key}`}
267
+ checked={isFlatAllowed('prompts', leaf.configKey)}
268
+ id={`${path}.prompts.${leaf.configKey}`}
266
269
  label={leaf.label}
267
- onToggle={(e) => toggleFlat('prompts', leaf.key, e.target.checked)}
270
+ onToggle={(e) => toggleFlat('prompts', leaf.configKey, e.target.checked)}
268
271
  tooltip={leaf.description}
269
272
  />
270
273
  </li>
@@ -286,12 +289,12 @@ export const AccessField: React.FC<Props> = ({ path, pluginConfig }) => {
286
289
  >
287
290
  <ul className={`${baseClass}__list`}>
288
291
  {resources.map((leaf) => (
289
- <li key={leaf.key}>
292
+ <li key={leaf.configKey}>
290
293
  <CheckboxInput
291
- checked={isFlatAllowed('resources', leaf.key)}
292
- id={`${path}.resources.${leaf.key}`}
294
+ checked={isFlatAllowed('resources', leaf.configKey)}
295
+ id={`${path}.resources.${leaf.configKey}`}
293
296
  label={leaf.label}
294
- onToggle={(e) => toggleFlat('resources', leaf.key, e.target.checked)}
297
+ onToggle={(e) => toggleFlat('resources', leaf.configKey, e.target.checked)}
295
298
  tooltip={leaf.description}
296
299
  />
297
300
  </li>
@@ -25,15 +25,15 @@ export const getAuthorizedMCP: (args: { req: PayloadRequest }) => Promise<Author
25
25
  items: pluginConfig.items.filter((item) => {
26
26
  switch (item.type) {
27
27
  case 'collectionTool':
28
- return apiKeyDoc.access.collections?.[item.collectionSlug]?.[item.key] !== false
28
+ return apiKeyDoc.access.collections?.[item.collectionSlug]?.[item.configKey] !== false
29
29
  case 'globalTool':
30
- return apiKeyDoc.access.globals?.[item.globalSlug]?.[item.key] !== false
30
+ return apiKeyDoc.access.globals?.[item.globalSlug]?.[item.configKey] !== false
31
31
  case 'prompt':
32
- return apiKeyDoc.access.prompts?.[item.key] !== false
32
+ return apiKeyDoc.access.prompts?.[item.configKey] !== false
33
33
  case 'resource':
34
- return apiKeyDoc.access.resources?.[item.key] !== false
34
+ return apiKeyDoc.access.resources?.[item.configKey] !== false
35
35
  case 'tool':
36
- return apiKeyDoc.access.tools?.[item.key] !== false
36
+ return apiKeyDoc.access.tools?.[item.configKey] !== false
37
37
  }
38
38
  }),
39
39
  overrideAccess: