@payloadcms/plugin-mcp 4.0.0-internal.a0ef1b8 → 4.0.0-internal.a1317b2

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 (240) hide show
  1. package/LICENSE.md +1 -1
  2. package/bin.js +7 -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/defineTool.d.ts +8 -8
  8. package/dist/defineTool.d.ts.map +1 -1
  9. package/dist/endpoint/access.d.ts +12 -5
  10. package/dist/endpoint/access.d.ts.map +1 -1
  11. package/dist/endpoint/access.js +75 -88
  12. package/dist/endpoint/access.js.map +1 -1
  13. package/dist/endpoint/index.d.ts +1 -1
  14. package/dist/endpoint/index.d.ts.map +1 -1
  15. package/dist/endpoint/index.js +68 -17
  16. package/dist/endpoint/index.js.map +1 -1
  17. package/dist/exports/client.d.ts +1 -1
  18. package/dist/exports/client.d.ts.map +1 -1
  19. package/dist/exports/client.js +1 -1
  20. package/dist/exports/client.js.map +1 -1
  21. package/dist/exports/internal.d.ts +2 -0
  22. package/dist/exports/internal.d.ts.map +1 -0
  23. package/dist/exports/internal.js +3 -0
  24. package/dist/exports/internal.js.map +1 -0
  25. package/dist/index.d.ts +2 -2
  26. package/dist/index.d.ts.map +1 -1
  27. package/dist/index.js +15 -20
  28. package/dist/index.js.map +1 -1
  29. package/dist/mcp/buildMcpServer.d.ts +5 -5
  30. package/dist/mcp/buildMcpServer.d.ts.map +1 -1
  31. package/dist/mcp/buildMcpServer.js +145 -80
  32. package/dist/mcp/buildMcpServer.js.map +1 -1
  33. package/dist/mcp/builtin/collections/authTools.d.ts.map +1 -1
  34. package/dist/mcp/builtin/collections/authTools.js +122 -61
  35. package/dist/mcp/builtin/collections/authTools.js.map +1 -1
  36. package/dist/mcp/builtin/collections/countTool.d.ts +2 -0
  37. package/dist/mcp/builtin/collections/countTool.d.ts.map +1 -0
  38. package/dist/mcp/builtin/collections/countTool.js +63 -0
  39. package/dist/mcp/builtin/collections/countTool.js.map +1 -0
  40. package/dist/mcp/builtin/collections/countVersionsTool.d.ts +2 -0
  41. package/dist/mcp/builtin/collections/countVersionsTool.d.ts.map +1 -0
  42. package/dist/mcp/builtin/collections/countVersionsTool.js +60 -0
  43. package/dist/mcp/builtin/collections/countVersionsTool.js.map +1 -0
  44. package/dist/mcp/builtin/collections/createTool.d.ts +1 -1
  45. package/dist/mcp/builtin/collections/createTool.d.ts.map +1 -1
  46. package/dist/mcp/builtin/collections/createTool.js +111 -68
  47. package/dist/mcp/builtin/collections/createTool.js.map +1 -1
  48. package/dist/mcp/builtin/collections/deleteTool.d.ts +1 -1
  49. package/dist/mcp/builtin/collections/deleteTool.d.ts.map +1 -1
  50. package/dist/mcp/builtin/collections/deleteTool.js +51 -61
  51. package/dist/mcp/builtin/collections/deleteTool.js.map +1 -1
  52. package/dist/mcp/builtin/collections/duplicateTool.d.ts +2 -0
  53. package/dist/mcp/builtin/collections/duplicateTool.d.ts.map +1 -0
  54. package/dist/mcp/builtin/collections/duplicateTool.js +86 -0
  55. package/dist/mcp/builtin/collections/duplicateTool.js.map +1 -0
  56. package/dist/mcp/builtin/collections/fileInput.d.ts +28 -0
  57. package/dist/mcp/builtin/collections/fileInput.d.ts.map +1 -0
  58. package/dist/mcp/builtin/collections/fileInput.js +123 -0
  59. package/dist/mcp/builtin/collections/fileInput.js.map +1 -0
  60. package/dist/mcp/builtin/collections/fileInput.spec.js +86 -0
  61. package/dist/mcp/builtin/collections/fileInput.spec.js.map +1 -0
  62. package/dist/mcp/builtin/collections/findDistinctTool.d.ts +2 -0
  63. package/dist/mcp/builtin/collections/findDistinctTool.d.ts.map +1 -0
  64. package/dist/mcp/builtin/collections/findDistinctTool.js +77 -0
  65. package/dist/mcp/builtin/collections/findDistinctTool.js.map +1 -0
  66. package/dist/mcp/builtin/collections/findTool.d.ts +1 -1
  67. package/dist/mcp/builtin/collections/findTool.d.ts.map +1 -1
  68. package/dist/mcp/builtin/collections/findTool.js +55 -72
  69. package/dist/mcp/builtin/collections/findTool.js.map +1 -1
  70. package/dist/mcp/builtin/collections/findVersionByIDTool.d.ts +2 -0
  71. package/dist/mcp/builtin/collections/findVersionByIDTool.d.ts.map +1 -0
  72. package/dist/mcp/builtin/collections/findVersionByIDTool.js +74 -0
  73. package/dist/mcp/builtin/collections/findVersionByIDTool.js.map +1 -0
  74. package/dist/mcp/builtin/collections/findVersionsTool.d.ts +2 -0
  75. package/dist/mcp/builtin/collections/findVersionsTool.d.ts.map +1 -0
  76. package/dist/mcp/builtin/collections/findVersionsTool.js +84 -0
  77. package/dist/mcp/builtin/collections/findVersionsTool.js.map +1 -0
  78. package/dist/mcp/builtin/collections/getCollectionSchemaTool.d.ts +2 -0
  79. package/dist/mcp/builtin/collections/getCollectionSchemaTool.d.ts.map +1 -0
  80. package/dist/mcp/builtin/collections/getCollectionSchemaTool.js +87 -0
  81. package/dist/mcp/builtin/collections/getCollectionSchemaTool.js.map +1 -0
  82. package/dist/mcp/builtin/collections/restoreVersionTool.d.ts +2 -0
  83. package/dist/mcp/builtin/collections/restoreVersionTool.d.ts.map +1 -0
  84. package/dist/mcp/builtin/collections/restoreVersionTool.js +69 -0
  85. package/dist/mcp/builtin/collections/restoreVersionTool.js.map +1 -0
  86. package/dist/mcp/builtin/collections/updateTool.d.ts +1 -1
  87. package/dist/mcp/builtin/collections/updateTool.d.ts.map +1 -1
  88. package/dist/mcp/builtin/collections/updateTool.js +104 -136
  89. package/dist/mcp/builtin/collections/updateTool.js.map +1 -1
  90. package/dist/mcp/builtin/collections/uploadInstructionsTool.d.ts +2 -0
  91. package/dist/mcp/builtin/collections/uploadInstructionsTool.d.ts.map +1 -0
  92. package/dist/mcp/builtin/collections/uploadInstructionsTool.js +55 -0
  93. package/dist/mcp/builtin/collections/uploadInstructionsTool.js.map +1 -0
  94. package/dist/mcp/builtin/formatEntityError.d.ts +16 -0
  95. package/dist/mcp/builtin/formatEntityError.d.ts.map +1 -0
  96. package/dist/mcp/builtin/formatEntityError.js +55 -0
  97. package/dist/mcp/builtin/formatEntityError.js.map +1 -0
  98. package/dist/mcp/builtin/getConfigInfoTool.d.ts +2 -0
  99. package/dist/mcp/builtin/getConfigInfoTool.d.ts.map +1 -0
  100. package/dist/mcp/builtin/getConfigInfoTool.js +69 -0
  101. package/dist/mcp/builtin/getConfigInfoTool.js.map +1 -0
  102. package/dist/mcp/builtin/globals/countVersionsTool.d.ts +2 -0
  103. package/dist/mcp/builtin/globals/countVersionsTool.d.ts.map +1 -0
  104. package/dist/mcp/builtin/globals/countVersionsTool.js +60 -0
  105. package/dist/mcp/builtin/globals/countVersionsTool.js.map +1 -0
  106. package/dist/mcp/builtin/globals/findTool.d.ts.map +1 -1
  107. package/dist/mcp/builtin/globals/findTool.js +27 -36
  108. package/dist/mcp/builtin/globals/findTool.js.map +1 -1
  109. package/dist/mcp/builtin/globals/findVersionByIDTool.d.ts +2 -0
  110. package/dist/mcp/builtin/globals/findVersionByIDTool.d.ts.map +1 -0
  111. package/dist/mcp/builtin/globals/findVersionByIDTool.js +68 -0
  112. package/dist/mcp/builtin/globals/findVersionByIDTool.js.map +1 -0
  113. package/dist/mcp/builtin/globals/findVersionsTool.d.ts +2 -0
  114. package/dist/mcp/builtin/globals/findVersionsTool.d.ts.map +1 -0
  115. package/dist/mcp/builtin/globals/findVersionsTool.js +78 -0
  116. package/dist/mcp/builtin/globals/findVersionsTool.js.map +1 -0
  117. package/dist/mcp/builtin/globals/getGlobalSchemaTool.d.ts +2 -0
  118. package/dist/mcp/builtin/globals/getGlobalSchemaTool.d.ts.map +1 -0
  119. package/dist/mcp/builtin/globals/getGlobalSchemaTool.js +65 -0
  120. package/dist/mcp/builtin/globals/getGlobalSchemaTool.js.map +1 -0
  121. package/dist/mcp/builtin/globals/restoreVersionTool.d.ts +2 -0
  122. package/dist/mcp/builtin/globals/restoreVersionTool.d.ts.map +1 -0
  123. package/dist/mcp/builtin/globals/restoreVersionTool.js +70 -0
  124. package/dist/mcp/builtin/globals/restoreVersionTool.js.map +1 -0
  125. package/dist/mcp/builtin/globals/updateTool.d.ts.map +1 -1
  126. package/dist/mcp/builtin/globals/updateTool.js +44 -62
  127. package/dist/mcp/builtin/globals/updateTool.js.map +1 -1
  128. package/dist/mcp/builtinTools.d.ts +150 -19
  129. package/dist/mcp/builtinTools.d.ts.map +1 -1
  130. package/dist/mcp/builtinTools.js +125 -20
  131. package/dist/mcp/builtinTools.js.map +1 -1
  132. package/dist/mcp/sanitizeMCPConfig.d.ts +0 -1
  133. package/dist/mcp/sanitizeMCPConfig.d.ts.map +1 -1
  134. package/dist/mcp/sanitizeMCPConfig.js +124 -58
  135. package/dist/mcp/sanitizeMCPConfig.js.map +1 -1
  136. package/dist/stdio.d.ts +3 -3
  137. package/dist/stdio.d.ts.map +1 -1
  138. package/dist/stdio.js +84 -46
  139. package/dist/stdio.js.map +1 -1
  140. package/dist/types.d.ts +114 -112
  141. package/dist/types.d.ts.map +1 -1
  142. package/dist/types.js +2 -4
  143. package/dist/types.js.map +1 -1
  144. package/dist/utils/camelCase.d.ts.map +1 -1
  145. package/dist/utils/getPluginConfig.d.ts +1 -1
  146. package/dist/utils/getPluginConfig.js +1 -1
  147. package/dist/utils/getPluginConfig.js.map +1 -1
  148. package/dist/utils/resolveProjectRoot.d.ts.map +1 -1
  149. package/dist/utils/toStandardSchema.d.ts.map +1 -1
  150. package/package.json +11 -18
  151. package/src/defaultAccess.ts +3 -0
  152. package/src/endpoint/access.ts +80 -101
  153. package/src/endpoint/index.ts +58 -16
  154. package/src/exports/client.ts +2 -1
  155. package/src/exports/internal.ts +1 -0
  156. package/src/index.ts +12 -20
  157. package/src/mcp/buildMcpServer.ts +179 -114
  158. package/src/mcp/builtin/collections/authTools.ts +119 -75
  159. package/src/mcp/builtin/collections/countTool.ts +61 -0
  160. package/src/mcp/builtin/collections/countVersionsTool.ts +60 -0
  161. package/src/mcp/builtin/collections/createTool.ts +104 -88
  162. package/src/mcp/builtin/collections/deleteTool.ts +48 -74
  163. package/src/mcp/builtin/collections/duplicateTool.ts +83 -0
  164. package/src/mcp/builtin/collections/fileInput.spec.ts +93 -0
  165. package/src/mcp/builtin/collections/fileInput.ts +169 -0
  166. package/src/mcp/builtin/collections/findDistinctTool.ts +67 -0
  167. package/src/mcp/builtin/collections/findTool.ts +55 -108
  168. package/src/mcp/builtin/collections/findVersionByIDTool.ts +66 -0
  169. package/src/mcp/builtin/collections/findVersionsTool.ts +83 -0
  170. package/src/mcp/builtin/collections/getCollectionSchemaTool.ts +80 -0
  171. package/src/mcp/builtin/collections/restoreVersionTool.ts +65 -0
  172. package/src/mcp/builtin/collections/updateTool.ts +101 -142
  173. package/src/mcp/builtin/collections/uploadInstructionsTool.ts +64 -0
  174. package/src/mcp/builtin/formatEntityError.ts +77 -0
  175. package/src/mcp/builtin/getConfigInfoTool.ts +68 -0
  176. package/src/mcp/builtin/globals/countVersionsTool.ts +60 -0
  177. package/src/mcp/builtin/globals/findTool.ts +27 -57
  178. package/src/mcp/builtin/globals/findVersionByIDTool.ts +64 -0
  179. package/src/mcp/builtin/globals/findVersionsTool.ts +69 -0
  180. package/src/mcp/builtin/globals/getGlobalSchemaTool.ts +63 -0
  181. package/src/mcp/builtin/globals/restoreVersionTool.ts +68 -0
  182. package/src/mcp/builtin/globals/updateTool.ts +51 -79
  183. package/src/mcp/builtinTools.ts +118 -41
  184. package/src/mcp/sanitizeMCPConfig.ts +120 -78
  185. package/src/stdio.ts +79 -46
  186. package/src/types.ts +130 -117
  187. package/src/utils/getPluginConfig.ts +1 -1
  188. package/dist/@types/assets.d.js +0 -2
  189. package/dist/@types/assets.d.js.map +0 -1
  190. package/dist/collection/getAccessField.d.ts +0 -12
  191. package/dist/collection/getAccessField.d.ts.map +0 -1
  192. package/dist/collection/getAccessField.js +0 -57
  193. package/dist/collection/getAccessField.js.map +0 -1
  194. package/dist/collection/index.d.ts +0 -6
  195. package/dist/collection/index.d.ts.map +0 -1
  196. package/dist/collection/index.js +0 -60
  197. package/dist/collection/index.js.map +0 -1
  198. package/dist/components/AccessField/index.client.d.ts +0 -10
  199. package/dist/components/AccessField/index.client.d.ts.map +0 -1
  200. package/dist/components/AccessField/index.client.js +0 -305
  201. package/dist/components/AccessField/index.client.js.map +0 -1
  202. package/dist/components/AccessField/index.css +0 -93
  203. package/dist/utils/getVirtualFieldNames.d.ts +0 -14
  204. package/dist/utils/getVirtualFieldNames.d.ts.map +0 -1
  205. package/dist/utils/getVirtualFieldNames.js +0 -35
  206. package/dist/utils/getVirtualFieldNames.js.map +0 -1
  207. package/dist/utils/localAPIDefaults.d.ts +0 -20
  208. package/dist/utils/localAPIDefaults.d.ts.map +0 -1
  209. package/dist/utils/localAPIDefaults.js +0 -19
  210. package/dist/utils/localAPIDefaults.js.map +0 -1
  211. package/dist/utils/schemaConversion/buildToolInput.d.ts +0 -29
  212. package/dist/utils/schemaConversion/buildToolInput.d.ts.map +0 -1
  213. package/dist/utils/schemaConversion/buildToolInput.js +0 -51
  214. package/dist/utils/schemaConversion/buildToolInput.js.map +0 -1
  215. package/dist/utils/schemaConversion/removeVirtualFieldsFromSchema.d.ts +0 -7
  216. package/dist/utils/schemaConversion/removeVirtualFieldsFromSchema.d.ts.map +0 -1
  217. package/dist/utils/schemaConversion/removeVirtualFieldsFromSchema.js +0 -20
  218. package/dist/utils/schemaConversion/removeVirtualFieldsFromSchema.js.map +0 -1
  219. package/dist/utils/schemaConversion/sanitizeEntitySchema.d.ts +0 -15
  220. package/dist/utils/schemaConversion/sanitizeEntitySchema.d.ts.map +0 -1
  221. package/dist/utils/schemaConversion/sanitizeEntitySchema.js +0 -464
  222. package/dist/utils/schemaConversion/sanitizeEntitySchema.js.map +0 -1
  223. package/dist/utils/schemaConversion/sanitizeEntitySchema.spec.js +0 -158
  224. package/dist/utils/schemaConversion/sanitizeEntitySchema.spec.js.map +0 -1
  225. package/dist/utils/transformPointDataToPayload.d.ts +0 -7
  226. package/dist/utils/transformPointDataToPayload.d.ts.map +0 -1
  227. package/dist/utils/transformPointDataToPayload.js +0 -28
  228. package/dist/utils/transformPointDataToPayload.js.map +0 -1
  229. package/src/@types/assets.d.ts +0 -3
  230. package/src/collection/getAccessField.ts +0 -64
  231. package/src/collection/index.ts +0 -64
  232. package/src/components/AccessField/index.client.tsx +0 -344
  233. package/src/components/AccessField/index.css +0 -93
  234. package/src/utils/getVirtualFieldNames.ts +0 -53
  235. package/src/utils/localAPIDefaults.ts +0 -22
  236. package/src/utils/schemaConversion/buildToolInput.ts +0 -68
  237. package/src/utils/schemaConversion/removeVirtualFieldsFromSchema.ts +0 -27
  238. package/src/utils/schemaConversion/sanitizeEntitySchema.spec.ts +0 -103
  239. package/src/utils/schemaConversion/sanitizeEntitySchema.ts +0 -529
  240. package/src/utils/transformPointDataToPayload.ts +0 -40
