payload-mcp-toolkit 0.8.0 → 0.9.0

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 (101) hide show
  1. package/README.md +100 -237
  2. package/dist/api-keys.js +16 -0
  3. package/dist/api-keys.js.map +1 -1
  4. package/dist/auth-strategy.js +49 -49
  5. package/dist/auth-strategy.js.map +1 -1
  6. package/dist/components/AgentConnectPill.d.ts +3 -0
  7. package/dist/components/AgentConnectPill.js +121 -0
  8. package/dist/components/AgentConnectPill.js.map +1 -0
  9. package/dist/components/CollectionScopesMatrix.js.map +1 -1
  10. package/dist/components/ConsentPermissions.d.ts +10 -0
  11. package/dist/components/ConsentPermissions.js +165 -0
  12. package/dist/components/ConsentPermissions.js.map +1 -0
  13. package/dist/components/GlobalScopesMatrix.js.map +1 -1
  14. package/dist/components/OAuthView.d.ts +4 -0
  15. package/dist/components/OAuthView.js +269 -0
  16. package/dist/components/OAuthView.js.map +1 -0
  17. package/dist/components/ScopesTable.d.ts +28 -0
  18. package/dist/components/ScopesTable.js +165 -130
  19. package/dist/components/ScopesTable.js.map +1 -1
  20. package/dist/components/agentInstructions.d.ts +2 -0
  21. package/dist/components/agentInstructions.js +34 -0
  22. package/dist/components/agentInstructions.js.map +1 -0
  23. package/dist/components/index.d.ts +2 -0
  24. package/dist/components/index.js +2 -0
  25. package/dist/components/index.js.map +1 -1
  26. package/dist/components/oauth.css +111 -0
  27. package/dist/conflict-detection.js +13 -13
  28. package/dist/conflict-detection.js.map +1 -1
  29. package/dist/draft-workflow.js +26 -26
  30. package/dist/draft-workflow.js.map +1 -1
  31. package/dist/endpoint.d.ts +5 -0
  32. package/dist/endpoint.js +21 -13
  33. package/dist/endpoint.js.map +1 -1
  34. package/dist/hash.js +15 -15
  35. package/dist/hash.js.map +1 -1
  36. package/dist/index.d.ts +2 -0
  37. package/dist/index.js +67 -3
  38. package/dist/index.js.map +1 -1
  39. package/dist/introspection.js +47 -47
  40. package/dist/introspection.js.map +1 -1
  41. package/dist/oauth-permissions.d.ts +52 -0
  42. package/dist/oauth-permissions.js +100 -0
  43. package/dist/oauth-permissions.js.map +1 -0
  44. package/dist/oauth-store.d.ts +19 -0
  45. package/dist/oauth-store.js +122 -0
  46. package/dist/oauth-store.js.map +1 -0
  47. package/dist/oauth.d.ts +19 -0
  48. package/dist/oauth.js +523 -0
  49. package/dist/oauth.js.map +1 -0
  50. package/dist/prompts.js +5 -5
  51. package/dist/prompts.js.map +1 -1
  52. package/dist/registry.js +7 -1
  53. package/dist/registry.js.map +1 -1
  54. package/dist/resources.js +10 -10
  55. package/dist/resources.js.map +1 -1
  56. package/dist/scope/audit-log.js +9 -9
  57. package/dist/scope/audit-log.js.map +1 -1
  58. package/dist/scope/policy.js +7 -7
  59. package/dist/scope/policy.js.map +1 -1
  60. package/dist/tools/_helpers.d.ts +10 -0
  61. package/dist/tools/_helpers.js +53 -41
  62. package/dist/tools/_helpers.js.map +1 -1
  63. package/dist/tools/_layout-helpers.js +33 -33
  64. package/dist/tools/_layout-helpers.js.map +1 -1
  65. package/dist/tools/create-document.js +20 -19
  66. package/dist/tools/create-document.js.map +1 -1
  67. package/dist/tools/delete-document.js +10 -9
  68. package/dist/tools/delete-document.js.map +1 -1
  69. package/dist/tools/find-document.js +18 -15
  70. package/dist/tools/find-document.js.map +1 -1
  71. package/dist/tools/find-global.js +13 -13
  72. package/dist/tools/find-global.js.map +1 -1
  73. package/dist/tools/global-versions.js +8 -7
  74. package/dist/tools/global-versions.js.map +1 -1
  75. package/dist/tools/patch-global-layout.js +9 -9
  76. package/dist/tools/patch-global-layout.js.map +1 -1
  77. package/dist/tools/patch-layout.js +15 -14
  78. package/dist/tools/patch-layout.js.map +1 -1
  79. package/dist/tools/publish-draft.js +2 -1
  80. package/dist/tools/publish-draft.js.map +1 -1
  81. package/dist/tools/publish-global-draft.js +4 -4
  82. package/dist/tools/publish-global-draft.js.map +1 -1
  83. package/dist/tools/resolve-reference.js.map +1 -1
  84. package/dist/tools/safe-delete.js +14 -14
  85. package/dist/tools/safe-delete.js.map +1 -1
  86. package/dist/tools/schedule-publish.js +21 -20
  87. package/dist/tools/schedule-publish.js.map +1 -1
  88. package/dist/tools/search-content.js +12 -12
  89. package/dist/tools/search-content.js.map +1 -1
  90. package/dist/tools/update-document.js +6 -5
  91. package/dist/tools/update-document.js.map +1 -1
  92. package/dist/tools/update-global.js +9 -9
  93. package/dist/tools/update-global.js.map +1 -1
  94. package/dist/tools/upload-media.js +2 -1
  95. package/dist/tools/upload-media.js.map +1 -1
  96. package/dist/tools/versions.js +10 -8
  97. package/dist/tools/versions.js.map +1 -1
  98. package/dist/types.d.ts +3 -0
  99. package/dist/types.js.map +1 -1
  100. package/docs/oauth.md +96 -0
  101. package/package.json +7 -2
package/dist/hash.js CHANGED
@@ -1,19 +1,19 @@
1
1
  import crypto from 'crypto';
2
- /**
3
- * Computes the HMAC index used to look up an API-key row by its plaintext.
4
- *
5
- * Formula: `HMAC-SHA-256(payloadSecret).update(plaintext)` returned as hex.
6
- *
7
- * This matches the formula used by `@payloadcms/plugin-mcp` v0.3.x and by
8
- * Payload's own `useAPIKey: true` collection auth — keeping the storage shape
9
- * identical so v0.4 can authenticate rows created under v0.3.x without
10
- * re-issuing keys (R11).
2
+ /**
3
+ * Computes the HMAC index used to look up an API-key row by its plaintext.
4
+ *
5
+ * Formula: `HMAC-SHA-256(payloadSecret).update(plaintext)` returned as hex.
6
+ *
7
+ * This matches the formula used by `@payloadcms/plugin-mcp` v0.3.x and by
8
+ * Payload's own `useAPIKey: true` collection auth — keeping the storage shape
9
+ * identical so v0.4 can authenticate rows created under v0.3.x without
10
+ * re-issuing keys (R11).
11
11
  */ export function hashKey(plaintext, payloadSecret) {
12
12
  return crypto.createHmac('sha256', payloadSecret).update(plaintext).digest('hex');
13
13
  }
14
- /**
15
- * Constant-time comparison of two hex-encoded hashes.
16
- * Returns false on any length mismatch without throwing.
14
+ /**
15
+ * Constant-time comparison of two hex-encoded hashes.
16
+ * Returns false on any length mismatch without throwing.
17
17
  */ export function verifyHash(presented, stored) {
18
18
  if (typeof presented !== 'string' || typeof stored !== 'string') return false;
19
19
  if (presented.length !== stored.length) return false;
@@ -23,9 +23,9 @@ import crypto from 'crypto';
23
23
  return crypto.timingSafeEqual(a, b);
24
24
  }
25
25
  const BEARER_PREFIX = 'Bearer ';
