@payloadcms/plugin-mcp 4.0.0-internal.5f0cd13 → 4.0.0-internal.a0ef1b8

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 (57) hide show
  1. package/dist/@types/assets.d.js +2 -0
  2. package/dist/@types/assets.d.js.map +1 -0
  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/mcp/buildMcpServer.d.ts.map +1 -1
  7. package/dist/mcp/buildMcpServer.js +17 -10
  8. package/dist/mcp/buildMcpServer.js.map +1 -1
  9. package/dist/mcp/builtin/collections/createTool.d.ts.map +1 -1
  10. package/dist/mcp/builtin/collections/createTool.js +12 -8
  11. package/dist/mcp/builtin/collections/createTool.js.map +1 -1
  12. package/dist/mcp/builtin/collections/updateTool.d.ts.map +1 -1
  13. package/dist/mcp/builtin/collections/updateTool.js +21 -17
  14. package/dist/mcp/builtin/collections/updateTool.js.map +1 -1
  15. package/dist/mcp/builtin/globals/updateTool.d.ts.map +1 -1
  16. package/dist/mcp/builtin/globals/updateTool.js +13 -9
  17. package/dist/mcp/builtin/globals/updateTool.js.map +1 -1
  18. package/dist/utils/schemaConversion/buildToolInput.d.ts +29 -0
  19. package/dist/utils/schemaConversion/buildToolInput.d.ts.map +1 -0
  20. package/dist/utils/schemaConversion/buildToolInput.js +51 -0
  21. package/dist/utils/schemaConversion/buildToolInput.js.map +1 -0
  22. package/dist/utils/schemaConversion/sanitizeEntitySchema.d.ts +15 -0
  23. package/dist/utils/schemaConversion/sanitizeEntitySchema.d.ts.map +1 -0
  24. package/dist/utils/schemaConversion/sanitizeEntitySchema.js +464 -0
  25. package/dist/utils/schemaConversion/sanitizeEntitySchema.js.map +1 -0
  26. package/dist/utils/schemaConversion/sanitizeEntitySchema.spec.js +158 -0
  27. package/dist/utils/schemaConversion/sanitizeEntitySchema.spec.js.map +1 -0
  28. package/package.json +6 -6
  29. package/src/@types/assets.d.ts +3 -0
  30. package/src/collection/index.ts +1 -0
  31. package/src/mcp/buildMcpServer.ts +19 -14
  32. package/src/mcp/builtin/collections/createTool.ts +37 -37
  33. package/src/mcp/builtin/collections/updateTool.ts +54 -49
  34. package/src/mcp/builtin/globals/updateTool.ts +35 -33
  35. package/src/utils/schemaConversion/buildToolInput.ts +68 -0
  36. package/src/utils/schemaConversion/sanitizeEntitySchema.spec.ts +103 -0
  37. package/src/utils/schemaConversion/sanitizeEntitySchema.ts +529 -0
  38. package/dist/utils/schemaConversion/prepareCollectionSchema.d.ts +0 -7
  39. package/dist/utils/schemaConversion/prepareCollectionSchema.d.ts.map +0 -1
  40. package/dist/utils/schemaConversion/prepareCollectionSchema.js +0 -37
  41. package/dist/utils/schemaConversion/prepareCollectionSchema.js.map +0 -1
  42. package/dist/utils/schemaConversion/sanitizeJsonSchema.d.ts +0 -13
  43. package/dist/utils/schemaConversion/sanitizeJsonSchema.d.ts.map +0 -1
  44. package/dist/utils/schemaConversion/sanitizeJsonSchema.js +0 -56
  45. package/dist/utils/schemaConversion/sanitizeJsonSchema.js.map +0 -1
  46. package/dist/utils/schemaConversion/simplifyRelationshipFields.d.ts +0 -20
  47. package/dist/utils/schemaConversion/simplifyRelationshipFields.d.ts.map +0 -1
  48. package/dist/utils/schemaConversion/simplifyRelationshipFields.js +0 -56
  49. package/dist/utils/schemaConversion/simplifyRelationshipFields.js.map +0 -1
  50. package/dist/utils/schemaConversion/transformPointFields.d.ts +0 -3
  51. package/dist/utils/schemaConversion/transformPointFields.d.ts.map +0 -1
  52. package/dist/utils/schemaConversion/transformPointFields.js +0 -57
  53. package/dist/utils/schemaConversion/transformPointFields.js.map +0 -1
  54. package/src/utils/schemaConversion/prepareCollectionSchema.ts +0 -39
  55. package/src/utils/schemaConversion/sanitizeJsonSchema.ts +0 -62
  56. package/src/utils/schemaConversion/simplifyRelationshipFields.ts +0 -70
  57. package/src/utils/schemaConversion/transformPointFields.ts +0 -56
