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.
- package/README.md +100 -237
- package/dist/api-keys.js +16 -0
- package/dist/api-keys.js.map +1 -1
- package/dist/auth-strategy.js +49 -49
- package/dist/auth-strategy.js.map +1 -1
- package/dist/components/AgentConnectPill.d.ts +3 -0
- package/dist/components/AgentConnectPill.js +121 -0
- package/dist/components/AgentConnectPill.js.map +1 -0
- package/dist/components/CollectionScopesMatrix.js.map +1 -1
- package/dist/components/ConsentPermissions.d.ts +10 -0
- package/dist/components/ConsentPermissions.js +165 -0
- package/dist/components/ConsentPermissions.js.map +1 -0
- package/dist/components/GlobalScopesMatrix.js.map +1 -1
- package/dist/components/OAuthView.d.ts +4 -0
- package/dist/components/OAuthView.js +269 -0
- package/dist/components/OAuthView.js.map +1 -0
- package/dist/components/ScopesTable.d.ts +28 -0
- package/dist/components/ScopesTable.js +165 -130
- package/dist/components/ScopesTable.js.map +1 -1
- package/dist/components/agentInstructions.d.ts +2 -0
- package/dist/components/agentInstructions.js +34 -0
- package/dist/components/agentInstructions.js.map +1 -0
- package/dist/components/index.d.ts +2 -0
- package/dist/components/index.js +2 -0
- package/dist/components/index.js.map +1 -1
- package/dist/components/oauth.css +111 -0
- package/dist/conflict-detection.js +13 -13
- package/dist/conflict-detection.js.map +1 -1
- package/dist/draft-workflow.js +26 -26
- package/dist/draft-workflow.js.map +1 -1
- package/dist/endpoint.d.ts +5 -0
- package/dist/endpoint.js +21 -13
- package/dist/endpoint.js.map +1 -1
- package/dist/hash.js +15 -15
- package/dist/hash.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +67 -3
- package/dist/index.js.map +1 -1
- package/dist/introspection.js +47 -47
- package/dist/introspection.js.map +1 -1
- package/dist/oauth-permissions.d.ts +52 -0
- package/dist/oauth-permissions.js +100 -0
- package/dist/oauth-permissions.js.map +1 -0
- package/dist/oauth-store.d.ts +19 -0
- package/dist/oauth-store.js +122 -0
- package/dist/oauth-store.js.map +1 -0
- package/dist/oauth.d.ts +19 -0
- package/dist/oauth.js +523 -0
- package/dist/oauth.js.map +1 -0
- package/dist/prompts.js +5 -5
- package/dist/prompts.js.map +1 -1
- package/dist/registry.js +7 -1
- package/dist/registry.js.map +1 -1
- package/dist/resources.js +10 -10
- package/dist/resources.js.map +1 -1
- package/dist/scope/audit-log.js +9 -9
- package/dist/scope/audit-log.js.map +1 -1
- package/dist/scope/policy.js +7 -7
- package/dist/scope/policy.js.map +1 -1
- package/dist/tools/_helpers.d.ts +10 -0
- package/dist/tools/_helpers.js +53 -41
- package/dist/tools/_helpers.js.map +1 -1
- package/dist/tools/_layout-helpers.js +33 -33
- package/dist/tools/_layout-helpers.js.map +1 -1
- package/dist/tools/create-document.js +20 -19
- package/dist/tools/create-document.js.map +1 -1
- package/dist/tools/delete-document.js +10 -9
- package/dist/tools/delete-document.js.map +1 -1
- package/dist/tools/find-document.js +18 -15
- package/dist/tools/find-document.js.map +1 -1
- package/dist/tools/find-global.js +13 -13
- package/dist/tools/find-global.js.map +1 -1
- package/dist/tools/global-versions.js +8 -7
- package/dist/tools/global-versions.js.map +1 -1
- package/dist/tools/patch-global-layout.js +9 -9
- package/dist/tools/patch-global-layout.js.map +1 -1
- package/dist/tools/patch-layout.js +15 -14
- package/dist/tools/patch-layout.js.map +1 -1
- package/dist/tools/publish-draft.js +2 -1
- package/dist/tools/publish-draft.js.map +1 -1
- package/dist/tools/publish-global-draft.js +4 -4
- package/dist/tools/publish-global-draft.js.map +1 -1
- package/dist/tools/resolve-reference.js.map +1 -1
- package/dist/tools/safe-delete.js +14 -14
- package/dist/tools/safe-delete.js.map +1 -1
- package/dist/tools/schedule-publish.js +21 -20
- package/dist/tools/schedule-publish.js.map +1 -1
- package/dist/tools/search-content.js +12 -12
- package/dist/tools/search-content.js.map +1 -1
- package/dist/tools/update-document.js +6 -5
- package/dist/tools/update-document.js.map +1 -1
- package/dist/tools/update-global.js +9 -9
- package/dist/tools/update-global.js.map +1 -1
- package/dist/tools/upload-media.js +2 -1
- package/dist/tools/upload-media.js.map +1 -1
- package/dist/tools/versions.js +10 -8
- package/dist/tools/versions.js.map +1 -1
- package/dist/types.d.ts +3 -0
- package/dist/types.js.map +1 -1
- package/docs/oauth.md +96 -0
- 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'\
|
|
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":"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"}
|
package/dist/introspection.js
CHANGED
|
@@ -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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"}
|