@@ -1,344 +0,0 @@
1
- 'use client'
2
-
3
- import type { JSONFieldClientProps } from 'payload'
4
-
5
- import { CheckboxInput, Collapsible, useField } from '@payloadcms/ui'
6
- import React from 'react'
7
-
8
- import type { ClientMCPPluginConfig, MCPAPIKeysDocAccessTree } from '../../types.js'
9
-
10
- import './index.css'
11
-
12
- const baseClass = 'mcp-access-field'
13
-
14
- type ClientItem = ClientMCPPluginConfig['items'][number]
15
- type ScopeKey = 'collections' | 'globals'
16
- type FlatKey = 'prompts' | 'resources' | 'tools'
17
-
18
- type Props = {
19
- pluginConfig: ClientMCPPluginConfig
20
- } & JSONFieldClientProps
21
-
22
- /** Drop a key from an object and return a new object — or `undefined` if it'd be empty. */
23
- const without = <T extends Record<string, unknown>>(
24
- obj: T | undefined,
25
- key: string,
26
- ): T | undefined => {
27
- if (!obj || !(key in obj)) {
28
- return obj
29
- }
30
- const { [key]: _omitted, ...rest } = obj
31
- return Object.keys(rest).length === 0 ? undefined : (rest as T)
32
- }
33
-
34
- const setKey = <T extends Record<string, unknown>>(
35
- obj: T | undefined,
36
- key: string,
37
- value: unknown,
38
- ): T => ({ ...(obj ?? {}), [key]: value }) as T
39
-
40
- export const AccessField: React.FC<Props> = ({ path, pluginConfig }) => {
41
- const { setValue, value } = useField<MCPAPIKeysDocAccessTree>({ path })
42
- const access = value ?? {}
43
-
44
- // Bucket items for rendering. (Bucketing is cheap and runs once per render;
45
- // memoizing would mean managing inputs/refs for marginal benefit.)
46
- const collectionsBySlug: Record<string, ClientItem[]> = {}
47
- const globalsBySlug: Record<string, ClientItem[]> = {}
48
- const tools: ClientItem[] = []
49
- const prompts: ClientItem[] = []
50
- const resources: ClientItem[] = []
51
- for (const item of pluginConfig.items) {
52
- switch (item.type) {
53
- case 'collectionTool':
54
- ;(collectionsBySlug[item.collectionSlug!] ??= []).push(item)
55
- break
56
- case 'globalTool':
57
- ;(globalsBySlug[item.globalSlug!] ??= []).push(item)
58
- break
59
- case 'prompt':
60
- prompts.push(item)
61
- break
62
- case 'resource':
63
- resources.push(item)
64
- break
65
- case 'tool':
66
- tools.push(item)
67
- break
68
- }
69
- }
70
-
71
- const isScopedAllowed = (scope: ScopeKey, slug: string, key: string): boolean =>
72
- access[scope]?.[slug]?.[key] !== false
73
-
74
- const isFlatAllowed = (scope: FlatKey, key: string): boolean => access[scope]?.[key] !== false
75
-
76
- const toggleScoped = (scope: ScopeKey, slug: string, key: string, allow: boolean) => {
77
- if (allow) {
78
- const slugBucket = without(access[scope]?.[slug], key)
79
- const scopeBucket = slugBucket
80
- ? setKey(access[scope], slug, slugBucket)
81
- : without(access[scope], slug)
82
- setValue(scopeBucket ? setKey(access, scope, scopeBucket) : (without(access, scope) ?? {}))
83
- } else {
84
- setValue(
85
- setKey(
86
- access,
87
- scope,
88
- setKey(access[scope], slug, setKey(access[scope]?.[slug], key, false)),
89
- ),
90
- )
91
- }
92
- }
93
-
94
- const toggleFlat = (scope: FlatKey, key: string, allow: boolean) => {
95
- if (allow) {
96
- const bucket = without(access[scope], key)
97
- setValue(bucket ? setKey(access, scope, bucket) : (without(access, scope) ?? {}))
98
- } else {
99
- setValue(setKey(access, scope, setKey(access[scope], key, false)))
100
- }
101
- }
102
-
103
- const setAllScoped = (scope: ScopeKey, slug: string, leaves: ClientItem[], allow: boolean) => {
104
- if (allow) {
105
- const scopeBucket = without(access[scope], slug)
106
- setValue(scopeBucket ? setKey(access, scope, scopeBucket) : (without(access, scope) ?? {}))
107
- } else {
108
- const slugBucket = leaves.reduce<Record<string, boolean>>(
109
- (acc, leaf) => ({ ...acc, [leaf.key]: false }),
110
- {},
111
- )
112
- setValue(setKey(access, scope, setKey(access[scope], slug, slugBucket)))
113
- }
114
- }
115
-
116
- const setAllFlat = (scope: FlatKey, leaves: ClientItem[], allow: boolean) => {
117
- if (allow) {
118
- setValue(without(access, scope) ?? {})
119
- } else {
120
- const bucket = leaves.reduce<Record<string, boolean>>(
121
- (acc, leaf) => ({ ...acc, [leaf.key]: false }),
122
- {},
123
- )
124
- setValue(setKey(access, scope, bucket))
125
- }
126
- }
127
-
128
- const collectionSlugs = Object.keys(collectionsBySlug)
129
- const globalSlugs = Object.keys(globalsBySlug)
130
-
131
- return (
132
- <div className={baseClass}>
133
- {collectionSlugs.length > 0 && (
134
- <section className={`${baseClass}__section`}>
135
- <header className={`${baseClass}__section-header`}>
136
- {/* TODO: needs i18n once design is finalized */}
137
- <h4>Collection-level permissions</h4>
138
- {/* TODO: needs i18n once design is finalized */}
139
- <p>Allow MCP clients to perform the following actions within these collections:</p>
140
- </header>
141
- {collectionSlugs.map((slug) => {
142
- const leaves = collectionsBySlug[slug]!
143
- return (
144
- <Collapsible
145
- actions={
146
- <GroupActions
147
- onSetAll={(allow) => setAllScoped('collections', slug, leaves, allow)}
148
- />
149
- }
150
- className={`${baseClass}__group`}
151
- header={<span className={`${baseClass}__group-label`}>{titleCase(slug)}</span>}
152
- initCollapsed
153
- key={`collection-${slug}`}
154
- >
155
- <ul className={`${baseClass}__list`}>
156
- {leaves.map((leaf) => (
157
- <li key={leaf.key}>
158
- <CheckboxInput
159
- checked={isScopedAllowed('collections', slug, leaf.key)}
160
- id={`${path}.collections.${slug}.${leaf.key}`}
161
- label={leaf.label}
162
- onToggle={(e) =>
163
- toggleScoped('collections', slug, leaf.key, e.target.checked)
164
- }
165
- tooltip={leaf.description}
166
- />
167
- </li>
168
- ))}
169
- </ul>
170
- </Collapsible>
171
- )
172
- })}
173
- </section>
174
- )}
175
-
176
- {globalSlugs.length > 0 && (
177
- <section className={`${baseClass}__section`}>
178
- <header className={`${baseClass}__section-header`}>
179
- {/* TODO: needs i18n once design is finalized */}
180
- <h4>Global-level permissions</h4>
181
- {/* TODO: needs i18n once design is finalized */}
182
- <p>Allow MCP clients to perform the following actions on these globals:</p>
183
- </header>
184
- {globalSlugs.map((slug) => {
185
- const leaves = globalsBySlug[slug]!
186
- return (
187
- <Collapsible
188
- actions={
189
- <GroupActions
190
- onSetAll={(allow) => setAllScoped('globals', slug, leaves, allow)}
191
- />
192
- }
193
- className={`${baseClass}__group`}
194
- header={<span className={`${baseClass}__group-label`}>{titleCase(slug)}</span>}
195
- initCollapsed
196
- key={`global-${slug}`}
197
- >
198
- <ul className={`${baseClass}__list`}>
199
- {leaves.map((leaf) => (
200
- <li key={leaf.key}>
201
- <CheckboxInput
202
- checked={isScopedAllowed('globals', slug, leaf.key)}
203
- id={`${path}.globals.${slug}.${leaf.key}`}
204
- label={leaf.label}
205
- onToggle={(e) => toggleScoped('globals', slug, leaf.key, e.target.checked)}
206
- tooltip={leaf.description}
207
- />
208
- </li>
209
- ))}
210
- </ul>
211
- </Collapsible>
212
- )
213
- })}
214
- </section>
215
- )}
216
-
217
- {(tools.length > 0 || prompts.length > 0 || resources.length > 0) && (
218
- <section className={`${baseClass}__section`}>
219
- <header className={`${baseClass}__section-header`}>
220
- {/* TODO: needs i18n once design is finalized */}
221
- <h4>Project-level permissions</h4>
222
- {/* TODO: needs i18n once design is finalized */}
223
- <p>Cross-cutting tools, prompts, and resources not scoped to a single collection.</p>
224
- </header>
225
- {tools.length > 0 && (
226
- <Collapsible
227
- actions={<GroupActions onSetAll={(allow) => setAllFlat('tools', tools, allow)} />}
228
- className={`${baseClass}__group`}
229
- header={
230
- /* TODO: needs i18n once design is finalized */
231
- <span className={`${baseClass}__group-label`}>Tools</span>
232
- }
233
- initCollapsed
234
- >
235
- <ul className={`${baseClass}__list`}>
236
- {tools.map((leaf) => (
237
- <li key={leaf.key}>
238
- <CheckboxInput
239
- checked={isFlatAllowed('tools', leaf.key)}
240
- id={`${path}.tools.${leaf.key}`}
241
- label={leaf.label}
242
- onToggle={(e) => toggleFlat('tools', leaf.key, e.target.checked)}
243
- tooltip={leaf.description}
244
- />
245
- </li>
246
- ))}
247
- </ul>
248
- </Collapsible>
249
- )}
250
- {prompts.length > 0 && (
251
- <Collapsible
252
- actions={<GroupActions onSetAll={(allow) => setAllFlat('prompts', prompts, allow)} />}
253
- className={`${baseClass}__group`}
254
- header={
255
- /* TODO: needs i18n once design is finalized */
256
- <span className={`${baseClass}__group-label`}>Prompts</span>
257
- }
258
- initCollapsed
259
- >
260
- <ul className={`${baseClass}__list`}>
261
- {prompts.map((leaf) => (
262
- <li key={leaf.key}>
263
- <CheckboxInput
264
- checked={isFlatAllowed('prompts', leaf.key)}
265
- id={`${path}.prompts.${leaf.key}`}
266
- label={leaf.label}
267
- onToggle={(e) => toggleFlat('prompts', leaf.key, e.target.checked)}
268
- tooltip={leaf.description}
269
- />
270
- </li>
271
- ))}
272
- </ul>
273
- </Collapsible>
274
- )}
275
- {resources.length > 0 && (
276
- <Collapsible
277
- actions={
278
- <GroupActions onSetAll={(allow) => setAllFlat('resources', resources, allow)} />
279
- }
280
- className={`${baseClass}__group`}
281
- header={
282
- /* TODO: needs i18n once design is finalized */
283
- <span className={`${baseClass}__group-label`}>Resources</span>
284
- }
285
- initCollapsed
286
- >
287
- <ul className={`${baseClass}__list`}>
288
- {resources.map((leaf) => (
289
- <li key={leaf.key}>
290
- <CheckboxInput
291
- checked={isFlatAllowed('resources', leaf.key)}
292
- id={`${path}.resources.${leaf.key}`}
293
- label={leaf.label}
294
- onToggle={(e) => toggleFlat('resources', leaf.key, e.target.checked)}
295
- tooltip={leaf.description}
296
- />
297
- </li>
298
- ))}
299
- </ul>
300
- </Collapsible>
301
- )}
302
- </section>
303
- )}
304
- </div>
305
- )
306
- }
307
-
308
- const GroupActions: React.FC<{ onSetAll: (allow: boolean) => void }> = ({ onSetAll }) => (
309
- // TODO: button labels + aria-labels need i18n once design is finalized
310
- <div className={`${baseClass}__group-actions`}>
311
- <button
312
- aria-label="Select all"
313
- className={`${baseClass}__action`}
314
- onClick={(e) => {
315
- e.stopPropagation()
316
- onSetAll(true)
317
- }}
318
- title="Select all"
319
- type="button"
320
- >
321
- all
322
- </button>
323
- <span aria-hidden className={`${baseClass}__action-sep`}>
324
- /
325
- </span>
326
- <button
327
- aria-label="Clear all"
328
- className={`${baseClass}__action`}
329
- onClick={(e) => {
330
- e.stopPropagation()
331
- onSetAll(false)
332
- }}
333
- title="Clear all"
334
- type="button"
335
- >
336
- none
337
- </button>
338
- </div>
339
- )
340
-
341
- const titleCase = (slug: string): string =>
342
- slug.replace(/(^|[-_])(.)/g, (_, sep: string, ch: string) =>
343
- sep ? ` ${ch.toUpperCase()}` : ch.toUpperCase(),
344
- )
@@ -1,93 +0,0 @@
1
- @layer payload-default {
2
- .mcp-access-field {
3
- display: flex;
4
- flex-direction: column;
5
- gap: var(--base);
6
- }
7
-
8
- .mcp-access-field__section {
9
- display: flex;
10
- flex-direction: column;
11
- gap: calc(var(--base) / 2);
12
- padding-bottom: var(--base);
13
- /* Full-bleed separator: extend past the sidebar's horizontal gutter so the
14
- border-block-end spans the entire sidebar width. */
15
- margin-inline-start: calc(-1 * var(--sidebar-gutter-h-left, var(--gutter-h)));
16
- margin-inline-end: calc(-1 * var(--sidebar-gutter-h-right, var(--gutter-h)));
17
- padding-inline-start: var(--sidebar-gutter-h-left, var(--gutter-h));
18
- padding-inline-end: var(--sidebar-gutter-h-right, var(--gutter-h));
19
- border-block-end: 1px solid var(--theme-elevation-100);
20
- }
21
-
22
- .mcp-access-field__section:last-child {
23
- border-block-end: none;
24
- }
25
-
26
- .mcp-access-field__section-header {
27
- display: flex;
28
- flex-direction: column;
29
- }
30
-
31
- .mcp-access-field__section-header h4 {
32
- margin: 0;
33
- color: var(--color-text);
34
- font-family: var(--text-heading-small-font-family);
35
- font-size: var(--text-heading-small-font-size);
36
- font-weight: var(--text-heading-small-font-weight);
37
- line-height: var(--text-heading-small-line-height);
38
- letter-spacing: var(--text-heading-small-letter-spacing);
39
- }
40
-
41
- .mcp-access-field__section-header p {
42
- margin: 0;
43
- color: var(--color-text-secondary);
44
- font-family: var(--text-body-medium-font-family);
45
- font-size: var(--text-body-medium-font-size);
46
- font-weight: var(--text-body-medium-font-weight);
47
- line-height: var(--text-body-medium-line-height);
48
- letter-spacing: var(--text-body-medium-letter-spacing);
49
- }
50
-
51
- .mcp-access-field__group {
52
- margin-block-end: calc(var(--base) / 2);
53
- }
54
-
55
- .mcp-access-field__group-label {
56
- font-weight: 600;
57
- }
58
-
59
- .mcp-access-field__group-actions {
60
- display: flex;
61
- align-items: center;
62
- gap: calc(var(--base) / 6);
63
- }
64
-
65
- .mcp-access-field__action {
66
- appearance: none;
67
- background: none;
68
- border: none;
69
- color: var(--theme-elevation-500);
70
- cursor: pointer;
71
- font-size: 0.75rem;
72
- padding: 0;
73
- }
74
-
75
- .mcp-access-field__action:hover {
76
- color: var(--theme-text);
77
- text-decoration: underline;
78
- }
79
-
80
- .mcp-access-field__action-sep {
81
- color: var(--theme-elevation-300);
82
- font-size: 0.75rem;
83
- }
84
-
85
- .mcp-access-field__list {
86
- list-style: none;
87
- margin: 0;
88
- padding: 0;
89
- display: flex;
90
- flex-direction: column;
91
- gap: calc(var(--base) / 3);
92
- }
93
- }
@@ -1,53 +0,0 @@
1
- import type { SanitizedConfig } from 'payload'
2
-
3
- import { fieldIsVirtual } from 'payload/shared'
4
-
5
- /**
6
- * Returns the names of all top-level virtual fields for a given collection slug.
7
- */
8
- export function getCollectionVirtualFieldNames(config: SanitizedConfig, slug: string): string[] {
9
- const collection = config.collections.find((c) => c.slug === slug)
10
-
11
- if (!collection) {
12
- return []
13
- }
14
-
15
- return collection.flattenedFields
16
- .filter((field) => 'name' in field && fieldIsVirtual(field))
17
- .map((field) => (field as { name: string }).name)
18
- }
19
-
20
- /**
21
- * Returns the names of all top-level virtual fields for a given global slug.
22
- */
23
- export function getGlobalVirtualFieldNames(config: SanitizedConfig, slug: string): string[] {
24
- const global = config.globals.find((g) => g.slug === slug)
25
-
26
- if (!global) {
27
- return []
28
- }
29
-
30
- return global.flattenedFields
31
- .filter((field) => 'name' in field && fieldIsVirtual(field))
32
- .map((field) => (field as { name: string }).name)
33
- }
34
-
35
- /**
36
- * Strips virtual field values from a data object given a list of virtual field names.
37
- */
38
- export function stripVirtualFields(
39
- data: Record<string, unknown>,
40
- virtualFieldNames: string[],
41
- ): Record<string, unknown> {
42
- if (virtualFieldNames.length === 0) {
43
- return data
44
- }
45
-
46
- const stripped = { ...data }
47
-
48
- for (const name of virtualFieldNames) {
49
- delete stripped[name]
50
- }
51
-
52
- return stripped
53
- }
@@ -1,22 +0,0 @@
1
- import type { AuthorizedMCP } from '../types.js'
2
-
3
- /**
4
- * Returns the `user` and `overrideAccess` arguments every Payload local API call
5
- * should receive when initiated from an MCP request. Spread the result into the
6
- * call's arg object so the two pieces of caller state can't drift apart.
7
- *
8
- * @example
9
- * ```ts
10
- * await req.payload.create({
11
- * collection: 'posts',
12
- * data,
13
- * ...localAPIDefaults(authorizedMCP),
14
- * })
15
- * ```
16
- */
17
- export const localAPIDefaults = (
18
- authorizedMCP: AuthorizedMCP,
19
- ): { overrideAccess: boolean; user: AuthorizedMCP['user'] } => ({
20
- overrideAccess: authorizedMCP.overrideAccess,
21
- user: authorizedMCP.user,
22
- })
@@ -1,68 +0,0 @@
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
- }
@@ -1,27 +0,0 @@
1
- import type { JsonSchemaType } from '../../types.js'
2
-
3
- /**
4
- * Removes virtual fields from a JSON Schema by name so they don't appear
5
- * in the generated MCP tool input schema.
6
- */
7
- export function removeVirtualFieldsFromSchema(
8
- schema: JsonSchemaType,
9
- virtualFieldNames: string[],
10
- ): JsonSchemaType {
11
- if (virtualFieldNames.length === 0) {
12
- return schema
13
- }
14
-
15
- for (const name of virtualFieldNames) {
16
- delete schema?.properties?.[name]
17
- }
18
-
19
- if (Array.isArray(schema.required)) {
20
- schema.required = schema.required.filter((field) => !virtualFieldNames.includes(field))
21
- if (schema.required.length === 0) {
22
- delete schema.required
23
- }
24
- }
25
-
26
- return schema
27
- }