@@ -0,0 +1,68 @@
1
+ import type { StandardSchemaWithJSON } from '@modelcontextprotocol/server'
2
+
3
+ import { z } from 'zod'
4
+
5
+ import type { JsonSchemaType } from '../../types.js'
6
+
7
+ /**
8
+ * Builds a create/update tool's `input`: a `data` field (the document's fields) plus controls like
9
+ * `depth` and `draft`. Using just `z.fromJSONSchema(ourJSONSchema)` has a few problems which are mitigated
10
+ * in this function. z.fromJSONSchema is both bigger and lossier (≈40% larger on the lexical schema).
11
+ * Each example below is `what we publish` => `what a plain zod round-trip would publish instead`.
12
+ *
13
+ * @example
14
+ * Bigger - zod inlines shared defs instead of keeping our `$ref`s (and adds junk integer bounds), so a
15
+ * reused def is duplicated at every use:
16
+ * `{ $ref: '#/$defs/author' }` => `{ type: 'object', properties: { id, name }, additionalProperties: false }`
17
+ *
18
+ * @example
19
+ * Lossier - zod drops the `description` on `enum`/`const` fields:
20
+ * `{ enum: ['draft', 'published'], description: 'Publish state' }` → `{ enum: ['draft', 'published'] }`
21
+ */
22
+ export const buildToolInput = <TControls extends z.ZodRawShape>({
23
+ controls,
24
+ dataDescription,
25
+ dataSchema,
26
+ }: {
27
+ /** Tool options alongside `data` (depth, draft, where, …) as plain zod - inferred into `input`. */
28
+ controls: TControls
29
+ dataDescription: string
30
+ dataSchema: JsonSchemaType
31
+ }) => {
32
+ // `sanitizeEntitySchema` already emits draft 2020-12 with `$defs`, which is what zod's `fromJSONSchema`
33
+ // and MCP clients both expect. Drop only the root `$schema` keyword, redundant once it's a sub-schema.
34
+ const { $schema: _schema, ...entitySchema } = dataSchema as Record<string, unknown>
35
+
36
+ const schema = z.object({
37
+ data: z.fromJSONSchema(entitySchema as unknown as z.core.JSONSchema.JSONSchema),
38
+ ...controls,
39
+ })
40
+ const standard = (schema as unknown as StandardSchemaWithJSON)['~standard']
41
+
42
+ return {
43
+ '~standard': {
44
+ ...standard,
45
+ jsonSchema: {
46
+ ...standard.jsonSchema,
47
+ input: (options) => {
48
+ // Start from zod's JSON Schema for the whole input, then replace its lossy `data` schema with
49
+ // the sanitized entity schema. The entity's `$defs` move to the root so the `$ref`s resolve.
50
+ const generated = standard.jsonSchema.input(options)
51
+ const { $defs, ...entityBody } = entitySchema
52
+ ;(generated.properties as Record<string, unknown>).data = {
53
+ ...entityBody,
54
+ description: dataDescription,
55
+ }
56
+ if ($defs) {
57
+ generated.$defs = $defs as object
58
+ } else {
59
+ delete generated.$defs
60
+ }
61
+ return generated
62
+ },
63
+ },
64
+ },
65
+ } as StandardSchemaWithJSON<
66
+ { data: Record<string, unknown> } & Omit<z.output<typeof schema>, 'data'>
67
+ >
68
+ }
@@ -0,0 +1,103 @@
1
+ import { describe, expect, it } from 'vitest'
2
+
3
+ import type { JsonSchemaType } from '../../types.js'
4
+
5
+ import { sanitizeEntitySchema } from './sanitizeEntitySchema.js'
6
+
7
+ describe('sanitizeEntitySchema', () => {
8
+ it('keeps a Lexical node union strict (oneOf) while simplifying relationship values to IDs', () => {
9
+ // Shaped like the schema the MCP server prepares for a collection with a Lexical richText field:
10
+ // a `$defs` node union (a `oneOf` of node shapes) where a relationship node's `value` is either
11
+ // an ID or a `$ref` to the populated related collection.
12
+ const standalone: JsonSchemaType = {
13
+ type: 'object',
14
+ $defs: {
15
+ LexicalNodes_ABCDEF12: {
16
+ oneOf: [
17
+ {
18
+ type: 'object',
19
+ additionalProperties: false,
20
+ properties: { type: { const: 'paragraph' } },
21
+ required: ['type'],
22
+ },
23
+ {
24
+ type: 'object',
25
+ additionalProperties: false,
26
+ properties: {
27
+ type: { const: 'relationship' },
28
+ value: { oneOf: [{ type: 'string' }, { $ref: '#/$defs/posts' }] },
29
+ },
30
+ required: ['type'],
31
+ },
32
+ ],
33
+ },
34
+ posts: {
35
+ type: 'object',
36
+ additionalProperties: false,
37
+ properties: { id: { type: 'string' }, title: { type: 'string' } },
38
+ },
39
+ },
40
+ properties: {
41
+ id: { type: 'string' },
42
+ content: {
43
+ type: 'object',
44
+ properties: {
45
+ root: {
46
+ type: 'object',
47
+ properties: {
48
+ children: { type: 'array', items: { $ref: '#/$defs/LexicalNodes_ABCDEF12' } },
49
+ },
50
+ },
51
+ },
52
+ },
53
+ },
54
+ }
55
+
56
+ expect(sanitizeEntitySchema(standalone)).toStrictEqual({
57
+ type: 'object',
58
+ $defs: {
59
+ // The node union is renamed to a short, readable `node`, and stays a strict discriminated
60
+ // `oneOf` - not loosened to `anyOf`...
61
+ node: {
62
+ oneOf: [
63
+ {
64
+ type: 'object',
65
+ additionalProperties: false,
66
+ properties: { type: { const: 'paragraph' } },
67
+ required: ['type'],
68
+ },
69
+ {
70
+ type: 'object',
71
+ additionalProperties: false,
72
+ properties: {
73
+ type: { const: 'relationship' },
74
+ // ...while the relationship `value` is simplified to a bare ID (the populated-doc `$ref` is dropped).
75
+ value: { type: 'string', description: 'The ID of the related "posts" document.' },
76
+ },
77
+ required: ['type'],
78
+ },
79
+ ],
80
+ },
81
+ posts: {
82
+ type: 'object',
83
+ additionalProperties: false,
84
+ properties: { id: { type: 'string' }, title: { type: 'string' } },
85
+ },
86
+ },
87
+ properties: {
88
+ // `id` is dropped - it's a Payload-managed field MCP clients never set.
89
+ content: {
90
+ type: 'object',
91
+ properties: {
92
+ root: {
93
+ type: 'object',
94
+ properties: {
95
+ children: { type: 'array', items: { $ref: '#/$defs/node' } },
96
+ },
97
+ },
98
+ },
99
+ },
100
+ },
101
+ })
102
+ })
103
+ })