26
- /**
27
- * Extracts the plaintext token from an `Authorization: Bearer <token>` header.
28
- * Returns null for any other shape (missing, wrong scheme, empty token).
26
+ /**
27
+ * Extracts the plaintext token from an `Authorization: Bearer <token>` header.
28
+ * Returns null for any other shape (missing, wrong scheme, empty token).
29
29
  */ export function extractBearerToken(headerValue) {
30
30
  if (typeof headerValue !== 'string') return null;
31
31
  if (!headerValue.startsWith(BEARER_PREFIX)) return null;
package/dist/hash.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/hash.ts"],"sourcesContent":["import crypto from 'crypto'\r\n\r\n/**\r\n * Computes the HMAC index used to look up an API-key row by its plaintext.\r\n *\r\n * Formula: `HMAC-SHA-256(payloadSecret).update(plaintext)` returned as hex.\r\n *\r\n * This matches the formula used by `@payloadcms/plugin-mcp` v0.3.x and by\r\n * Payload's own `useAPIKey: true` collection auth — keeping the storage shape\r\n * identical so v0.4 can authenticate rows created under v0.3.x without\r\n * re-issuing keys (R11).\r\n */\r\nexport function hashKey(plaintext: string, payloadSecret: string): string {\r\n return crypto.createHmac('sha256', payloadSecret).update(plaintext).digest('hex')\r\n}\r\n\r\n/**\r\n * Constant-time comparison of two hex-encoded hashes.\r\n * Returns false on any length mismatch without throwing.\r\n */\r\nexport function verifyHash(presented: string, stored: string): boolean {\r\n if (typeof presented !== 'string' || typeof stored !== 'string') return false\r\n if (presented.length !== stored.length) return false\r\n const a = Buffer.from(presented, 'hex')\r\n const b = Buffer.from(stored, 'hex')\r\n if (a.length !== b.length || a.length === 0) return false\r\n return crypto.timingSafeEqual(a, b)\r\n}\r\n\r\nconst BEARER_PREFIX = 'Bearer '\r\n\r\n/**\r\n * Extracts the plaintext token from an `Authorization: Bearer <token>` header.\r\n * Returns null for any other shape (missing, wrong scheme, empty token).\r\n */\r\nexport function extractBearerToken(headerValue: string | null | undefined): string | null {\r\n if (typeof headerValue !== 'string') return null\r\n if (!headerValue.startsWith(BEARER_PREFIX)) return null\r\n const token = headerValue.slice(BEARER_PREFIX.length).trim()\r\n return token.length > 0 ? token : null\r\n}\r\n"],"names":["crypto","hashKey","plaintext","payloadSecret","createHmac","update","digest","verifyHash","presented","stored","length","a","Buffer","from","b","timingSafeEqual","BEARER_PREFIX","extractBearerToken","headerValue","startsWith","token","slice","trim"],"mappings":"AAAA,OAAOA,YAAY,SAAQ;AAE3B;;;;;;;;;CASC,GACD,OAAO,SAASC,QAAQC,SAAiB,EAAEC,aAAqB;IAC9D,OAAOH,OAAOI,UAAU,CAAC,UAAUD,eAAeE,MAAM,CAACH,WAAWI,MAAM,CAAC;AAC7E;AAEA;;;CAGC,GACD,OAAO,SAASC,WAAWC,SAAiB,EAAEC,MAAc;IAC1D,IAAI,OAAOD,cAAc,YAAY,OAAOC,WAAW,UAAU,OAAO;IACxE,IAAID,UAAUE,MAAM,KAAKD,OAAOC,MAAM,EAAE,OAAO;IAC/C,MAAMC,IAAIC,OAAOC,IAAI,CAACL,WAAW;IACjC,MAAMM,IAAIF,OAAOC,IAAI,CAACJ,QAAQ;IAC9B,IAAIE,EAAED,MAAM,KAAKI,EAAEJ,MAAM,IAAIC,EAAED,MAAM,KAAK,GAAG,OAAO;IACpD,OAAOV,OAAOe,eAAe,CAACJ,GAAGG;AACnC;AAEA,MAAME,gBAAgB;AAEtB;;;CAGC,GACD,OAAO,SAASC,mBAAmBC,WAAsC;IACvE,IAAI,OAAOA,gBAAgB,UAAU,OAAO;IAC5C,IAAI,CAACA,YAAYC,UAAU,CAACH,gBAAgB,OAAO;IACnD,MAAMI,QAAQF,YAAYG,KAAK,CAACL,cAAcN,MAAM,EAAEY,IAAI;IAC1D,OAAOF,MAAMV,MAAM,GAAG,IAAIU,QAAQ;AACpC"}
1
+ {"version":3,"sources":["../src/hash.ts"],"sourcesContent":["import crypto from 'crypto'\n\n/**\n * Computes the HMAC index used to look up an API-key row by its plaintext.\n *\n * Formula: `HMAC-SHA-256(payloadSecret).update(plaintext)` returned as hex.\n *\n * This matches the formula used by `@payloadcms/plugin-mcp` v0.3.x and by\n * Payload's own `useAPIKey: true` collection auth — keeping the storage shape\n * identical so v0.4 can authenticate rows created under v0.3.x without\n * re-issuing keys (R11).\n */\nexport function hashKey(plaintext: string, payloadSecret: string): string {\n return crypto.createHmac('sha256', payloadSecret).update(plaintext).digest('hex')\n}\n\n/**\n * Constant-time comparison of two hex-encoded hashes.\n * Returns false on any length mismatch without throwing.\n */\nexport function verifyHash(presented: string, stored: string): boolean {\n if (typeof presented !== 'string' || typeof stored !== 'string') return false\n if (presented.length !== stored.length) return false\n const a = Buffer.from(presented, 'hex')\n const b = Buffer.from(stored, 'hex')\n if (a.length !== b.length || a.length === 0) return false\n return crypto.timingSafeEqual(a, b)\n}\n\nconst BEARER_PREFIX = 'Bearer '\n\n/**\n * Extracts the plaintext token from an `Authorization: Bearer <token>` header.\n * Returns null for any other shape (missing, wrong scheme, empty token).\n */\nexport function extractBearerToken(headerValue: string | null | undefined): string | null {\n if (typeof headerValue !== 'string') return null\n if (!headerValue.startsWith(BEARER_PREFIX)) return null\n const token = headerValue.slice(BEARER_PREFIX.length).trim()\n return token.length > 0 ? token : null\n}\n"],"names":["crypto","hashKey","plaintext","payloadSecret","createHmac","update","digest","verifyHash","presented","stored","length","a","Buffer","from","b","timingSafeEqual","BEARER_PREFIX","extractBearerToken","headerValue","startsWith","token","slice","trim"],"mappings":"AAAA,OAAOA,YAAY,SAAQ;AAE3B;;;;;;;;;CASC,GACD,OAAO,SAASC,QAAQC,SAAiB,EAAEC,aAAqB;IAC9D,OAAOH,OAAOI,UAAU,CAAC,UAAUD,eAAeE,MAAM,CAACH,WAAWI,MAAM,CAAC;AAC7E;AAEA;;;CAGC,GACD,OAAO,SAASC,WAAWC,SAAiB,EAAEC,MAAc;IAC1D,IAAI,OAAOD,cAAc,YAAY,OAAOC,WAAW,UAAU,OAAO;IACxE,IAAID,UAAUE,MAAM,KAAKD,OAAOC,MAAM,EAAE,OAAO;IAC/C,MAAMC,IAAIC,OAAOC,IAAI,CAACL,WAAW;IACjC,MAAMM,IAAIF,OAAOC,IAAI,CAACJ,QAAQ;IAC9B,IAAIE,EAAED,MAAM,KAAKI,EAAEJ,MAAM,IAAIC,EAAED,MAAM,KAAK,GAAG,OAAO;IACpD,OAAOV,OAAOe,eAAe,CAACJ,GAAGG;AACnC;AAEA,MAAME,gBAAgB;AAEtB;;;CAGC,GACD,OAAO,SAASC,mBAAmBC,WAAsC;IACvE,IAAI,OAAOA,gBAAgB,UAAU,OAAO;IAC5C,IAAI,CAACA,YAAYC,UAAU,CAACH,gBAAgB,OAAO;IACnD,MAAMI,QAAQF,YAAYG,KAAK,CAACL,cAAcN,MAAM,EAAEY,IAAI;IAC1D,OAAOF,MAAMV,MAAM,GAAG,IAAIU,QAAQ;AACpC"}
package/dist/index.d.ts CHANGED
@@ -17,6 +17,8 @@ import type { ContentToolkitOptions } from './types';
17
17
  */
18
18
  export declare function mcpToolkitPlugin(options?: ContentToolkitOptions): Plugin;
19
19
  export { jsonResponse, textResponse } from './tools/_helpers';
20
+ export type { OAuthOptions } from './oauth';
21
+ export { pruneOAuthRecords } from './oauth-store';
20
22
  export type { ToolFactoryOutput } from './registry';
21
23
  export type { ToolRouting, ResourceKind } from './scope/policy';
22
24
  export type { McpTextResponse } from './tools/_helpers';
package/dist/index.js CHANGED
@@ -5,6 +5,8 @@ import { computeDraftCollections, computeDraftGlobals } from './draft-workflow';
5
5
  import { createApiKeysCollection, API_KEYS_DEFAULT_SLUG } from './api-keys';
6
6
  import { createBearerStrategy } from './auth-strategy';
7
7
  import { createMcpEndpoints } from './endpoint';
8
+ import { createOAuth } from './oauth';
9
+ import { createOAuthCollection, OAUTH_COLLECTION } from './oauth-store';
8
10
  import { createInitializeServer } from './registry';
9
11
  import { assertNoSlugConflict, assertNoToolNameConflict, assertNoUpstreamPlugin } from './conflict-detection';
10
12
  import { createCreateDocumentTool } from './tools/create-document';
@@ -50,6 +52,7 @@ import { createListVersionsTool, createRestoreVersionTool } from './tools/versio
50
52
  */ export function mcpToolkitPlugin(options = {}) {
51
53
  return (incomingConfig)=>{
52
54
  const apiKeysSlug = options.apiKeyCollection?.slug ?? API_KEYS_DEFAULT_SLUG;
55
+ if (options.oauth) assertNoSlugConflict(incomingConfig.collections, OAUTH_COLLECTION);
53
56
  // Conflict detection — fail fast with actionable messages.
54
57
  assertNoUpstreamPlugin(incomingConfig.plugins);
55
58
  assertNoSlugConflict(incomingConfig.collections, apiKeysSlug);
@@ -156,6 +159,19 @@ import { createListVersionsTool, createRestoreVersionTool } from './tools/versio
156
159
  // config at boot time. Adding a collection requires a dev restart for
157
160
  // it to surface as a scope option.
158
161
  const userCollection = resolveUserCollection(options, incomingConfig);
162
+ const oauth = options.oauth ? createOAuth(options.oauth, incomingConfig, userCollection, {
163
+ collections: [
164
+ ...collectionsBySlug.keys()
165
+ ],
166
+ globals: [
167
+ ...exposedGlobalSchemas.keys()
168
+ ],
169
+ tools: tools.map((t)=>({
170
+ name: t.name,
171
+ kind: t.routing.kind,
172
+ action: t.routing.action
173
+ }))
174
+ }) : undefined;
159
175
  const availableCollections = collections.map((c)=>c.slug).filter((s)=>s !== apiKeysSlug);
160
176
  const availableGlobals = [
161
177
  ...exposedGlobalSchemas.keys()
@@ -170,7 +186,10 @@ import { createListVersionsTool, createRestoreVersionTool } from './tools/versio
170
186
  });
171
187
  const updatedCollections = [
172
188
  ...collections,
173
- apiKeysCollection
189
+ apiKeysCollection,
190
+ ...oauth ? [
191
+ createOAuthCollection()
192
+ ] : []
174
193
  ];
175
194
  // Attach the bearer strategy to the user collection's auth config.
176
195
  const bearerStrategy = createBearerStrategy({
@@ -200,14 +219,58 @@ import { createListVersionsTool, createRestoreVersionTool } from './tools/versio
200
219
  const mcpEndpoints = createMcpEndpoints({
201
220
  buildInitializeServer,
202
221
  allowedOrigins: options.auth?.allowedOrigins,
203
- serverURL: incomingConfig.serverURL
222
+ serverURL: incomingConfig.serverURL,
223
+ oauth
204
224
  });
205
225
  return {
206
226
  ...incomingConfig,
227
+ ...oauth ? {
228
+ admin: {
229
+ ...incomingConfig.admin,
230
+ components: {
231
+ ...incomingConfig.admin?.components,
232
+ views: {
233
+ ...incomingConfig.admin?.components?.views,
234
+ mcpAuthorize: {
235
+ path: '/mcp-authorize',
236
+ exact: true,
237
+ meta: {
238
+ title: 'Connect your account'
239
+ },
240
+ Component: {
241
+ path: 'payload-mcp-toolkit/client#OAuthView',
242
+ clientProps: {
243
+ mode: 'authorize'
244
+ }
245
+ }
246
+ },
247
+ mcpConnections: {
248
+ path: '/mcp-connections',
249
+ exact: true,
250
+ meta: {
251
+ title: 'AI connections'
252
+ },
253
+ Component: {
254
+ path: 'payload-mcp-toolkit/client#OAuthView',
255
+ clientProps: {
256
+ mode: 'connections'
257
+ }
258
+ }
259
+ }
260
+ },
261
+ // Hosts with a custom Nav render <AgentConnectPill /> themselves; this slot is Payload's default nav.
262
+ afterNavLinks: [
263
+ ...incomingConfig.admin?.components?.afterNavLinks ?? [],
264
+ 'payload-mcp-toolkit/client#AgentConnectPill'
265
+ ]
266
+ }
267
+ }
268
+ } : {},
207
269
  collections: collectionsWithStrategy,
208
270
  endpoints: [
209
271
  ...incomingConfig.endpoints ?? [],
210
- ...mcpEndpoints
272
+ ...mcpEndpoints,
273
+ ...oauth?.endpoints ?? []
211
274
  ]
212
275
  };
213
276
  };
@@ -215,5 +278,6 @@ import { createListVersionsTool, createRestoreVersionTool } from './tools/versio
215
278
  // Runtime helpers for building custom tools — the same envelope builders the
216
279
  // built-in tools use, so a host tool returns the identical result shape.
217
280
  export { jsonResponse, textResponse } from './tools/_helpers';
281
+ export { pruneOAuthRecords } from './oauth-store';
218
282
 
219
283
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type { Block, CollectionConfig, Config, GlobalConfig, Plugin } from 'payload'\nimport type { ContentToolkitOptions, GlobalSchema } from './types'\nimport {\n introspectCollections,\n introspectGlobals,\n introspectBlocks,\n buildBlockNestingMap,\n buildRelationshipGraph,\n} from './introspection'\nimport { generatePrompts } from './prompts'\nimport { generateResources } from './resources'\nimport { computeDraftCollections, computeDraftGlobals } from './draft-workflow'\nimport { createApiKeysCollection, API_KEYS_DEFAULT_SLUG } from './api-keys'\nimport { createBearerStrategy } from './auth-strategy'\nimport { createMcpEndpoints } from './endpoint'\nimport {\n createInitializeServer,\n type ToolFactoryOutput,\n} from './registry'\nimport {\n assertNoSlugConflict,\n assertNoToolNameConflict,\n assertNoUpstreamPlugin,\n} from './conflict-detection'\nimport { createCreateDocumentTool } from './tools/create-document'\nimport { createDeleteDocumentTool } from './tools/delete-document'\nimport { createFindDocumentTool } from './tools/find-document'\nimport { createFindGlobalTool } from './tools/find-global'\nimport { createUpdateGlobalTool } from './tools/update-global'\nimport { createPatchGlobalLayoutTool } from './tools/patch-global-layout'\nimport { createPublishGlobalDraftTool } from './tools/publish-global-draft'\nimport {\n createListGlobalVersionsTool,\n createRestoreGlobalVersionTool,\n} from './tools/global-versions'\nimport { createPatchLayoutTool } from './tools/patch-layout'\nimport { createPublishDraftTool } from './tools/publish-draft'\nimport { createResolveReferenceTool } from './tools/resolve-reference'\nimport { createSafeDeleteTool } from './tools/safe-delete'\nimport { createSchedulePublishTool } from './tools/schedule-publish'\nimport { createSearchContentTool } from './tools/search-content'\nimport { createUpdateDocumentTool } from './tools/update-document'\nimport { createUploadMediaTool } from './tools/upload-media'\nimport { createListVersionsTool, createRestoreVersionTool } from './tools/versions'\n\n/**\n * Resolves the user collection slug for API-key linkage.\n *\n * Resolution order: explicit `options.apiKeyCollection.userCollection` →\n * explicit `options.userCollection` → `incomingConfig.admin.user` →\n * 'users' as a last resort.\n */\nfunction resolveUserCollection(\n options: ContentToolkitOptions,\n incomingConfig: Config,\n): string {\n return (\n options.apiKeyCollection?.userCollection ??\n options.userCollection ??\n (incomingConfig.admin?.user as string | undefined) ??\n 'users'\n )\n}\n\n/**\n * payload-mcp-toolkit — standalone Payload v3 MCP plugin.\n *\n * Owns the `/api/mcp` endpoint, the `payload-mcp-api-keys` collection,\n * bearer authentication via Payload's `auth.strategies` extension point,\n * and the per-tool scope check. Upstream `@payloadcms/plugin-mcp` is no\n * longer required (and is incompatible — see `assertNoUpstreamPlugin`).\n *\n * Zero-config usage:\n * ```ts\n * plugins: [mcpToolkitPlugin()]\n * ```\n *\n * See `ContentToolkitOptions` for the (entirely optional) escape hatches.\n */\nexport function mcpToolkitPlugin(options: ContentToolkitOptions = {}): Plugin {\n return (incomingConfig: Config): Config => {\n const apiKeysSlug = options.apiKeyCollection?.slug ?? API_KEYS_DEFAULT_SLUG\n\n // Conflict detection — fail fast with actionable messages.\n assertNoUpstreamPlugin(incomingConfig.plugins)\n assertNoSlugConflict(incomingConfig.collections as CollectionConfig[] | undefined, apiKeysSlug)\n\n const collections = (incomingConfig.collections ?? []) as CollectionConfig[]\n const globals = (incomingConfig.globals ?? []) as GlobalConfig[]\n const allBlocks = (incomingConfig.blocks ?? []) as Block[]\n\n const collectionSchemas = introspectCollections(collections)\n const globalSchemas = introspectGlobals(globals)\n const blockCatalog = introspectBlocks(allBlocks)\n const relationships = buildRelationshipGraph(collectionSchemas)\n\n const previewSiteUrl = options.preview?.disabled\n ? undefined\n : options.preview?.siteUrl ??\n incomingConfig.serverURL ??\n process.env.NEXT_PUBLIC_SERVER_URL ??\n process.env.SITE_URL\n const previewDisabled = options.preview?.disabled === true\n\n const { draftCollections, excluded } = computeDraftCollections(collections, {\n draftBehavior: options.draftBehavior,\n excludeCollections: options.exclude?.collections,\n apiKeysSlug,\n })\n\n const { draftGlobals, excluded: excludedGlobals } = computeDraftGlobals(globals, {\n draftBehavior: options.draftBehavior,\n excludeGlobals: options.exclude?.globals,\n })\n\n // Build blockNesting from exclusion-filtered inputs so excluded\n // collections/globals never appear in patchLayout/patchGlobalLayout slug\n // enums or in the `blocks://nesting` resource body.\n const exposedCollectionsForNesting = collections.filter((c) => !excluded.has(c.slug))\n const exposedGlobalsForNesting = globals.filter((g) => !excludedGlobals.has(g.slug))\n const blockNesting = buildBlockNestingMap(\n exposedCollectionsForNesting,\n exposedGlobalsForNesting,\n allBlocks,\n )\n\n // Build a slug → CollectionConfig map for tools that need access to\n // collection-level admin config (preview functions, etc).\n const collectionsBySlug = new Map<string, CollectionConfig>()\n for (const c of collections) {\n if (!excluded.has(c.slug)) collectionsBySlug.set(c.slug, c)\n }\n\n // Schemas-without-excluded view, used by the polymorphic tool factories\n // so excluded collections don't appear in tool descriptions.\n const exposedSchemas = new Map<string, ReturnType<typeof introspectCollections> extends Map<string, infer V> ? V : never>()\n for (const [slug, schema] of collectionSchemas) {\n if (!excluded.has(slug)) exposedSchemas.set(slug, schema)\n }\n\n // Same shape for globals — excluded slugs are stripped at registration\n // time so they never reach Zod input enums, the globals://schema\n // resource, or availableGlobals on the admin matrix. composeScopes\n // stays exclusion-unaware (mirrors the collection mechanism).\n const exposedGlobalSchemas = new Map<string, GlobalSchema>()\n const globalsBySlug = new Map<string, GlobalConfig>()\n for (const [slug, schema] of globalSchemas) {\n if (excludedGlobals.has(slug)) continue\n exposedGlobalSchemas.set(slug, schema)\n }\n for (const g of globals) {\n if (!excludedGlobals.has(g.slug)) globalsBySlug.set(g.slug, g)\n }\n\n const prompts = generatePrompts(\n exposedSchemas,\n blockCatalog,\n blockNesting,\n relationships,\n options.domainPrompts,\n )\n const resources = generateResources(\n exposedSchemas,\n blockCatalog,\n blockNesting,\n relationships,\n exposedGlobalSchemas,\n )\n\n const searchableCollections = new Map<string, string[]>()\n for (const [slug, schema] of exposedSchemas) {\n if (schema.searchableFields.length > 0) {\n searchableCollections.set(slug, schema.searchableFields)\n }\n }\n\n const tools: ToolFactoryOutput[] = [\n createCreateDocumentTool(exposedSchemas, draftCollections),\n createDeleteDocumentTool(exposedSchemas),\n createFindDocumentTool(\n exposedSchemas,\n draftCollections,\n collectionsBySlug,\n previewSiteUrl,\n previewDisabled,\n ),\n createPatchLayoutTool(blockCatalog, blockNesting, draftCollections),\n createPublishDraftTool(draftCollections),\n createResolveReferenceTool(searchableCollections),\n createSafeDeleteTool(relationships),\n createSearchContentTool(exposedSchemas),\n createUpdateDocumentTool(exposedSchemas, draftCollections),\n createUploadMediaTool({\n maxFileSize: options.mediaUpload?.maxFileSize,\n collectionSlug: options.mediaUpload?.collectionSlug,\n }),\n createListVersionsTool(draftCollections),\n createRestoreVersionTool(draftCollections),\n ]\n\n const schedulePublish = createSchedulePublishTool(exposedSchemas, draftCollections)\n if (schedulePublish) tools.push(schedulePublish)\n\n // Global tools — registered only when at least one global is exposed.\n if (exposedGlobalSchemas.size > 0) {\n tools.push(\n createFindGlobalTool(\n exposedGlobalSchemas,\n draftGlobals,\n globalsBySlug,\n previewSiteUrl,\n previewDisabled,\n ),\n createUpdateGlobalTool(exposedGlobalSchemas, draftGlobals),\n )\n\n const patchGlobalLayout = createPatchGlobalLayoutTool(blockCatalog, blockNesting, draftGlobals)\n if (patchGlobalLayout) tools.push(patchGlobalLayout)\n\n const publishGlobalDraft = createPublishGlobalDraftTool(draftGlobals)\n if (publishGlobalDraft) tools.push(publishGlobalDraft)\n\n const listGlobalVersions = createListGlobalVersionsTool(draftGlobals)\n if (listGlobalVersions) tools.push(listGlobalVersions)\n\n const restoreGlobalVersion = createRestoreGlobalVersionTool(draftGlobals)\n if (restoreGlobalVersion) tools.push(restoreGlobalVersion)\n }\n\n // Host-supplied tools go on the end, so a built-in never loses its slot in\n // tools/list. They share the wrapper: scope check, mcp stamp, audit log.\n assertNoToolNameConflict(tools, options.customTools)\n if (options.customTools?.length) tools.push(...options.customTools)\n\n // Build the per-request initializer that mcp-handler invokes.\n const buildInitializeServer = createInitializeServer({\n tools,\n prompts: prompts as never,\n resources: resources as never,\n })\n\n // Attach API-keys collection. Available collections / tools are\n // snapshotted now so the admin UI's scope dropdowns reflect the host\n // config at boot time. Adding a collection requires a dev restart for\n // it to surface as a scope option.\n const userCollection = resolveUserCollection(options, incomingConfig)\n const availableCollections = collections\n .map((c) => c.slug)\n .filter((s) => s !== apiKeysSlug)\n const availableGlobals = [...exposedGlobalSchemas.keys()]\n const availableTools = tools.map((t) => t.name)\n const apiKeysCollection = createApiKeysCollection({\n slug: apiKeysSlug,\n userCollection,\n availableCollections,\n availableGlobals,\n availableTools,\n })\n const updatedCollections: CollectionConfig[] = [...collections, apiKeysCollection]\n\n // Attach the bearer strategy to the user collection's auth config.\n const bearerStrategy = createBearerStrategy({\n collectionSlug: apiKeysSlug,\n userCollection,\n })\n const collectionsWithStrategy = updatedCollections.map((c) => {\n if (c.slug !== userCollection) return c\n const existingAuth = c.auth\n if (!existingAuth) return c\n const authConfig =\n typeof existingAuth === 'object' && existingAuth !== null\n ? { ...existingAuth }\n : { useAPIKey: existingAuth === true ? false : false }\n const existingStrategies = Array.isArray((authConfig as { strategies?: unknown[] }).strategies)\n ? ((authConfig as { strategies: unknown[] }).strategies as unknown[])\n : []\n ;(authConfig as { strategies: unknown[] }).strategies = [\n ...existingStrategies,\n bearerStrategy,\n ]\n return { ...c, auth: authConfig } as CollectionConfig\n })\n\n // Attach the MCP endpoints additively to the host config.\n const mcpEndpoints = createMcpEndpoints({\n buildInitializeServer,\n allowedOrigins: options.auth?.allowedOrigins,\n serverURL: incomingConfig.serverURL,\n })\n\n return {\n ...incomingConfig,\n collections: collectionsWithStrategy,\n endpoints: [...(incomingConfig.endpoints ?? []), ...mcpEndpoints],\n }\n }\n}\n\n// Runtime helpers for building custom tools — the same envelope builders the\n// built-in tools use, so a host tool returns the identical result shape.\nexport { jsonResponse, textResponse } from './tools/_helpers'\n\nexport type { ToolFactoryOutput } from './registry'\nexport type { ToolRouting, ResourceKind } from './scope/policy'\nexport type { McpTextResponse } from './tools/_helpers'\n\nexport type {\n ContentToolkitOptions,\n DomainPrompt,\n CollectionSchema,\n GlobalSchema,\n BlockCatalog,\n BlockSchema,\n BlockNestingMap,\n BlockNestingEdge,\n RelationshipEdge,\n FieldSchema,\n CollectionAction,\n GlobalAction,\n KeyScopes,\n ScopePreset,\n} from './types'\n"],"names":["introspectCollections","introspectGlobals","introspectBlocks","buildBlockNestingMap","buildRelationshipGraph","generatePrompts","generateResources","computeDraftCollections","computeDraftGlobals","createApiKeysCollection","API_KEYS_DEFAULT_SLUG","createBearerStrategy","createMcpEndpoints","createInitializeServer","assertNoSlugConflict","assertNoToolNameConflict","assertNoUpstreamPlugin","createCreateDocumentTool","createDeleteDocumentTool","createFindDocumentTool","createFindGlobalTool","createUpdateGlobalTool","createPatchGlobalLayoutTool","createPublishGlobalDraftTool","createListGlobalVersionsTool","createRestoreGlobalVersionTool","createPatchLayoutTool","createPublishDraftTool","createResolveReferenceTool","createSafeDeleteTool","createSchedulePublishTool","createSearchContentTool","createUpdateDocumentTool","createUploadMediaTool","createListVersionsTool","createRestoreVersionTool","resolveUserCollection","options","incomingConfig","apiKeyCollection","userCollection","admin","user","mcpToolkitPlugin","apiKeysSlug","slug","plugins","collections","globals","allBlocks","blocks","collectionSchemas","globalSchemas","blockCatalog","relationships","previewSiteUrl","preview","disabled","undefined","siteUrl","serverURL","process","env","NEXT_PUBLIC_SERVER_URL","SITE_URL","previewDisabled","draftCollections","excluded","draftBehavior","excludeCollections","exclude","draftGlobals","excludedGlobals","excludeGlobals","exposedCollectionsForNesting","filter","c","has","exposedGlobalsForNesting","g","blockNesting","collectionsBySlug","Map","set","exposedSchemas","schema","exposedGlobalSchemas","globalsBySlug","prompts","domainPrompts","resources","searchableCollections","searchableFields","length","tools","maxFileSize","mediaUpload","collectionSlug","schedulePublish","push","size","patchGlobalLayout","publishGlobalDraft","listGlobalVersions","restoreGlobalVersion","customTools","buildInitializeServer","availableCollections","map","s","availableGlobals","keys","availableTools","t","name","apiKeysCollection","updatedCollections","bearerStrategy","collectionsWithStrategy","existingAuth","auth","authConfig","useAPIKey","existingStrategies","Array","isArray","strategies","mcpEndpoints","allowedOrigins","endpoints","jsonResponse","textResponse"],"mappings":"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"}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type { Block, CollectionConfig, Config, GlobalConfig, Plugin } from 'payload'\nimport type { ContentToolkitOptions, GlobalSchema } from './types'\nimport {\n introspectCollections,\n introspectGlobals,\n introspectBlocks,\n buildBlockNestingMap,\n buildRelationshipGraph,\n} from './introspection'\nimport { generatePrompts } from './prompts'\nimport { generateResources } from './resources'\nimport { computeDraftCollections, computeDraftGlobals } from './draft-workflow'\nimport { createApiKeysCollection, API_KEYS_DEFAULT_SLUG } from './api-keys'\nimport { createBearerStrategy } from './auth-strategy'\nimport { createMcpEndpoints } from './endpoint'\nimport { createOAuth } from './oauth'\nimport { createOAuthCollection, OAUTH_COLLECTION } from './oauth-store'\nimport {\n createInitializeServer,\n type ToolFactoryOutput,\n} from './registry'\nimport {\n assertNoSlugConflict,\n assertNoToolNameConflict,\n assertNoUpstreamPlugin,\n} from './conflict-detection'\nimport { createCreateDocumentTool } from './tools/create-document'\nimport { createDeleteDocumentTool } from './tools/delete-document'\nimport { createFindDocumentTool } from './tools/find-document'\nimport { createFindGlobalTool } from './tools/find-global'\nimport { createUpdateGlobalTool } from './tools/update-global'\nimport { createPatchGlobalLayoutTool } from './tools/patch-global-layout'\nimport { createPublishGlobalDraftTool } from './tools/publish-global-draft'\nimport {\n createListGlobalVersionsTool,\n createRestoreGlobalVersionTool,\n} from './tools/global-versions'\nimport { createPatchLayoutTool } from './tools/patch-layout'\nimport { createPublishDraftTool } from './tools/publish-draft'\nimport { createResolveReferenceTool } from './tools/resolve-reference'\nimport { createSafeDeleteTool } from './tools/safe-delete'\nimport { createSchedulePublishTool } from './tools/schedule-publish'\nimport { createSearchContentTool } from './tools/search-content'\nimport { createUpdateDocumentTool } from './tools/update-document'\nimport { createUploadMediaTool } from './tools/upload-media'\nimport { createListVersionsTool, createRestoreVersionTool } from './tools/versions'\n\n/**\n * Resolves the user collection slug for API-key linkage.\n *\n * Resolution order: explicit `options.apiKeyCollection.userCollection` →\n * explicit `options.userCollection` → `incomingConfig.admin.user` →\n * 'users' as a last resort.\n */\nfunction resolveUserCollection(\n options: ContentToolkitOptions,\n incomingConfig: Config,\n): string {\n return (\n options.apiKeyCollection?.userCollection ??\n options.userCollection ??\n (incomingConfig.admin?.user as string | undefined) ??\n 'users'\n )\n}\n\n/**\n * payload-mcp-toolkit — standalone Payload v3 MCP plugin.\n *\n * Owns the `/api/mcp` endpoint, the `payload-mcp-api-keys` collection,\n * bearer authentication via Payload's `auth.strategies` extension point,\n * and the per-tool scope check. Upstream `@payloadcms/plugin-mcp` is no\n * longer required (and is incompatible — see `assertNoUpstreamPlugin`).\n *\n * Zero-config usage:\n * ```ts\n * plugins: [mcpToolkitPlugin()]\n * ```\n *\n * See `ContentToolkitOptions` for the (entirely optional) escape hatches.\n */\nexport function mcpToolkitPlugin(options: ContentToolkitOptions = {}): Plugin {\n return (incomingConfig: Config): Config => {\n const apiKeysSlug = options.apiKeyCollection?.slug ?? API_KEYS_DEFAULT_SLUG\n if (options.oauth) assertNoSlugConflict(incomingConfig.collections as CollectionConfig[] | undefined, OAUTH_COLLECTION)\n\n // Conflict detection — fail fast with actionable messages.\n assertNoUpstreamPlugin(incomingConfig.plugins)\n assertNoSlugConflict(incomingConfig.collections as CollectionConfig[] | undefined, apiKeysSlug)\n\n const collections = (incomingConfig.collections ?? []) as CollectionConfig[]\n const globals = (incomingConfig.globals ?? []) as GlobalConfig[]\n const allBlocks = (incomingConfig.blocks ?? []) as Block[]\n\n const collectionSchemas = introspectCollections(collections)\n const globalSchemas = introspectGlobals(globals)\n const blockCatalog = introspectBlocks(allBlocks)\n const relationships = buildRelationshipGraph(collectionSchemas)\n\n const previewSiteUrl = options.preview?.disabled\n ? undefined\n : options.preview?.siteUrl ??\n incomingConfig.serverURL ??\n process.env.NEXT_PUBLIC_SERVER_URL ??\n process.env.SITE_URL\n const previewDisabled = options.preview?.disabled === true\n\n const { draftCollections, excluded } = computeDraftCollections(collections, {\n draftBehavior: options.draftBehavior,\n excludeCollections: options.exclude?.collections,\n apiKeysSlug,\n })\n\n const { draftGlobals, excluded: excludedGlobals } = computeDraftGlobals(globals, {\n draftBehavior: options.draftBehavior,\n excludeGlobals: options.exclude?.globals,\n })\n\n // Build blockNesting from exclusion-filtered inputs so excluded\n // collections/globals never appear in patchLayout/patchGlobalLayout slug\n // enums or in the `blocks://nesting` resource body.\n const exposedCollectionsForNesting = collections.filter((c) => !excluded.has(c.slug))\n const exposedGlobalsForNesting = globals.filter((g) => !excludedGlobals.has(g.slug))\n const blockNesting = buildBlockNestingMap(\n exposedCollectionsForNesting,\n exposedGlobalsForNesting,\n allBlocks,\n )\n\n // Build a slug → CollectionConfig map for tools that need access to\n // collection-level admin config (preview functions, etc).\n const collectionsBySlug = new Map<string, CollectionConfig>()\n for (const c of collections) {\n if (!excluded.has(c.slug)) collectionsBySlug.set(c.slug, c)\n }\n\n // Schemas-without-excluded view, used by the polymorphic tool factories\n // so excluded collections don't appear in tool descriptions.\n const exposedSchemas = new Map<string, ReturnType<typeof introspectCollections> extends Map<string, infer V> ? V : never>()\n for (const [slug, schema] of collectionSchemas) {\n if (!excluded.has(slug)) exposedSchemas.set(slug, schema)\n }\n\n // Same shape for globals — excluded slugs are stripped at registration\n // time so they never reach Zod input enums, the globals://schema\n // resource, or availableGlobals on the admin matrix. composeScopes\n // stays exclusion-unaware (mirrors the collection mechanism).\n const exposedGlobalSchemas = new Map<string, GlobalSchema>()\n const globalsBySlug = new Map<string, GlobalConfig>()\n for (const [slug, schema] of globalSchemas) {\n if (excludedGlobals.has(slug)) continue\n exposedGlobalSchemas.set(slug, schema)\n }\n for (const g of globals) {\n if (!excludedGlobals.has(g.slug)) globalsBySlug.set(g.slug, g)\n }\n\n const prompts = generatePrompts(\n exposedSchemas,\n blockCatalog,\n blockNesting,\n relationships,\n options.domainPrompts,\n )\n const resources = generateResources(\n exposedSchemas,\n blockCatalog,\n blockNesting,\n relationships,\n exposedGlobalSchemas,\n )\n\n const searchableCollections = new Map<string, string[]>()\n for (const [slug, schema] of exposedSchemas) {\n if (schema.searchableFields.length > 0) {\n searchableCollections.set(slug, schema.searchableFields)\n }\n }\n\n const tools: ToolFactoryOutput[] = [\n createCreateDocumentTool(exposedSchemas, draftCollections),\n createDeleteDocumentTool(exposedSchemas),\n createFindDocumentTool(\n exposedSchemas,\n draftCollections,\n collectionsBySlug,\n previewSiteUrl,\n previewDisabled,\n ),\n createPatchLayoutTool(blockCatalog, blockNesting, draftCollections),\n createPublishDraftTool(draftCollections),\n createResolveReferenceTool(searchableCollections),\n createSafeDeleteTool(relationships),\n createSearchContentTool(exposedSchemas),\n createUpdateDocumentTool(exposedSchemas, draftCollections),\n createUploadMediaTool({\n maxFileSize: options.mediaUpload?.maxFileSize,\n collectionSlug: options.mediaUpload?.collectionSlug,\n }),\n createListVersionsTool(draftCollections),\n createRestoreVersionTool(draftCollections),\n ]\n\n const schedulePublish = createSchedulePublishTool(exposedSchemas, draftCollections)\n if (schedulePublish) tools.push(schedulePublish)\n\n // Global tools — registered only when at least one global is exposed.\n if (exposedGlobalSchemas.size > 0) {\n tools.push(\n createFindGlobalTool(\n exposedGlobalSchemas,\n draftGlobals,\n globalsBySlug,\n previewSiteUrl,\n previewDisabled,\n ),\n createUpdateGlobalTool(exposedGlobalSchemas, draftGlobals),\n )\n\n const patchGlobalLayout = createPatchGlobalLayoutTool(blockCatalog, blockNesting, draftGlobals)\n if (patchGlobalLayout) tools.push(patchGlobalLayout)\n\n const publishGlobalDraft = createPublishGlobalDraftTool(draftGlobals)\n if (publishGlobalDraft) tools.push(publishGlobalDraft)\n\n const listGlobalVersions = createListGlobalVersionsTool(draftGlobals)\n if (listGlobalVersions) tools.push(listGlobalVersions)\n\n const restoreGlobalVersion = createRestoreGlobalVersionTool(draftGlobals)\n if (restoreGlobalVersion) tools.push(restoreGlobalVersion)\n }\n\n // Host-supplied tools go on the end, so a built-in never loses its slot in\n // tools/list. They share the wrapper: scope check, mcp stamp, audit log.\n assertNoToolNameConflict(tools, options.customTools)\n if (options.customTools?.length) tools.push(...options.customTools)\n\n // Build the per-request initializer that mcp-handler invokes.\n const buildInitializeServer = createInitializeServer({\n tools,\n prompts: prompts as never,\n resources: resources as never,\n })\n\n // Attach API-keys collection. Available collections / tools are\n // snapshotted now so the admin UI's scope dropdowns reflect the host\n // config at boot time. Adding a collection requires a dev restart for\n // it to surface as a scope option.\n const userCollection = resolveUserCollection(options, incomingConfig)\n const oauth = options.oauth ? createOAuth(options.oauth, incomingConfig, userCollection, {\n collections: [...collectionsBySlug.keys()],\n globals: [...exposedGlobalSchemas.keys()],\n tools: tools.map(t => ({ name: t.name, kind: t.routing.kind, action: t.routing.action })),\n }) : undefined\n const availableCollections = collections\n .map((c) => c.slug)\n .filter((s) => s !== apiKeysSlug)\n const availableGlobals = [...exposedGlobalSchemas.keys()]\n const availableTools = tools.map((t) => t.name)\n const apiKeysCollection = createApiKeysCollection({\n slug: apiKeysSlug,\n userCollection,\n availableCollections,\n availableGlobals,\n availableTools,\n })\n const updatedCollections: CollectionConfig[] = [...collections, apiKeysCollection, ...(oauth ? [createOAuthCollection()] : [])]\n\n // Attach the bearer strategy to the user collection's auth config.\n const bearerStrategy = createBearerStrategy({\n collectionSlug: apiKeysSlug,\n userCollection,\n })\n const collectionsWithStrategy = updatedCollections.map((c) => {\n if (c.slug !== userCollection) return c\n const existingAuth = c.auth\n if (!existingAuth) return c\n const authConfig =\n typeof existingAuth === 'object' && existingAuth !== null\n ? { ...existingAuth }\n : { useAPIKey: existingAuth === true ? false : false }\n const existingStrategies = Array.isArray((authConfig as { strategies?: unknown[] }).strategies)\n ? ((authConfig as { strategies: unknown[] }).strategies as unknown[])\n : []\n ;(authConfig as { strategies: unknown[] }).strategies = [\n ...existingStrategies,\n bearerStrategy,\n ]\n return { ...c, auth: authConfig } as CollectionConfig\n })\n\n // Attach the MCP endpoints additively to the host config.\n const mcpEndpoints = createMcpEndpoints({\n buildInitializeServer,\n allowedOrigins: options.auth?.allowedOrigins,\n serverURL: incomingConfig.serverURL,\n oauth,\n })\n\n return {\n ...incomingConfig,\n ...(oauth ? { admin: {\n ...incomingConfig.admin,\n components: {\n ...incomingConfig.admin?.components,\n views: {\n ...incomingConfig.admin?.components?.views,\n mcpAuthorize: { path: '/mcp-authorize', exact: true, meta: { title: 'Connect your account' }, Component: {\n path: 'payload-mcp-toolkit/client#OAuthView', clientProps: { mode: 'authorize' },\n } },\n mcpConnections: { path: '/mcp-connections', exact: true, meta: { title: 'AI connections' }, Component: {\n path: 'payload-mcp-toolkit/client#OAuthView', clientProps: { mode: 'connections' },\n } },\n },\n // Hosts with a custom Nav render <AgentConnectPill /> themselves; this slot is Payload's default nav.\n afterNavLinks: [\n ...(incomingConfig.admin?.components?.afterNavLinks ?? []),\n 'payload-mcp-toolkit/client#AgentConnectPill',\n ],\n },\n } } : {}),\n collections: collectionsWithStrategy,\n endpoints: [...(incomingConfig.endpoints ?? []), ...mcpEndpoints, ...(oauth?.endpoints ?? [])],\n }\n }\n}\n\n// Runtime helpers for building custom tools — the same envelope builders the\n// built-in tools use, so a host tool returns the identical result shape.\nexport { jsonResponse, textResponse } from './tools/_helpers'\nexport type { OAuthOptions } from './oauth'\nexport { pruneOAuthRecords } from './oauth-store'\n\nexport type { ToolFactoryOutput } from './registry'\nexport type { ToolRouting, ResourceKind } from './scope/policy'\nexport type { McpTextResponse } from './tools/_helpers'\n\nexport type {\n ContentToolkitOptions,\n DomainPrompt,\n CollectionSchema,\n GlobalSchema,\n BlockCatalog,\n BlockSchema,\n BlockNestingMap,\n BlockNestingEdge,\n RelationshipEdge,\n FieldSchema,\n CollectionAction,\n GlobalAction,\n KeyScopes,\n ScopePreset,\n} from './types'\n"],"names":["introspectCollections","introspectGlobals","introspectBlocks","buildBlockNestingMap","buildRelationshipGraph","generatePrompts","generateResources","computeDraftCollections","computeDraftGlobals","createApiKeysCollection","API_KEYS_DEFAULT_SLUG","createBearerStrategy","createMcpEndpoints","createOAuth","createOAuthCollection","OAUTH_COLLECTION","createInitializeServer","assertNoSlugConflict","assertNoToolNameConflict","assertNoUpstreamPlugin","createCreateDocumentTool","createDeleteDocumentTool","createFindDocumentTool","createFindGlobalTool","createUpdateGlobalTool","createPatchGlobalLayoutTool","createPublishGlobalDraftTool","createListGlobalVersionsTool","createRestoreGlobalVersionTool","createPatchLayoutTool","createPublishDraftTool","createResolveReferenceTool","createSafeDeleteTool","createSchedulePublishTool","createSearchContentTool","createUpdateDocumentTool","createUploadMediaTool","createListVersionsTool","createRestoreVersionTool","resolveUserCollection","options","incomingConfig","apiKeyCollection","userCollection","admin","user","mcpToolkitPlugin","apiKeysSlug","slug","oauth","collections","plugins","globals","allBlocks","blocks","collectionSchemas","globalSchemas","blockCatalog","relationships","previewSiteUrl","preview","disabled","undefined","siteUrl","serverURL","process","env","NEXT_PUBLIC_SERVER_URL","SITE_URL","previewDisabled","draftCollections","excluded","draftBehavior","excludeCollections","exclude","draftGlobals","excludedGlobals","excludeGlobals","exposedCollectionsForNesting","filter","c","has","exposedGlobalsForNesting","g","blockNesting","collectionsBySlug","Map","set","exposedSchemas","schema","exposedGlobalSchemas","globalsBySlug","prompts","domainPrompts","resources","searchableCollections","searchableFields","length","tools","maxFileSize","mediaUpload","collectionSlug","schedulePublish","push","size","patchGlobalLayout","publishGlobalDraft","listGlobalVersions","restoreGlobalVersion","customTools","buildInitializeServer","keys","map","t","name","kind","routing","action","availableCollections","s","availableGlobals","availableTools","apiKeysCollection","updatedCollections","bearerStrategy","collectionsWithStrategy","existingAuth","auth","authConfig","useAPIKey","existingStrategies","Array","isArray","strategies","mcpEndpoints","allowedOrigins","components","views","mcpAuthorize","path","exact","meta","title","Component","clientProps","mode","mcpConnections","afterNavLinks","endpoints","jsonResponse","textResponse","pruneOAuthRecords"],"mappings":"AAEA,SACEA,qBAAqB,EACrBC,iBAAiB,EACjBC,gBAAgB,EAChBC,oBAAoB,EACpBC,sBAAsB,QACjB,kBAAiB;AACxB,SAASC,eAAe,QAAQ,YAAW;AAC3C,SAASC,iBAAiB,QAAQ,cAAa;AAC/C,SAASC,uBAAuB,EAAEC,mBAAmB,QAAQ,mBAAkB;AAC/E,SAASC,uBAAuB,EAAEC,qBAAqB,QAAQ,aAAY;AAC3E,SAASC,oBAAoB,QAAQ,kBAAiB;AACtD,SAASC,kBAAkB,QAAQ,aAAY;AAC/C,SAASC,WAAW,QAAQ,UAAS;AACrC,SAASC,qBAAqB,EAAEC,gBAAgB,QAAQ,gBAAe;AACvE,SACEC,sBAAsB,QAEjB,aAAY;AACnB,SACEC,oBAAoB,EACpBC,wBAAwB,EACxBC,sBAAsB,QACjB,uBAAsB;AAC7B,SAASC,wBAAwB,QAAQ,0BAAyB;AAClE,SAASC,wBAAwB,QAAQ,0BAAyB;AAClE,SAASC,sBAAsB,QAAQ,wBAAuB;AAC9D,SAASC,oBAAoB,QAAQ,sBAAqB;AAC1D,SAASC,sBAAsB,QAAQ,wBAAuB;AAC9D,SAASC,2BAA2B,QAAQ,8BAA6B;AACzE,SAASC,4BAA4B,QAAQ,+BAA8B;AAC3E,SACEC,4BAA4B,EAC5BC,8BAA8B,QACzB,0BAAyB;AAChC,SAASC,qBAAqB,QAAQ,uBAAsB;AAC5D,SAASC,sBAAsB,QAAQ,wBAAuB;AAC9D,SAASC,0BAA0B,QAAQ,4BAA2B;AACtE,SAASC,oBAAoB,QAAQ,sBAAqB;AAC1D,SAASC,yBAAyB,QAAQ,2BAA0B;AACpE,SAASC,uBAAuB,QAAQ,yBAAwB;AAChE,SAASC,wBAAwB,QAAQ,0BAAyB;AAClE,SAASC,qBAAqB,QAAQ,uBAAsB;AAC5D,SAASC,sBAAsB,EAAEC,wBAAwB,QAAQ,mBAAkB;AAEnF;;;;;;CAMC,GACD,SAASC,sBACPC,OAA8B,EAC9BC,cAAsB;IAEtB,OACED,QAAQE,gBAAgB,EAAEC,kBAC1BH,QAAQG,cAAc,IACrBF,eAAeG,KAAK,EAAEC,QACvB;AAEJ;AAEA;;;;;;;;;;;;;;CAcC,GACD,OAAO,SAASC,iBAAiBN,UAAiC,CAAC,CAAC;IAClE,OAAO,CAACC;QACN,MAAMM,cAAcP,QAAQE,gBAAgB,EAAEM,QAAQtC;QACtD,IAAI8B,QAAQS,KAAK,EAAEhC,qBAAqBwB,eAAeS,WAAW,EAAoCnC;QAEtG,2DAA2D;QAC3DI,uBAAuBsB,eAAeU,OAAO;QAC7ClC,qBAAqBwB,eAAeS,WAAW,EAAoCH;QAEnF,MAAMG,cAAeT,eAAeS,WAAW,IAAI,EAAE;QACrD,MAAME,UAAWX,eAAeW,OAAO,IAAI,EAAE;QAC7C,MAAMC,YAAaZ,eAAea,MAAM,IAAI,EAAE;QAE9C,MAAMC,oBAAoBvD,sBAAsBkD;QAChD,MAAMM,gBAAgBvD,kBAAkBmD;QACxC,MAAMK,eAAevD,iBAAiBmD;QACtC,MAAMK,gBAAgBtD,uBAAuBmD;QAE7C,MAAMI,iBAAiBnB,QAAQoB,OAAO,EAAEC,WACpCC,YACAtB,QAAQoB,OAAO,EAAEG,WACjBtB,eAAeuB,SAAS,IACxBC,QAAQC,GAAG,CAACC,sBAAsB,IAClCF,QAAQC,GAAG,CAACE,QAAQ;QACxB,MAAMC,kBAAkB7B,QAAQoB,OAAO,EAAEC,aAAa;QAEtD,MAAM,EAAES,gBAAgB,EAAEC,QAAQ,EAAE,GAAGhE,wBAAwB2C,aAAa;YAC1EsB,eAAehC,QAAQgC,aAAa;YACpCC,oBAAoBjC,QAAQkC,OAAO,EAAExB;YACrCH;QACF;QAEA,MAAM,EAAE4B,YAAY,EAAEJ,UAAUK,eAAe,EAAE,GAAGpE,oBAAoB4C,SAAS;YAC/EoB,eAAehC,QAAQgC,aAAa;YACpCK,gBAAgBrC,QAAQkC,OAAO,EAAEtB;QACnC;QAEA,gEAAgE;QAChE,yEAAyE;QACzE,oDAAoD;QACpD,MAAM0B,+BAA+B5B,YAAY6B,MAAM,CAAC,CAACC,IAAM,CAACT,SAASU,GAAG,CAACD,EAAEhC,IAAI;QACnF,MAAMkC,2BAA2B9B,QAAQ2B,MAAM,CAAC,CAACI,IAAM,CAACP,gBAAgBK,GAAG,CAACE,EAAEnC,IAAI;QAClF,MAAMoC,eAAejF,qBACnB2E,8BACAI,0BACA7B;QAGF,oEAAoE;QACpE,0DAA0D;QAC1D,MAAMgC,oBAAoB,IAAIC;QAC9B,KAAK,MAAMN,KAAK9B,YAAa;YAC3B,IAAI,CAACqB,SAASU,GAAG,CAACD,EAAEhC,IAAI,GAAGqC,kBAAkBE,GAAG,CAACP,EAAEhC,IAAI,EAAEgC;QAC3D;QAEA,wEAAwE;QACxE,6DAA6D;QAC7D,MAAMQ,iBAAiB,IAAIF;QAC3B,KAAK,MAAM,CAACtC,MAAMyC,OAAO,IAAIlC,kBAAmB;YAC9C,IAAI,CAACgB,SAASU,GAAG,CAACjC,OAAOwC,eAAeD,GAAG,CAACvC,MAAMyC;QACpD;QAEA,uEAAuE;QACvE,iEAAiE;QACjE,mEAAmE;QACnE,8DAA8D;QAC9D,MAAMC,uBAAuB,IAAIJ;QACjC,MAAMK,gBAAgB,IAAIL;QAC1B,KAAK,MAAM,CAACtC,MAAMyC,OAAO,IAAIjC,cAAe;YAC1C,IAAIoB,gBAAgBK,GAAG,CAACjC,OAAO;YAC/B0C,qBAAqBH,GAAG,CAACvC,MAAMyC;QACjC;QACA,KAAK,MAAMN,KAAK/B,QAAS;YACvB,IAAI,CAACwB,gBAAgBK,GAAG,CAACE,EAAEnC,IAAI,GAAG2C,cAAcJ,GAAG,CAACJ,EAAEnC,IAAI,EAAEmC;QAC9D;QAEA,MAAMS,UAAUvF,gBACdmF,gBACA/B,cACA2B,cACA1B,eACAlB,QAAQqD,aAAa;QAEvB,MAAMC,YAAYxF,kBAChBkF,gBACA/B,cACA2B,cACA1B,eACAgC;QAGF,MAAMK,wBAAwB,IAAIT;QAClC,KAAK,MAAM,CAACtC,MAAMyC,OAAO,IAAID,eAAgB;YAC3C,IAAIC,OAAOO,gBAAgB,CAACC,MAAM,GAAG,GAAG;gBACtCF,sBAAsBR,GAAG,CAACvC,MAAMyC,OAAOO,gBAAgB;YACzD;QACF;QAEA,MAAME,QAA6B;YACjC9E,yBAAyBoE,gBAAgBlB;YACzCjD,yBAAyBmE;YACzBlE,uBACEkE,gBACAlB,kBACAe,mBACA1B,gBACAU;YAEFxC,sBAAsB4B,cAAc2B,cAAcd;YAClDxC,uBAAuBwC;YACvBvC,2BAA2BgE;YAC3B/D,qBAAqB0B;YACrBxB,wBAAwBsD;YACxBrD,yBAAyBqD,gBAAgBlB;YACzClC,sBAAsB;gBACpB+D,aAAa3D,QAAQ4D,WAAW,EAAED;gBAClCE,gBAAgB7D,QAAQ4D,WAAW,EAAEC;YACvC;YACAhE,uBAAuBiC;YACvBhC,yBAAyBgC;SAC1B;QAED,MAAMgC,kBAAkBrE,0BAA0BuD,gBAAgBlB;QAClE,IAAIgC,iBAAiBJ,MAAMK,IAAI,CAACD;QAEhC,sEAAsE;QACtE,IAAIZ,qBAAqBc,IAAI,GAAG,GAAG;YACjCN,MAAMK,IAAI,CACRhF,qBACEmE,sBACAf,cACAgB,eACAhC,gBACAU,kBAEF7C,uBAAuBkE,sBAAsBf;YAG/C,MAAM8B,oBAAoBhF,4BAA4BgC,cAAc2B,cAAcT;YAClF,IAAI8B,mBAAmBP,MAAMK,IAAI,CAACE;YAElC,MAAMC,qBAAqBhF,6BAA6BiD;YACxD,IAAI+B,oBAAoBR,MAAMK,IAAI,CAACG;YAEnC,MAAMC,qBAAqBhF,6BAA6BgD;YACxD,IAAIgC,oBAAoBT,MAAMK,IAAI,CAACI;YAEnC,MAAMC,uBAAuBhF,+BAA+B+C;YAC5D,IAAIiC,sBAAsBV,MAAMK,IAAI,CAACK;QACvC;QAEA,2EAA2E;QAC3E,yEAAyE;QACzE1F,yBAAyBgF,OAAO1D,QAAQqE,WAAW;QACnD,IAAIrE,QAAQqE,WAAW,EAAEZ,QAAQC,MAAMK,IAAI,IAAI/D,QAAQqE,WAAW;QAElE,8DAA8D;QAC9D,MAAMC,wBAAwB9F,uBAAuB;YACnDkF;YACAN,SAASA;YACTE,WAAWA;QACb;QAEA,gEAAgE;QAChE,qEAAqE;QACrE,sEAAsE;QACtE,mCAAmC;QACnC,MAAMnD,iBAAiBJ,sBAAsBC,SAASC;QACtD,MAAMQ,QAAQT,QAAQS,KAAK,GAAGpC,YAAY2B,QAAQS,KAAK,EAAER,gBAAgBE,gBAAgB;YACvFO,aAAa;mBAAImC,kBAAkB0B,IAAI;aAAG;YAC1C3D,SAAS;mBAAIsC,qBAAqBqB,IAAI;aAAG;YACzCb,OAAOA,MAAMc,GAAG,CAACC,CAAAA,IAAM,CAAA;oBAAEC,MAAMD,EAAEC,IAAI;oBAAEC,MAAMF,EAAEG,OAAO,CAACD,IAAI;oBAAEE,QAAQJ,EAAEG,OAAO,CAACC,MAAM;gBAAC,CAAA;QACxF,KAAKvD;QACL,MAAMwD,uBAAuBpE,YAC1B8D,GAAG,CAAC,CAAChC,IAAMA,EAAEhC,IAAI,EACjB+B,MAAM,CAAC,CAACwC,IAAMA,MAAMxE;QACvB,MAAMyE,mBAAmB;eAAI9B,qBAAqBqB,IAAI;SAAG;QACzD,MAAMU,iBAAiBvB,MAAMc,GAAG,CAAC,CAACC,IAAMA,EAAEC,IAAI;QAC9C,MAAMQ,oBAAoBjH,wBAAwB;YAChDuC,MAAMD;YACNJ;YACA2E;YACAE;YACAC;QACF;QACA,MAAME,qBAAyC;eAAIzE;YAAawE;eAAuBzE,QAAQ;gBAACnC;aAAwB,GAAG,EAAE;SAAE;QAE/H,mEAAmE;QACnE,MAAM8G,iBAAiBjH,qBAAqB;YAC1C0F,gBAAgBtD;YAChBJ;QACF;QACA,MAAMkF,0BAA0BF,mBAAmBX,GAAG,CAAC,CAAChC;YACtD,IAAIA,EAAEhC,IAAI,KAAKL,gBAAgB,OAAOqC;YACtC,MAAM8C,eAAe9C,EAAE+C,IAAI;YAC3B,IAAI,CAACD,cAAc,OAAO9C;YAC1B,MAAMgD,aACJ,OAAOF,iBAAiB,YAAYA,iBAAiB,OACjD;gBAAE,GAAGA,YAAY;YAAC,IAClB;gBAAEG,WAAWH,iBAAiB,OAAO,QAAQ;YAAM;YACzD,MAAMI,qBAAqBC,MAAMC,OAAO,CAAC,AAACJ,WAA0CK,UAAU,IACzF,AAACL,WAAyCK,UAAU,GACrD,EAAE;YACJL,WAAyCK,UAAU,GAAG;mBACnDH;gBACHN;aACD;YACD,OAAO;gBAAE,GAAG5C,CAAC;gBAAE+C,MAAMC;YAAW;QAClC;QAEA,0DAA0D;QAC1D,MAAMM,eAAe1H,mBAAmB;YACtCkG;YACAyB,gBAAgB/F,QAAQuF,IAAI,EAAEQ;YAC9BvE,WAAWvB,eAAeuB,SAAS;YACnCf;QACF;QAEA,OAAO;YACL,GAAGR,cAAc;YACjB,GAAIQ,QAAQ;gBAAEL,OAAO;oBACnB,GAAGH,eAAeG,KAAK;oBACvB4F,YAAY;wBACV,GAAG/F,eAAeG,KAAK,EAAE4F,UAAU;wBACnCC,OAAO;4BACL,GAAGhG,eAAeG,KAAK,EAAE4F,YAAYC,KAAK;4BAC1CC,cAAc;gCAAEC,MAAM;gCAAkBC,OAAO;gCAAMC,MAAM;oCAAEC,OAAO;gCAAuB;gCAAGC,WAAW;oCACvGJ,MAAM;oCAAwCK,aAAa;wCAAEC,MAAM;oCAAY;gCACjF;4BAAE;4BACFC,gBAAgB;gCAAEP,MAAM;gCAAoBC,OAAO;gCAAMC,MAAM;oCAAEC,OAAO;gCAAiB;gCAAGC,WAAW;oCACrGJ,MAAM;oCAAwCK,aAAa;wCAAEC,MAAM;oCAAc;gCACnF;4BAAE;wBACJ;wBACA,sGAAsG;wBACtGE,eAAe;+BACT1G,eAAeG,KAAK,EAAE4F,YAAYW,iBAAiB,EAAE;4BACzD;yBACD;oBACH;gBACF;YAAE,IAAI,CAAC,CAAC;YACRjG,aAAa2E;YACbuB,WAAW;mBAAK3G,eAAe2G,SAAS,IAAI,EAAE;mBAAMd;mBAAkBrF,OAAOmG,aAAa,EAAE;aAAE;QAChG;IACF;AACF;AAEA,6EAA6E;AAC7E,yEAAyE;AACzE,SAASC,YAAY,EAAEC,YAAY,QAAQ,mBAAkB;AAE7D,SAASC,iBAAiB,QAAQ,gBAAe"}
@@ -1,11 +1,11 @@
1
- /**
2
- * True if the collection has Payload drafts enabled in its versions config.
1
+ /**
2
+ * True if the collection has Payload drafts enabled in its versions config.
3
3
  */ export function hasCollectionDrafts(collection) {
4
4
  const versions = collection.versions;
5
5
  return typeof versions === 'object' && versions !== null && 'drafts' in versions && Boolean(versions.drafts);
6
6
  }
7
- /**
8
- * Introspect a Payload collection config into structured metadata.
7
+ /**
8
+ * Introspect a Payload collection config into structured metadata.
9
9
  */ export function introspectCollection(collection) {
10
10
  const fields = extractFields(collection.fields);
11
11
  const relationships = extractRelationships(collection.fields);
@@ -27,8 +27,8 @@
27
27
  searchableFields
28
28
  };
29
29
  }
30
- /**
31
- * Introspect all collections into a map keyed by slug.
30
+ /**
31
+ * Introspect all collections into a map keyed by slug.
32
32
  */ export function introspectCollections(collections) {
33
33
  const map = new Map();
34
34
  for (const collection of collections){
@@ -36,16 +36,16 @@
36
36
  }
37
37
  return map;
38
38
  }
39
- /**
40
- * True if the global has Payload drafts enabled in its versions config.
41
- * Mirrors `hasCollectionDrafts` — globals use the same `versions.drafts`
42
- * shape as collections.
39
+ /**
40
+ * True if the global has Payload drafts enabled in its versions config.
41
+ * Mirrors `hasCollectionDrafts` — globals use the same `versions.drafts`
42
+ * shape as collections.
43
43
  */ export function hasGlobalDrafts(global) {
44
44
  const versions = global.versions;
45
45
  return typeof versions === 'object' && versions !== null && 'drafts' in versions && Boolean(versions.drafts);
46
46
  }
47
- /**
48
- * Introspect a Payload global config into structured metadata.
47
+ /**
48
+ * Introspect a Payload global config into structured metadata.
49
49
  */ export function introspectGlobal(global) {
50
50
  const fields = extractFields(global.fields);
51
51
  const hasLivePreview = !!(global.admin && typeof global.admin === 'object' && 'livePreview' in global.admin && global.admin.livePreview);
@@ -56,8 +56,8 @@
56
56
  hasLivePreview
57
57
  };
58
58
  }
59
- /**
60
- * Introspect all globals into a map keyed by slug.
59
+ /**
60
+ * Introspect all globals into a map keyed by slug.
61
61
  */ export function introspectGlobals(globals) {
62
62
  const map = new Map();
63
63
  for (const global of globals){
@@ -65,11 +65,11 @@
65
65
  }
66
66
  return map;
67
67
  }
68
- /**
69
- * Build a flat catalog of every block in the schema. Whether a block can
70
- * nest other blocks is represented separately in the BlockNestingMap, not
71
- * as a section/leaf classification — the AI reads both and composes
72
- * arbitrarily-nested layouts from there.
68
+ /**
69
+ * Build a flat catalog of every block in the schema. Whether a block can
70
+ * nest other blocks is represented separately in the BlockNestingMap, not
71
+ * as a section/leaf classification — the AI reads both and composes
72
+ * arbitrarily-nested layouts from there.
73
73
  */ export function introspectBlocks(blocks) {
74
74
  const catalog = blocks.map((block)=>({
75
75
  slug: block.slug,
@@ -79,13 +79,13 @@
79
79
  blocks: catalog
80
80
  };
81
81
  }
82
- /**
83
- * Walk every collection and every block, recording each `blocks`-typed
84
- * field's owner, dotted path, and accepted slugs.
85
- *
86
- * The AI uses this to compose layouts at any depth: it looks up which
87
- * slugs the relevant field accepts, picks one, then if that block has
88
- * its own `blocks` fields it recurses against the same map.
82
+ /**
83
+ * Walk every collection and every block, recording each `blocks`-typed
84
+ * field's owner, dotted path, and accepted slugs.
85
+ *
86
+ * The AI uses this to compose layouts at any depth: it looks up which
87
+ * slugs the relevant field accepts, picks one, then if that block has
88
+ * its own `blocks` fields it recurses against the same map.
89
89
  */ export function buildBlockNestingMap(collections, globalsOrBlocks, blocks) {
90
90
  // Back-compat overload: when called with two args, the second is `blocks`
91
91
  // and there are no globals. The new shape is `(collections, globals, blocks)`.
@@ -120,12 +120,12 @@
120
120
  assertBlockNestingMapInvariant(edges);
121
121
  return edges;
122
122
  }
123
- /**
124
- * Guard against `(owner, fieldPath)` collisions across different `ownerType`
125
- * values. Payload's own slug registry forbids collection/global slug
126
- * collisions, but a defensive check here keeps the validator lookup in
127
- * `patchLayout` / `patchGlobalLayout` unambiguous and surfaces config
128
- * mistakes loudly instead of silently picking the first match.
123
+ /**
124
+ * Guard against `(owner, fieldPath)` collisions across different `ownerType`
125
+ * values. Payload's own slug registry forbids collection/global slug
126
+ * collisions, but a defensive check here keeps the validator lookup in
127
+ * `patchLayout` / `patchGlobalLayout` unambiguous and surfaces config
128
+ * mistakes loudly instead of silently picking the first match.
129
129
  */ function assertBlockNestingMapInvariant(edges) {
130
130
  const seen = new Map();
131
131
  for (const edge of edges){
@@ -137,8 +137,8 @@
137
137
  seen.set(key, edge.ownerType);
138
138
  }
139
139
  }
140
- /**
141
- * Build a relationship graph from introspected collection schemas.
140
+ /**
141
+ * Build a relationship graph from introspected collection schemas.
142
142
  */ export function buildRelationshipGraph(schemas) {
143
143
  const edges = [];
144
144
  for (const [slug, schema] of schemas){
@@ -154,9 +154,9 @@
154
154
  return edges;
155
155
  }
156
156
  // ─── Internal helpers ──────────────────────────────────────────────
157
- /**
158
- * Recursively extract field metadata from a Payload fields array.
159
- * Handles tabs, groups, arrays, rows, and collapsible containers.
157
+ /**
158
+ * Recursively extract field metadata from a Payload fields array.
159
+ * Handles tabs, groups, arrays, rows, and collapsible containers.
160
160
  */ function extractFields(fields) {
161
161
  const result = [];
162
162
  for (const field of fields){
@@ -204,8 +204,8 @@
204
204
  }
205
205
  return result;
206
206
  }
207
- /**
208
- * Extract relationship metadata from fields (for the relationship graph).
207
+ /**
208
+ * Extract relationship metadata from fields (for the relationship graph).
209
209
  */ function extractRelationships(fields, prefix = '') {
210
210
  const rels = [];
211
211
  for (const field of fields){
@@ -246,10 +246,10 @@
246
246
  }
247
247
  return rels;
248
248
  }
249
- /**
250
- * Walk fields recording every `blocks`-typed field encountered, including
251
- * those nested in tabs/rows/groups/arrays/collapsibles. Each entry carries
252
- * the dotted path from the owner root to the field.
249
+ /**
250
+ * Walk fields recording every `blocks`-typed field encountered, including
251
+ * those nested in tabs/rows/groups/arrays/collapsibles. Each entry carries
252
+ * the dotted path from the owner root to the field.
253
253
  */ function collectBlocksFieldEdges(fields, ctx) {
254
254
  const edges = [];
255
255
  for (const field of fields){
@@ -308,10 +308,10 @@
308
308
  }
309
309
  return edges;
310
310
  }
311
- /**
312
- * Read block slugs from a blocks-typed field, handling both resolved
313
- * (field.blocks contains objects) and unresolved (field.blockReferences
314
- * holds slug strings) forms.
311
+ /**
312
+ * Read block slugs from a blocks-typed field, handling both resolved
313
+ * (field.blocks contains objects) and unresolved (field.blockReferences
314
+ * holds slug strings) forms.
315
315
  */ function readBlockSlugs(field) {
316
316
  const f = field;
317
317
  if (Array.isArray(f.blocks) && f.blocks.length > 0 && typeof f.blocks[0] === 'object' && f.blocks[0]?.slug) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/introspection.ts"],"sourcesContent":["import type { Block, CollectionConfig, Field, GlobalConfig } from 'payload'\r\nimport type {\r\n BlockCatalog,\r\n BlockNestingEdge,\r\n BlockNestingMap,\r\n BlockSchema,\r\n CollectionSchema,\r\n FieldSchema,\r\n GlobalSchema,\r\n RelationshipEdge,\r\n} from './types'\r\n\r\n/**\r\n * True if the collection has Payload drafts enabled in its versions config.\r\n */\r\nexport function hasCollectionDrafts(collection: CollectionConfig): boolean {\r\n const versions = collection.versions\r\n return (\r\n typeof versions === 'object' &&\r\n versions !== null &&\r\n 'drafts' in versions &&\r\n Boolean(versions.drafts)\r\n )\r\n}\r\n\r\n/**\r\n * Introspect a Payload collection config into structured metadata.\r\n */\r\nexport function introspectCollection(collection: CollectionConfig): CollectionSchema {\r\n const fields = extractFields(collection.fields)\r\n const relationships = extractRelationships(collection.fields)\r\n const searchableFields = fields\r\n .filter((f) => ['text', 'email'].includes(f.type) && ['name', 'title', 'slug'].includes(f.name))\r\n .map((f) => f.name)\r\n\r\n const hasLivePreview = !!(\r\n collection.admin &&\r\n typeof collection.admin === 'object' &&\r\n 'livePreview' in collection.admin &&\r\n collection.admin.livePreview\r\n )\r\n\r\n return {\r\n slug: collection.slug,\r\n fields,\r\n hasDrafts: hasCollectionDrafts(collection),\r\n hasLivePreview,\r\n relationships,\r\n searchableFields,\r\n }\r\n}\r\n\r\n/**\r\n * Introspect all collections into a map keyed by slug.\r\n */\r\nexport function introspectCollections(\r\n collections: CollectionConfig[],\r\n): Map<string, CollectionSchema> {\r\n const map = new Map<string, CollectionSchema>()\r\n for (const collection of collections) {\r\n map.set(collection.slug, introspectCollection(collection))\r\n }\r\n return map\r\n}\r\n\r\n/**\r\n * True if the global has Payload drafts enabled in its versions config.\r\n * Mirrors `hasCollectionDrafts` — globals use the same `versions.drafts`\r\n * shape as collections.\r\n */\r\nexport function hasGlobalDrafts(global: GlobalConfig): boolean {\r\n const versions = global.versions\r\n return (\r\n typeof versions === 'object' &&\r\n versions !== null &&\r\n 'drafts' in versions &&\r\n Boolean(versions.drafts)\r\n )\r\n}\r\n\r\n/**\r\n * Introspect a Payload global config into structured metadata.\r\n */\r\nexport function introspectGlobal(global: GlobalConfig): GlobalSchema {\r\n const fields = extractFields(global.fields)\r\n const hasLivePreview = !!(\r\n global.admin &&\r\n typeof global.admin === 'object' &&\r\n 'livePreview' in global.admin &&\r\n global.admin.livePreview\r\n )\r\n\r\n return {\r\n slug: global.slug,\r\n fields,\r\n hasDrafts: hasGlobalDrafts(global),\r\n hasLivePreview,\r\n }\r\n}\r\n\r\n/**\r\n * Introspect all globals into a map keyed by slug.\r\n */\r\nexport function introspectGlobals(globals: GlobalConfig[]): Map<string, GlobalSchema> {\r\n const map = new Map<string, GlobalSchema>()\r\n for (const global of globals) {\r\n map.set(global.slug, introspectGlobal(global))\r\n }\r\n return map\r\n}\r\n\r\n/**\r\n * Build a flat catalog of every block in the schema. Whether a block can\r\n * nest other blocks is represented separately in the BlockNestingMap, not\r\n * as a section/leaf classification — the AI reads both and composes\r\n * arbitrarily-nested layouts from there.\r\n */\r\nexport function introspectBlocks(blocks: Block[]): BlockCatalog {\r\n const catalog: BlockSchema[] = blocks.map((block) => ({\r\n slug: block.slug,\r\n fields: extractFields(block.fields),\r\n }))\r\n return { blocks: catalog }\r\n}\r\n\r\n/**\r\n * Walk every collection and every block, recording each `blocks`-typed\r\n * field's owner, dotted path, and accepted slugs.\r\n *\r\n * The AI uses this to compose layouts at any depth: it looks up which\r\n * slugs the relevant field accepts, picks one, then if that block has\r\n * its own `blocks` fields it recurses against the same map.\r\n */\r\nexport function buildBlockNestingMap(\r\n collections: CollectionConfig[],\r\n globalsOrBlocks: GlobalConfig[] | Block[],\r\n blocks?: Block[],\r\n): BlockNestingMap {\r\n // Back-compat overload: when called with two args, the second is `blocks`\r\n // and there are no globals. The new shape is `(collections, globals, blocks)`.\r\n const globals: GlobalConfig[] = blocks === undefined ? [] : (globalsOrBlocks as GlobalConfig[])\r\n const effectiveBlocks: Block[] =\r\n blocks === undefined ? (globalsOrBlocks as Block[]) : blocks\r\n\r\n const knownSlugs = new Set(effectiveBlocks.map((b) => b.slug))\r\n const edges: BlockNestingMap = []\r\n\r\n for (const collection of collections) {\r\n edges.push(\r\n ...collectBlocksFieldEdges(collection.fields, {\r\n owner: collection.slug,\r\n ownerType: 'collection',\r\n prefix: '',\r\n knownSlugs,\r\n }),\r\n )\r\n }\r\n\r\n for (const global of globals) {\r\n edges.push(\r\n ...collectBlocksFieldEdges(global.fields, {\r\n owner: global.slug,\r\n ownerType: 'global',\r\n prefix: '',\r\n knownSlugs,\r\n }),\r\n )\r\n }\r\n\r\n for (const block of effectiveBlocks) {\r\n edges.push(\r\n ...collectBlocksFieldEdges(block.fields, {\r\n owner: block.slug,\r\n ownerType: 'block',\r\n prefix: '',\r\n knownSlugs,\r\n }),\r\n )\r\n }\r\n\r\n assertBlockNestingMapInvariant(edges)\r\n return edges\r\n}\r\n\r\n/**\r\n * Guard against `(owner, fieldPath)` collisions across different `ownerType`\r\n * values. Payload's own slug registry forbids collection/global slug\r\n * collisions, but a defensive check here keeps the validator lookup in\r\n * `patchLayout` / `patchGlobalLayout` unambiguous and surfaces config\r\n * mistakes loudly instead of silently picking the first match.\r\n */\r\nfunction assertBlockNestingMapInvariant(edges: BlockNestingMap): void {\r\n const seen = new Map<string, BlockNestingEdge['ownerType']>()\r\n for (const edge of edges) {\r\n const key = `${edge.owner}.${edge.fieldPath}`\r\n const prior = seen.get(key)\r\n if (prior && prior !== edge.ownerType) {\r\n throw new Error(\r\n `[payload-mcp-toolkit] Block-nesting map invariant violated: ` +\r\n `\"${key}\" appears as both \"${prior}\" and \"${edge.ownerType}\". ` +\r\n `A collection and a global cannot share a slug; rename one.`,\r\n )\r\n }\r\n seen.set(key, edge.ownerType)\r\n }\r\n}\r\n\r\n/**\r\n * Build a relationship graph from introspected collection schemas.\r\n */\r\nexport function buildRelationshipGraph(\r\n schemas: Map<string, CollectionSchema>,\r\n): RelationshipEdge[] {\r\n const edges: RelationshipEdge[] = []\r\n for (const [slug, schema] of schemas) {\r\n for (const rel of schema.relationships) {\r\n edges.push({\r\n fromCollection: slug,\r\n fieldName: rel.fieldName,\r\n toCollection: rel.relationTo,\r\n hasMany: rel.hasMany,\r\n })\r\n }\r\n }\r\n return edges\r\n}\r\n\r\n// ─── Internal helpers ──────────────────────────────────────────────\r\n\r\n/**\r\n * Recursively extract field metadata from a Payload fields array.\r\n * Handles tabs, groups, arrays, rows, and collapsible containers.\r\n */\r\nfunction extractFields(fields: Field[]): FieldSchema[] {\r\n const result: FieldSchema[] = []\r\n\r\n for (const field of fields) {\r\n if ('name' in field && field.name) {\r\n const schema: FieldSchema = {\r\n name: field.name,\r\n type: field.type,\r\n }\r\n\r\n if ('required' in field && field.required) schema.required = true\r\n if ('hasMany' in field && field.hasMany) schema.hasMany = true\r\n if ('relationTo' in field && field.relationTo) {\r\n schema.relationTo = field.relationTo as string | string[]\r\n }\r\n if ('maxRows' in field && field.maxRows) schema.maxRows = field.maxRows\r\n\r\n if (field.type === 'select' && 'options' in field && Array.isArray(field.options)) {\r\n schema.options = field.options.map((opt) =>\r\n typeof opt === 'string'\r\n ? { label: opt, value: opt }\r\n : { label: String(opt.label), value: String(opt.value) },\r\n )\r\n }\r\n\r\n if (field.type === 'array' && 'fields' in field) {\r\n schema.fields = extractFields(field.fields)\r\n }\r\n if (field.type === 'group' && 'fields' in field) {\r\n schema.fields = extractFields(field.fields)\r\n }\r\n\r\n result.push(schema)\r\n }\r\n\r\n if (field.type === 'tabs' && 'tabs' in field) {\r\n for (const tab of field.tabs) {\r\n if ('fields' in tab) {\r\n result.push(...extractFields(tab.fields))\r\n }\r\n }\r\n }\r\n if (field.type === 'row' && 'fields' in field) {\r\n result.push(...extractFields(field.fields))\r\n }\r\n if (field.type === 'collapsible' && 'fields' in field) {\r\n result.push(...extractFields(field.fields))\r\n }\r\n }\r\n\r\n return result\r\n}\r\n\r\n/**\r\n * Extract relationship metadata from fields (for the relationship graph).\r\n */\r\nfunction extractRelationships(\r\n fields: Field[],\r\n prefix = '',\r\n): Array<{ fieldName: string; relationTo: string | string[]; hasMany: boolean }> {\r\n const rels: Array<{ fieldName: string; relationTo: string | string[]; hasMany: boolean }> = []\r\n\r\n for (const field of fields) {\r\n const fieldName = 'name' in field && field.name ? `${prefix}${field.name}` : prefix\r\n\r\n if (field.type === 'relationship' && 'relationTo' in field) {\r\n rels.push({\r\n fieldName,\r\n relationTo: field.relationTo as string | string[],\r\n hasMany: !!('hasMany' in field && field.hasMany),\r\n })\r\n }\r\n\r\n if (field.type === 'upload' && 'relationTo' in field) {\r\n rels.push({\r\n fieldName,\r\n relationTo: field.relationTo as string,\r\n hasMany: !!('hasMany' in field && field.hasMany),\r\n })\r\n }\r\n\r\n if (field.type === 'tabs' && 'tabs' in field) {\r\n for (const tab of field.tabs) {\r\n if ('fields' in tab) {\r\n rels.push(...extractRelationships(tab.fields, prefix))\r\n }\r\n }\r\n }\r\n if (field.type === 'group' && 'fields' in field) {\r\n rels.push(...extractRelationships(field.fields, `${fieldName}.`))\r\n }\r\n if (field.type === 'array' && 'fields' in field) {\r\n rels.push(...extractRelationships(field.fields, `${fieldName}[].`))\r\n }\r\n if (field.type === 'row' && 'fields' in field) {\r\n rels.push(...extractRelationships(field.fields, prefix))\r\n }\r\n if (field.type === 'collapsible' && 'fields' in field) {\r\n rels.push(...extractRelationships(field.fields, prefix))\r\n }\r\n }\r\n\r\n return rels\r\n}\r\n\r\ninterface NestingScanContext {\r\n owner: string\r\n ownerType: 'collection' | 'block' | 'global'\r\n prefix: string\r\n knownSlugs: Set<string>\r\n}\r\n\r\n/**\r\n * Walk fields recording every `blocks`-typed field encountered, including\r\n * those nested in tabs/rows/groups/arrays/collapsibles. Each entry carries\r\n * the dotted path from the owner root to the field.\r\n */\r\nfunction collectBlocksFieldEdges(fields: Field[], ctx: NestingScanContext): BlockNestingMap {\r\n const edges: BlockNestingMap = []\r\n\r\n for (const field of fields) {\r\n if (field.type === 'blocks') {\r\n const fieldName = 'name' in field && field.name ? field.name : ''\r\n const fullPath = ctx.prefix ? `${ctx.prefix}.${fieldName}` : fieldName\r\n const allSlugs = readBlockSlugs(field as Field & { type: 'blocks' })\r\n const acceptedSlugs = allSlugs.filter((s) => ctx.knownSlugs.has(s))\r\n\r\n const edge: BlockNestingMap[number] = {\r\n owner: ctx.owner,\r\n ownerType: ctx.ownerType,\r\n fieldPath: fullPath,\r\n acceptedBlockSlugs: acceptedSlugs,\r\n }\r\n const maxRows = (field as Field & { type: 'blocks' }).maxRows\r\n if (typeof maxRows === 'number') edge.maxRows = maxRows\r\n edges.push(edge)\r\n continue\r\n }\r\n\r\n if (field.type === 'tabs' && 'tabs' in field) {\r\n for (const tab of field.tabs) {\r\n if (!('fields' in tab)) continue\r\n const tabName = 'name' in tab && tab.name ? tab.name : ''\r\n const tabPrefix = tabName\r\n ? ctx.prefix\r\n ? `${ctx.prefix}.${tabName}`\r\n : tabName\r\n : ctx.prefix\r\n edges.push(...collectBlocksFieldEdges(tab.fields, { ...ctx, prefix: tabPrefix }))\r\n }\r\n continue\r\n }\r\n if (field.type === 'row' && 'fields' in field) {\r\n edges.push(...collectBlocksFieldEdges(field.fields, ctx))\r\n continue\r\n }\r\n if (field.type === 'collapsible' && 'fields' in field) {\r\n edges.push(...collectBlocksFieldEdges(field.fields, ctx))\r\n continue\r\n }\r\n if (field.type === 'group' && 'fields' in field && 'name' in field && field.name) {\r\n const newPrefix = ctx.prefix ? `${ctx.prefix}.${field.name}` : field.name\r\n edges.push(...collectBlocksFieldEdges(field.fields, { ...ctx, prefix: newPrefix }))\r\n continue\r\n }\r\n if (field.type === 'array' && 'fields' in field && 'name' in field && field.name) {\r\n const newPrefix = ctx.prefix ? `${ctx.prefix}.${field.name}[]` : `${field.name}[]`\r\n edges.push(...collectBlocksFieldEdges(field.fields, { ...ctx, prefix: newPrefix }))\r\n continue\r\n }\r\n }\r\n\r\n return edges\r\n}\r\n\r\n/**\r\n * Read block slugs from a blocks-typed field, handling both resolved\r\n * (field.blocks contains objects) and unresolved (field.blockReferences\r\n * holds slug strings) forms.\r\n */\r\nfunction readBlockSlugs(field: Field & { type: 'blocks' }): string[] {\r\n const f = field as any\r\n\r\n if (\r\n Array.isArray(f.blocks) &&\r\n f.blocks.length > 0 &&\r\n typeof f.blocks[0] === 'object' &&\r\n f.blocks[0]?.slug\r\n ) {\r\n return f.blocks.map((b: { slug: string }) => b.slug)\r\n }\r\n\r\n if (Array.isArray(f.blockReferences) && f.blockReferences.length > 0) {\r\n return f.blockReferences.filter((ref: unknown) => typeof ref === 'string') as string[]\r\n }\r\n\r\n return []\r\n}\r\n"],"names":["hasCollectionDrafts","collection","versions","Boolean","drafts","introspectCollection","fields","extractFields","relationships","extractRelationships","searchableFields","filter","f","includes","type","name","map","hasLivePreview","admin","livePreview","slug","hasDrafts","introspectCollections","collections","Map","set","hasGlobalDrafts","global","introspectGlobal","introspectGlobals","globals","introspectBlocks","blocks","catalog","block","buildBlockNestingMap","globalsOrBlocks","undefined","effectiveBlocks","knownSlugs","Set","b","edges","push","collectBlocksFieldEdges","owner","ownerType","prefix","assertBlockNestingMapInvariant","seen","edge","key","fieldPath","prior","get","Error","buildRelationshipGraph","schemas","schema","rel","fromCollection","fieldName","toCollection","relationTo","hasMany","result","field","required","maxRows","Array","isArray","options","opt","label","value","String","tab","tabs","rels","ctx","fullPath","allSlugs","readBlockSlugs","acceptedSlugs","s","has","acceptedBlockSlugs","tabName","tabPrefix","newPrefix","length","blockReferences","ref"],"mappings":"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"}
1
+ {"version":3,"sources":["../src/introspection.ts"],"sourcesContent":["import type { Block, CollectionConfig, Field, GlobalConfig } from 'payload'\nimport type {\n BlockCatalog,\n BlockNestingEdge,\n BlockNestingMap,\n BlockSchema,\n CollectionSchema,\n FieldSchema,\n GlobalSchema,\n RelationshipEdge,\n} from './types'\n\n/**\n * True if the collection has Payload drafts enabled in its versions config.\n */\nexport function hasCollectionDrafts(collection: CollectionConfig): boolean {\n const versions = collection.versions\n return (\n typeof versions === 'object' &&\n versions !== null &&\n 'drafts' in versions &&\n Boolean(versions.drafts)\n )\n}\n\n/**\n * Introspect a Payload collection config into structured metadata.\n */\nexport function introspectCollection(collection: CollectionConfig): CollectionSchema {\n const fields = extractFields(collection.fields)\n const relationships = extractRelationships(collection.fields)\n const searchableFields = fields\n .filter((f) => ['text', 'email'].includes(f.type) && ['name', 'title', 'slug'].includes(f.name))\n .map((f) => f.name)\n\n const hasLivePreview = !!(\n collection.admin &&\n typeof collection.admin === 'object' &&\n 'livePreview' in collection.admin &&\n collection.admin.livePreview\n )\n\n return {\n slug: collection.slug,\n fields,\n hasDrafts: hasCollectionDrafts(collection),\n hasLivePreview,\n relationships,\n searchableFields,\n }\n}\n\n/**\n * Introspect all collections into a map keyed by slug.\n */\nexport function introspectCollections(\n collections: CollectionConfig[],\n): Map<string, CollectionSchema> {\n const map = new Map<string, CollectionSchema>()\n for (const collection of collections) {\n map.set(collection.slug, introspectCollection(collection))\n }\n return map\n}\n\n/**\n * True if the global has Payload drafts enabled in its versions config.\n * Mirrors `hasCollectionDrafts` — globals use the same `versions.drafts`\n * shape as collections.\n */\nexport function hasGlobalDrafts(global: GlobalConfig): boolean {\n const versions = global.versions\n return (\n typeof versions === 'object' &&\n versions !== null &&\n 'drafts' in versions &&\n Boolean(versions.drafts)\n )\n}\n\n/**\n * Introspect a Payload global config into structured metadata.\n */\nexport function introspectGlobal(global: GlobalConfig): GlobalSchema {\n const fields = extractFields(global.fields)\n const hasLivePreview = !!(\n global.admin &&\n typeof global.admin === 'object' &&\n 'livePreview' in global.admin &&\n global.admin.livePreview\n )\n\n return {\n slug: global.slug,\n fields,\n hasDrafts: hasGlobalDrafts(global),\n hasLivePreview,\n }\n}\n\n/**\n * Introspect all globals into a map keyed by slug.\n */\nexport function introspectGlobals(globals: GlobalConfig[]): Map<string, GlobalSchema> {\n const map = new Map<string, GlobalSchema>()\n for (const global of globals) {\n map.set(global.slug, introspectGlobal(global))\n }\n return map\n}\n\n/**\n * Build a flat catalog of every block in the schema. Whether a block can\n * nest other blocks is represented separately in the BlockNestingMap, not\n * as a section/leaf classification — the AI reads both and composes\n * arbitrarily-nested layouts from there.\n */\nexport function introspectBlocks(blocks: Block[]): BlockCatalog {\n const catalog: BlockSchema[] = blocks.map((block) => ({\n slug: block.slug,\n fields: extractFields(block.fields),\n }))\n return { blocks: catalog }\n}\n\n/**\n * Walk every collection and every block, recording each `blocks`-typed\n * field's owner, dotted path, and accepted slugs.\n *\n * The AI uses this to compose layouts at any depth: it looks up which\n * slugs the relevant field accepts, picks one, then if that block has\n * its own `blocks` fields it recurses against the same map.\n */\nexport function buildBlockNestingMap(\n collections: CollectionConfig[],\n globalsOrBlocks: GlobalConfig[] | Block[],\n blocks?: Block[],\n): BlockNestingMap {\n // Back-compat overload: when called with two args, the second is `blocks`\n // and there are no globals. The new shape is `(collections, globals, blocks)`.\n const globals: GlobalConfig[] = blocks === undefined ? [] : (globalsOrBlocks as GlobalConfig[])\n const effectiveBlocks: Block[] =\n blocks === undefined ? (globalsOrBlocks as Block[]) : blocks\n\n const knownSlugs = new Set(effectiveBlocks.map((b) => b.slug))\n const edges: BlockNestingMap = []\n\n for (const collection of collections) {\n edges.push(\n ...collectBlocksFieldEdges(collection.fields, {\n owner: collection.slug,\n ownerType: 'collection',\n prefix: '',\n knownSlugs,\n }),\n )\n }\n\n for (const global of globals) {\n edges.push(\n ...collectBlocksFieldEdges(global.fields, {\n owner: global.slug,\n ownerType: 'global',\n prefix: '',\n knownSlugs,\n }),\n )\n }\n\n for (const block of effectiveBlocks) {\n edges.push(\n ...collectBlocksFieldEdges(block.fields, {\n owner: block.slug,\n ownerType: 'block',\n prefix: '',\n knownSlugs,\n }),\n )\n }\n\n assertBlockNestingMapInvariant(edges)\n return edges\n}\n\n/**\n * Guard against `(owner, fieldPath)` collisions across different `ownerType`\n * values. Payload's own slug registry forbids collection/global slug\n * collisions, but a defensive check here keeps the validator lookup in\n * `patchLayout` / `patchGlobalLayout` unambiguous and surfaces config\n * mistakes loudly instead of silently picking the first match.\n */\nfunction assertBlockNestingMapInvariant(edges: BlockNestingMap): void {\n const seen = new Map<string, BlockNestingEdge['ownerType']>()\n for (const edge of edges) {\n const key = `${edge.owner}.${edge.fieldPath}`\n const prior = seen.get(key)\n if (prior && prior !== edge.ownerType) {\n throw new Error(\n `[payload-mcp-toolkit] Block-nesting map invariant violated: ` +\n `\"${key}\" appears as both \"${prior}\" and \"${edge.ownerType}\". ` +\n `A collection and a global cannot share a slug; rename one.`,\n )\n }\n seen.set(key, edge.ownerType)\n }\n}\n\n/**\n * Build a relationship graph from introspected collection schemas.\n */\nexport function buildRelationshipGraph(\n schemas: Map<string, CollectionSchema>,\n): RelationshipEdge[] {\n const edges: RelationshipEdge[] = []\n for (const [slug, schema] of schemas) {\n for (const rel of schema.relationships) {\n edges.push({\n fromCollection: slug,\n fieldName: rel.fieldName,\n toCollection: rel.relationTo,\n hasMany: rel.hasMany,\n })\n }\n }\n return edges\n}\n\n// ─── Internal helpers ──────────────────────────────────────────────\n\n/**\n * Recursively extract field metadata from a Payload fields array.\n * Handles tabs, groups, arrays, rows, and collapsible containers.\n */\nfunction extractFields(fields: Field[]): FieldSchema[] {\n const result: FieldSchema[] = []\n\n for (const field of fields) {\n if ('name' in field && field.name) {\n const schema: FieldSchema = {\n name: field.name,\n type: field.type,\n }\n\n if ('required' in field && field.required) schema.required = true\n if ('hasMany' in field && field.hasMany) schema.hasMany = true\n if ('relationTo' in field && field.relationTo) {\n schema.relationTo = field.relationTo as string | string[]\n }\n if ('maxRows' in field && field.maxRows) schema.maxRows = field.maxRows\n\n if (field.type === 'select' && 'options' in field && Array.isArray(field.options)) {\n schema.options = field.options.map((opt) =>\n typeof opt === 'string'\n ? { label: opt, value: opt }\n : { label: String(opt.label), value: String(opt.value) },\n )\n }\n\n if (field.type === 'array' && 'fields' in field) {\n schema.fields = extractFields(field.fields)\n }\n if (field.type === 'group' && 'fields' in field) {\n schema.fields = extractFields(field.fields)\n }\n\n result.push(schema)\n }\n\n if (field.type === 'tabs' && 'tabs' in field) {\n for (const tab of field.tabs) {\n if ('fields' in tab) {\n result.push(...extractFields(tab.fields))\n }\n }\n }\n if (field.type === 'row' && 'fields' in field) {\n result.push(...extractFields(field.fields))\n }\n if (field.type === 'collapsible' && 'fields' in field) {\n result.push(...extractFields(field.fields))\n }\n }\n\n return result\n}\n\n/**\n * Extract relationship metadata from fields (for the relationship graph).\n */\nfunction extractRelationships(\n fields: Field[],\n prefix = '',\n): Array<{ fieldName: string; relationTo: string | string[]; hasMany: boolean }> {\n const rels: Array<{ fieldName: string; relationTo: string | string[]; hasMany: boolean }> = []\n\n for (const field of fields) {\n const fieldName = 'name' in field && field.name ? `${prefix}${field.name}` : prefix\n\n if (field.type === 'relationship' && 'relationTo' in field) {\n rels.push({\n fieldName,\n relationTo: field.relationTo as string | string[],\n hasMany: !!('hasMany' in field && field.hasMany),\n })\n }\n\n if (field.type === 'upload' && 'relationTo' in field) {\n rels.push({\n fieldName,\n relationTo: field.relationTo as string,\n hasMany: !!('hasMany' in field && field.hasMany),\n })\n }\n\n if (field.type === 'tabs' && 'tabs' in field) {\n for (const tab of field.tabs) {\n if ('fields' in tab) {\n rels.push(...extractRelationships(tab.fields, prefix))\n }\n }\n }\n if (field.type === 'group' && 'fields' in field) {\n rels.push(...extractRelationships(field.fields, `${fieldName}.`))\n }\n if (field.type === 'array' && 'fields' in field) {\n rels.push(...extractRelationships(field.fields, `${fieldName}[].`))\n }\n if (field.type === 'row' && 'fields' in field) {\n rels.push(...extractRelationships(field.fields, prefix))\n }\n if (field.type === 'collapsible' && 'fields' in field) {\n rels.push(...extractRelationships(field.fields, prefix))\n }\n }\n\n return rels\n}\n\ninterface NestingScanContext {\n owner: string\n ownerType: 'collection' | 'block' | 'global'\n prefix: string\n knownSlugs: Set<string>\n}\n\n/**\n * Walk fields recording every `blocks`-typed field encountered, including\n * those nested in tabs/rows/groups/arrays/collapsibles. Each entry carries\n * the dotted path from the owner root to the field.\n */\nfunction collectBlocksFieldEdges(fields: Field[], ctx: NestingScanContext): BlockNestingMap {\n const edges: BlockNestingMap = []\n\n for (const field of fields) {\n if (field.type === 'blocks') {\n const fieldName = 'name' in field && field.name ? field.name : ''\n const fullPath = ctx.prefix ? `${ctx.prefix}.${fieldName}` : fieldName\n const allSlugs = readBlockSlugs(field as Field & { type: 'blocks' })\n const acceptedSlugs = allSlugs.filter((s) => ctx.knownSlugs.has(s))\n\n const edge: BlockNestingMap[number] = {\n owner: ctx.owner,\n ownerType: ctx.ownerType,\n fieldPath: fullPath,\n acceptedBlockSlugs: acceptedSlugs,\n }\n const maxRows = (field as Field & { type: 'blocks' }).maxRows\n if (typeof maxRows === 'number') edge.maxRows = maxRows\n edges.push(edge)\n continue\n }\n\n if (field.type === 'tabs' && 'tabs' in field) {\n for (const tab of field.tabs) {\n if (!('fields' in tab)) continue\n const tabName = 'name' in tab && tab.name ? tab.name : ''\n const tabPrefix = tabName\n ? ctx.prefix\n ? `${ctx.prefix}.${tabName}`\n : tabName\n : ctx.prefix\n edges.push(...collectBlocksFieldEdges(tab.fields, { ...ctx, prefix: tabPrefix }))\n }\n continue\n }\n if (field.type === 'row' && 'fields' in field) {\n edges.push(...collectBlocksFieldEdges(field.fields, ctx))\n continue\n }\n if (field.type === 'collapsible' && 'fields' in field) {\n edges.push(...collectBlocksFieldEdges(field.fields, ctx))\n continue\n }\n if (field.type === 'group' && 'fields' in field && 'name' in field && field.name) {\n const newPrefix = ctx.prefix ? `${ctx.prefix}.${field.name}` : field.name\n edges.push(...collectBlocksFieldEdges(field.fields, { ...ctx, prefix: newPrefix }))\n continue\n }\n if (field.type === 'array' && 'fields' in field && 'name' in field && field.name) {\n const newPrefix = ctx.prefix ? `${ctx.prefix}.${field.name}[]` : `${field.name}[]`\n edges.push(...collectBlocksFieldEdges(field.fields, { ...ctx, prefix: newPrefix }))\n continue\n }\n }\n\n return edges\n}\n\n/**\n * Read block slugs from a blocks-typed field, handling both resolved\n * (field.blocks contains objects) and unresolved (field.blockReferences\n * holds slug strings) forms.\n */\nfunction readBlockSlugs(field: Field & { type: 'blocks' }): string[] {\n const f = field as any\n\n if (\n Array.isArray(f.blocks) &&\n f.blocks.length > 0 &&\n typeof f.blocks[0] === 'object' &&\n f.blocks[0]?.slug\n ) {\n return f.blocks.map((b: { slug: string }) => b.slug)\n }\n\n if (Array.isArray(f.blockReferences) && f.blockReferences.length > 0) {\n return f.blockReferences.filter((ref: unknown) => typeof ref === 'string') as string[]\n }\n\n return []\n}\n"],"names":["hasCollectionDrafts","collection","versions","Boolean","drafts","introspectCollection","fields","extractFields","relationships","extractRelationships","searchableFields","filter","f","includes","type","name","map","hasLivePreview","admin","livePreview","slug","hasDrafts","introspectCollections","collections","Map","set","hasGlobalDrafts","global","introspectGlobal","introspectGlobals","globals","introspectBlocks","blocks","catalog","block","buildBlockNestingMap","globalsOrBlocks","undefined","effectiveBlocks","knownSlugs","Set","b","edges","push","collectBlocksFieldEdges","owner","ownerType","prefix","assertBlockNestingMapInvariant","seen","edge","key","fieldPath","prior","get","Error","buildRelationshipGraph","schemas","schema","rel","fromCollection","fieldName","toCollection","relationTo","hasMany","result","field","required","maxRows","Array","isArray","options","opt","label","value","String","tab","tabs","rels","ctx","fullPath","allSlugs","readBlockSlugs","acceptedSlugs","s","has","acceptedBlockSlugs","tabName","tabPrefix","newPrefix","length","blockReferences","ref"],"mappings":"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"}