@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.
- package/dist/collection/getAccessField.js +1 -1
- package/dist/collection/getAccessField.js.map +1 -1
- package/dist/collection/index.d.ts.map +1 -1
- package/dist/collection/index.js +2 -1
- package/dist/collection/index.js.map +1 -1
- package/dist/components/AccessField/index.client.d.ts.map +1 -1
- package/dist/components/AccessField/index.client.js +30 -30
- package/dist/components/AccessField/index.client.js.map +1 -1
- package/dist/endpoint/access.js +5 -5
- package/dist/endpoint/access.js.map +1 -1
- package/dist/mcp/buildMcpServer.d.ts.map +1 -1
- package/dist/mcp/buildMcpServer.js +100 -64
- package/dist/mcp/buildMcpServer.js.map +1 -1
- package/dist/mcp/builtin/collections/createTool.d.ts +1 -1
- package/dist/mcp/builtin/collections/createTool.d.ts.map +1 -1
- package/dist/mcp/builtin/collections/createTool.js +28 -21
- package/dist/mcp/builtin/collections/createTool.js.map +1 -1
- package/dist/mcp/builtin/collections/deleteTool.d.ts +1 -1
- package/dist/mcp/builtin/collections/deleteTool.d.ts.map +1 -1
- package/dist/mcp/builtin/collections/deleteTool.js +5 -20
- package/dist/mcp/builtin/collections/deleteTool.js.map +1 -1
- package/dist/mcp/builtin/collections/findTool.d.ts +1 -1
- package/dist/mcp/builtin/collections/findTool.d.ts.map +1 -1
- package/dist/mcp/builtin/collections/findTool.js +6 -21
- package/dist/mcp/builtin/collections/findTool.js.map +1 -1
- package/dist/mcp/builtin/collections/formatCollectionError.d.ts +9 -0
- package/dist/mcp/builtin/collections/formatCollectionError.d.ts.map +1 -0
- package/dist/mcp/builtin/collections/formatCollectionError.js +60 -0
- package/dist/mcp/builtin/collections/formatCollectionError.js.map +1 -0
- package/dist/mcp/builtin/collections/getCollectionSchemaTool.d.ts +2 -0
- package/dist/mcp/builtin/collections/getCollectionSchemaTool.d.ts.map +1 -0
- package/dist/mcp/builtin/collections/getCollectionSchemaTool.js +35 -0
- package/dist/mcp/builtin/collections/getCollectionSchemaTool.js.map +1 -0
- package/dist/mcp/builtin/collections/updateTool.d.ts +1 -1
- package/dist/mcp/builtin/collections/updateTool.d.ts.map +1 -1
- package/dist/mcp/builtin/collections/updateTool.js +74 -62
- package/dist/mcp/builtin/collections/updateTool.js.map +1 -1
- package/dist/mcp/builtin/getConfigInfoTool.d.ts +2 -0
- package/dist/mcp/builtin/getConfigInfoTool.d.ts.map +1 -0
- package/dist/mcp/builtin/getConfigInfoTool.js +49 -0
- package/dist/mcp/builtin/getConfigInfoTool.js.map +1 -0
- package/dist/mcp/builtin/globals/findTool.js +1 -1
- package/dist/mcp/builtin/globals/findTool.js.map +1 -1
- package/dist/mcp/builtin/globals/getGlobalSchemaTool.d.ts +2 -0
- package/dist/mcp/builtin/globals/getGlobalSchemaTool.d.ts.map +1 -0
- package/dist/mcp/builtin/globals/getGlobalSchemaTool.js +35 -0
- package/dist/mcp/builtin/globals/getGlobalSchemaTool.js.map +1 -0
- package/dist/mcp/builtin/globals/updateTool.d.ts.map +1 -1
- package/dist/mcp/builtin/globals/updateTool.js +21 -19
- package/dist/mcp/builtin/globals/updateTool.js.map +1 -1
- package/dist/mcp/builtin/validateEntityData.d.ts +14 -0
- package/dist/mcp/builtin/validateEntityData.d.ts.map +1 -0
- package/dist/mcp/builtin/validateEntityData.js +82 -0
- package/dist/mcp/builtin/validateEntityData.js.map +1 -0
- package/dist/mcp/builtinTools.d.ts +84 -16
- package/dist/mcp/builtinTools.d.ts.map +1 -1
- package/dist/mcp/builtinTools.js +54 -11
- package/dist/mcp/builtinTools.js.map +1 -1
- package/dist/mcp/sanitizeMCPConfig.d.ts.map +1 -1
- package/dist/mcp/sanitizeMCPConfig.js +61 -40
- package/dist/mcp/sanitizeMCPConfig.js.map +1 -1
- package/dist/types.d.ts +16 -27
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/utils/schemaConversion/getEntityInputSchema.d.ts +11 -0
- package/dist/utils/schemaConversion/getEntityInputSchema.d.ts.map +1 -0
- package/dist/utils/schemaConversion/getEntityInputSchema.js +34 -0
- package/dist/utils/schemaConversion/getEntityInputSchema.js.map +1 -0
- package/dist/utils/schemaConversion/sanitizeEntitySchema.d.ts +15 -0
- package/dist/utils/schemaConversion/sanitizeEntitySchema.d.ts.map +1 -0
- package/dist/utils/schemaConversion/sanitizeEntitySchema.js +464 -0
- package/dist/utils/schemaConversion/sanitizeEntitySchema.js.map +1 -0
- package/dist/utils/schemaConversion/sanitizeEntitySchema.spec.js +158 -0
- package/dist/utils/schemaConversion/sanitizeEntitySchema.spec.js.map +1 -0
- package/dist/utils/whereSchema.d.ts +9 -0
- package/dist/utils/whereSchema.d.ts.map +1 -0
- package/dist/utils/whereSchema.js +13 -0
- package/dist/utils/whereSchema.js.map +1 -0
- package/package.json +5 -5
- package/src/collection/getAccessField.ts +1 -1
- package/src/collection/index.ts +1 -0
- package/src/components/AccessField/index.client.tsx +34 -31
- package/src/endpoint/access.ts +5 -5
- package/src/mcp/buildMcpServer.ts +123 -90
- package/src/mcp/builtin/collections/createTool.ts +46 -50
- package/src/mcp/builtin/collections/deleteTool.ts +9 -16
- package/src/mcp/builtin/collections/findTool.ts +7 -17
- package/src/mcp/builtin/collections/formatCollectionError.ts +84 -0
- package/src/mcp/builtin/collections/getCollectionSchemaTool.ts +28 -0
- package/src/mcp/builtin/collections/updateTool.ts +97 -91
- package/src/mcp/builtin/getConfigInfoTool.ts +44 -0
- package/src/mcp/builtin/globals/findTool.ts +1 -1
- package/src/mcp/builtin/globals/getGlobalSchemaTool.ts +28 -0
- package/src/mcp/builtin/globals/updateTool.ts +40 -43
- package/src/mcp/builtin/validateEntityData.ts +132 -0
- package/src/mcp/builtinTools.ts +52 -38
- package/src/mcp/sanitizeMCPConfig.ts +78 -57
- package/src/types.ts +24 -29
- package/src/utils/schemaConversion/getEntityInputSchema.ts +78 -0
- package/src/utils/schemaConversion/sanitizeEntitySchema.spec.ts +103 -0
- package/src/utils/schemaConversion/sanitizeEntitySchema.ts +529 -0
- package/src/utils/whereSchema.ts +24 -0
- package/dist/utils/schemaConversion/prepareCollectionSchema.d.ts +0 -7
- package/dist/utils/schemaConversion/prepareCollectionSchema.d.ts.map +0 -1
- package/dist/utils/schemaConversion/prepareCollectionSchema.js +0 -37
- package/dist/utils/schemaConversion/prepareCollectionSchema.js.map +0 -1
- package/dist/utils/schemaConversion/sanitizeJsonSchema.d.ts +0 -13
- package/dist/utils/schemaConversion/sanitizeJsonSchema.d.ts.map +0 -1
- package/dist/utils/schemaConversion/sanitizeJsonSchema.js +0 -56
- package/dist/utils/schemaConversion/sanitizeJsonSchema.js.map +0 -1
- package/dist/utils/schemaConversion/simplifyRelationshipFields.d.ts +0 -20
- package/dist/utils/schemaConversion/simplifyRelationshipFields.d.ts.map +0 -1
- package/dist/utils/schemaConversion/simplifyRelationshipFields.js +0 -56
- package/dist/utils/schemaConversion/simplifyRelationshipFields.js.map +0 -1
- package/dist/utils/schemaConversion/transformPointFields.d.ts +0 -3
- package/dist/utils/schemaConversion/transformPointFields.d.ts.map +0 -1
- package/dist/utils/schemaConversion/transformPointFields.js +0 -57
- package/dist/utils/schemaConversion/transformPointFields.js.map +0 -1
- package/src/utils/schemaConversion/prepareCollectionSchema.ts +0 -39
- package/src/utils/schemaConversion/sanitizeJsonSchema.ts +0 -62
- package/src/utils/schemaConversion/simplifyRelationshipFields.ts +0 -70
- 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.
|
|
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
|
-
"
|
|
66
|
-
"
|
|
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.
|
|
71
|
-
"payload": "4.0.0-canary.
|
|
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
|
})
|
package/src/collection/index.ts
CHANGED
|
@@ -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,
|
|
72
|
-
access[scope]?.[slug]?.[
|
|
71
|
+
const isScopedAllowed = (scope: ScopeKey, slug: string, configKey: string): boolean =>
|
|
72
|
+
access[scope]?.[slug]?.[configKey] !== false
|
|
73
73
|
|
|
74
|
-
const isFlatAllowed = (scope: FlatKey,
|
|
74
|
+
const isFlatAllowed = (scope: FlatKey, configKey: string): boolean =>
|
|
75
|
+
access[scope]?.[configKey] !== false
|
|
75
76
|
|
|
76
|
-
const toggleScoped = (scope: ScopeKey, slug: string,
|
|
77
|
+
const toggleScoped = (scope: ScopeKey, slug: string, configKey: string, allow: boolean) => {
|
|
77
78
|
if (allow) {
|
|
78
|
-
const slugBucket = without(access[scope]?.[slug],
|
|
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],
|
|
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,
|
|
95
|
+
const toggleFlat = (scope: FlatKey, configKey: string, allow: boolean) => {
|
|
95
96
|
if (allow) {
|
|
96
|
-
const bucket = without(access[scope],
|
|
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],
|
|
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.
|
|
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.
|
|
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.
|
|
158
|
+
<li key={leaf.configKey}>
|
|
158
159
|
<CheckboxInput
|
|
159
|
-
checked={isScopedAllowed('collections', slug, leaf.
|
|
160
|
-
id={`${path}.collections.${slug}.${leaf.
|
|
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.
|
|
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.
|
|
201
|
+
<li key={leaf.configKey}>
|
|
201
202
|
<CheckboxInput
|
|
202
|
-
checked={isScopedAllowed('globals', slug, leaf.
|
|
203
|
-
id={`${path}.globals.${slug}.${leaf.
|
|
203
|
+
checked={isScopedAllowed('globals', slug, leaf.configKey)}
|
|
204
|
+
id={`${path}.globals.${slug}.${leaf.configKey}`}
|
|
204
205
|
label={leaf.label}
|
|
205
|
-
onToggle={(e) =>
|
|
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.
|
|
240
|
+
<li key={leaf.configKey}>
|
|
238
241
|
<CheckboxInput
|
|
239
|
-
checked={isFlatAllowed('tools', leaf.
|
|
240
|
-
id={`${path}.tools.${leaf.
|
|
242
|
+
checked={isFlatAllowed('tools', leaf.configKey)}
|
|
243
|
+
id={`${path}.tools.${leaf.configKey}`}
|
|
241
244
|
label={leaf.label}
|
|
242
|
-
onToggle={(e) => toggleFlat('tools', leaf.
|
|
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.
|
|
265
|
+
<li key={leaf.configKey}>
|
|
263
266
|
<CheckboxInput
|
|
264
|
-
checked={isFlatAllowed('prompts', leaf.
|
|
265
|
-
id={`${path}.prompts.${leaf.
|
|
267
|
+
checked={isFlatAllowed('prompts', leaf.configKey)}
|
|
268
|
+
id={`${path}.prompts.${leaf.configKey}`}
|
|
266
269
|
label={leaf.label}
|
|
267
|
-
onToggle={(e) => toggleFlat('prompts', leaf.
|
|
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.
|
|
292
|
+
<li key={leaf.configKey}>
|
|
290
293
|
<CheckboxInput
|
|
291
|
-
checked={isFlatAllowed('resources', leaf.
|
|
292
|
-
id={`${path}.resources.${leaf.
|
|
294
|
+
checked={isFlatAllowed('resources', leaf.configKey)}
|
|
295
|
+
id={`${path}.resources.${leaf.configKey}`}
|
|
293
296
|
label={leaf.label}
|
|
294
|
-
onToggle={(e) => toggleFlat('resources', leaf.
|
|
297
|
+
onToggle={(e) => toggleFlat('resources', leaf.configKey, e.target.checked)}
|
|
295
298
|
tooltip={leaf.description}
|
|
296
299
|
/>
|
|
297
300
|
</li>
|
package/src/endpoint/access.ts
CHANGED
|
@@ -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.
|
|
28
|
+
return apiKeyDoc.access.collections?.[item.collectionSlug]?.[item.configKey] !== false
|
|
29
29
|
case 'globalTool':
|
|
30
|
-
return apiKeyDoc.access.globals?.[item.globalSlug]?.[item.
|
|
30
|
+
return apiKeyDoc.access.globals?.[item.globalSlug]?.[item.configKey] !== false
|
|
31
31
|
case 'prompt':
|
|
32
|
-
return apiKeyDoc.access.prompts?.[item.
|
|
32
|
+
return apiKeyDoc.access.prompts?.[item.configKey] !== false
|
|
33
33
|
case 'resource':
|
|
34
|
-
return apiKeyDoc.access.resources?.[item.
|
|
34
|
+
return apiKeyDoc.access.resources?.[item.configKey] !== false
|
|
35
35
|
case 'tool':
|
|
36
|
-
return apiKeyDoc.access.tools?.[item.
|
|
36
|
+
return apiKeyDoc.access.tools?.[item.configKey] !== false
|
|
37
37
|
}
|
|
38
38
|
}),
|
|
39
39
|
overrideAccess:
|