@forumone/throughline-core 0.6.0 → 0.8.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 (47) hide show
  1. package/CHANGELOG.md +94 -0
  2. package/README.md +8 -3
  3. package/dist/index.d.ts +4 -6
  4. package/dist/index.d.ts.map +1 -1
  5. package/dist/index.js +2 -3
  6. package/dist/index.js.map +1 -1
  7. package/dist/mcp/collector.d.ts +23 -6
  8. package/dist/mcp/collector.d.ts.map +1 -1
  9. package/dist/mcp/collector.js +51 -8
  10. package/dist/mcp/collector.js.map +1 -1
  11. package/dist/mcp/index.d.ts +1 -3
  12. package/dist/mcp/index.d.ts.map +1 -1
  13. package/dist/mcp/index.js +0 -1
  14. package/dist/mcp/index.js.map +1 -1
  15. package/dist/mcp/payload-mcp.d.ts.map +1 -1
  16. package/dist/mcp/payload-mcp.js.map +1 -1
  17. package/dist/utils/content-hash.js +1 -1
  18. package/dist/utils/content-hash.js.map +1 -1
  19. package/dist/utils/index.d.ts +2 -0
  20. package/dist/utils/index.d.ts.map +1 -1
  21. package/dist/utils/index.js +2 -0
  22. package/dist/utils/index.js.map +1 -1
  23. package/dist/utils/sha256.d.ts +10 -0
  24. package/dist/utils/sha256.d.ts.map +1 -0
  25. package/dist/utils/sha256.js +16 -0
  26. package/dist/utils/sha256.js.map +1 -0
  27. package/dist/utils/zod-issues.d.ts +19 -0
  28. package/dist/utils/zod-issues.d.ts.map +1 -0
  29. package/dist/utils/zod-issues.js +22 -0
  30. package/dist/utils/zod-issues.js.map +1 -0
  31. package/package.json +2 -2
  32. package/dist/auth/api-keys.d.ts +0 -21
  33. package/dist/auth/api-keys.d.ts.map +0 -1
  34. package/dist/auth/api-keys.js +0 -115
  35. package/dist/auth/api-keys.js.map +0 -1
  36. package/dist/auth/authenticator.d.ts +0 -19
  37. package/dist/auth/authenticator.d.ts.map +0 -1
  38. package/dist/auth/authenticator.js +0 -74
  39. package/dist/auth/authenticator.js.map +0 -1
  40. package/dist/auth/index.d.ts +0 -5
  41. package/dist/auth/index.d.ts.map +0 -1
  42. package/dist/auth/index.js +0 -3
  43. package/dist/auth/index.js.map +0 -1
  44. package/dist/mcp/handler.d.ts +0 -20
  45. package/dist/mcp/handler.d.ts.map +0 -1
  46. package/dist/mcp/handler.js +0 -132
  47. package/dist/mcp/handler.js.map +0 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,99 @@
1
1
  # @forumone/throughline-core
2
2
 
3
+ ## 0.8.0
4
+
5
+ ### Minor Changes
6
+
7
+ - a9262da: Per-tool gating works, because tool names no longer wait for `onInit`
8
+
9
+ `@payloadcms/plugin-mcp` generates one per-key checkbox per tool while the host's
10
+ config is being built, and then gates every call on the checkbox matching the
11
+ tool's name. Every Throughline tool was built at `onInit` — each closes over
12
+ `payload`, the publishing service or the manifest loader — so the array it maps
13
+ over was empty, no checkboxes were generated, and its `?? false` denied all 27
14
+ tools to every key. A valid key got a 200 and an empty `tools/list`, with nothing
15
+ wrong on either side.
16
+
17
+ The plugin needs only `name` and `description` then, and neither needs a Payload.
18
+ So a server now **declares** its tools as the config is built and **binds** their
19
+ handlers at `onInit`:
20
+
21
+ ```ts
22
+ options.mcpTools?.declare(PUBLISHING_TOOL_DESCRIPTORS, { serverName: 'publishing' })
23
+ // …later, at onInit:
24
+ options.mcpTools?.add(tools, { serverName: 'publishing' })
25
+ ```
26
+
27
+ Each package gained a `tools/descriptors.ts` holding every tool's name and
28
+ description; the factories spread from it, so the checkbox and the MCP client
29
+ cannot describe a tool differently. A `descriptors.test.ts` in each package
30
+ asserts the two sets match, without needing a database.
31
+
32
+ `createMcpToolCollector` gains `declare()` and an `unbound` list. Both mismatches
33
+ are refused rather than absorbed: a tool built but never declared throws at
34
+ `onInit` (it would otherwise be denied to every key, silently), and a tool
35
+ declared but never bound stays advertised with a handler that explains itself.
36
+
37
+ **Order in the host's plugin array is now load-bearing.** Every tool-bearing
38
+ server must come before `mcpPlugin`, or it declares into an array that has
39
+ already been read. It was only a convention before; it is a requirement now, and
40
+ the failure mode — a server's tools missing from every key — is the one this
41
+ change exists to remove.
42
+
43
+ `requiredScope` stays declared and read by nothing. Enforcement is the checkbox;
44
+ these record which tools are consequential, and are the mapping a scope-aware
45
+ default would be built from.
46
+
47
+ The playground registers `mcpPlugin` for the first time, so the suite's only
48
+ end-to-end host now exercises the tools rather than just their composition.
49
+
50
+ ## 0.7.0
51
+
52
+ ### Minor Changes
53
+
54
+ - 3140ea0: One MCP transport, not seven
55
+
56
+ Every plugin served its own `POST /<prefix>/mcp` on a 146-line JSON-RPC subset of
57
+ the protocol that spoke `tools/list` and `tools/call` and nothing else. Payload
58
+ ships an MCP server built on the official SDK — streamable HTTP, sessions, per-key
59
+ capability checkboxes — and the tools were never the transport. They now reach a
60
+ client through the host's `@payloadcms/plugin-mcp`, on one `/api/mcp`, via the
61
+ collector `createMcpToolCollector` already provided.
62
+
63
+ **Breaking.** Removed from `@forumone/throughline-core`: `createMcpHandler`,
64
+ `McpHandlerOptions`, `createApiKeysCollection`, `ApiKeysCollectionOptions`,
65
+ `DEFAULT_API_KEYS_SLUG`, `createBearerTokenAuthenticator`,
66
+ `BearerTokenAuthenticatorOptions`, `generateApiKey`. Removed from
67
+ `@forumone/throughline-plugin-contract`: `McpAuthenticator`, `McpAuthResult`.
68
+ `sha256Hex` stays exported, from `./utils` rather than `./auth`.
69
+
70
+ `routePrefix` is gone from `auditQueryPlugin`, `componentsPlugin` and
71
+ `integrationsPlugin` — omitted from their options types, so passing one is a
72
+ compile error rather than config that reads as if it does something. `/mcp` was
73
+ the only endpoint any of the three served. `publishingPlugin`, `approvalsPlugin`
74
+ and `formsPlugin` keep theirs; they still serve admin controls, the approval
75
+ action link and the public form post.
76
+
77
+ **A host that passes no `mcpTools` collector now has no MCP surface.** There is no
78
+ per-server endpoint left as a fallback. This is a config change of one line per
79
+ plugin, and `createMcpToolCollector`'s own docs carry the shape.
80
+
81
+ **What this costs, stated plainly.** `requiredScope` is now read by nothing —
82
+ `plugin-mcp` gates on checkboxes generated at config time, which this suite cannot
83
+ fill because every tool is built at `onInit`. So a key that authenticates reaches
84
+ every collected tool, exactly as an all-or-nothing per-server key did. The
85
+ declarations are kept because they are the mapping those checkboxes need; #78
86
+ tracks restoring enforcement, and the type's own doc comment says so.
87
+
88
+ Also drops the key collection from the playground, which leaves that app with no
89
+ MCP surface at all until `mcpPlugin` can be wired there — #79, blocked on moving
90
+ it off `payload@^3.83.0`.
91
+
92
+ ### Patch Changes
93
+
94
+ - Updated dependencies [3140ea0]
95
+ - @forumone/throughline-plugin-contract@0.4.0
96
+
3
97
  ## 0.6.0
4
98
 
5
99
  ### Minor Changes
package/README.md CHANGED
@@ -7,11 +7,16 @@ The shared plumbing every Throughline server package depends on. Drop it into a
7
7
  | Subsystem | Subpath | Role |
8
8
  |---|---|---|
9
9
  | Audit | `./audit` | `auditPlugin`, `createAuditCollection`, `createAuditWriter`, `getAuditWriter`, `AUDIT_ACTIONS`, `AUDIT_MCP_SERVERS` |
10
- | Auth | `./auth` | `createApiKeysCollection`, `createBearerTokenAuthenticator`, `generateApiKey`, `sha256Hex` |
11
10
  | Events | `./events` | `createInngestClient`, `CoreEvents`, `FrameworkEvents` (module-augmentation seam) |
12
- | MCP | `./mcp` | `createMcpHandler`, `McpMetaSchema`, `withMeta` |
11
+ | MCP | `./mcp` | `createMcpToolCollector`, `toPayloadMcpTools`, `McpMetaSchema`, `withMeta`, `auditContext` |
13
12
  | Logger | (main) | `defaultLogger`, `createNamedLogger` |
14
- | Utils | (main) | `documentContentHash` |
13
+ | Utils | (main) | `documentContentHash`, `sha256Hex`, `formatZodIssues` |
14
+
15
+ There is no `./auth` any more. It held an MCP key collection, a bearer-token
16
+ authenticator and `createMcpHandler` — a JSON-RPC subset each plugin mounted at its
17
+ own `/mcp`. `@payloadcms/plugin-mcp` owns the transport, the keys and authentication
18
+ now; `createMcpToolCollector` is how this suite's tools get to it. `sha256Hex`
19
+ survived, under `./utils`.
15
20
 
16
21
  The main entry re-exports everything; the subpath exports keep bundles smaller for consumers who only need one slice.
17
22
 
package/dist/index.d.ts CHANGED
@@ -1,13 +1,11 @@
1
1
  export { AUDIT_ACTIONS, AUDIT_MCP_SERVERS, DEFAULT_AUDIT_SLUG, auditPlugin, createAuditCollection, createAuditWriter, getAuditWriter, } from './audit/index.js';
2
2
  export type { AuditAction, AuditActor, AuditCollectionOptions, AuditEventInput, AuditMcpServer, AuditPluginOptions, AuditWriter, AuditWriterOptions, } from './audit/index.js';
3
- export { DEFAULT_API_KEYS_SLUG, createApiKeysCollection, createBearerTokenAuthenticator, generateApiKey, sha256Hex, } from './auth/index.js';
4
- export type { ApiKeysCollectionOptions, BearerTokenAuthenticatorOptions } from './auth/index.js';
5
3
  export { createInngestClient } from './events/index.js';
6
4
  export type { CoreEvents, FrameworkEvents, InngestClientOptions } from './events/index.js';
7
- export { McpMetaSchema, auditContext, deniedEnvelope, createMcpHandler, createMcpToolCollector, toPayloadMcpTool, toPayloadMcpTools, withMeta, } from './mcp/index.js';
8
- export type { AddToolsOptions, AuditContextFields, CreateMcpToolCollectorOptions, McpHandlerOptions, McpMeta, McpToolCollector, PayloadMcpRequest, PayloadMcpTool, ToPayloadMcpToolOptions, } from './mcp/index.js';
5
+ export { McpMetaSchema, auditContext, deniedEnvelope, createMcpToolCollector, toPayloadMcpTool, toPayloadMcpTools, withMeta, } from './mcp/index.js';
6
+ export type { AddToolsOptions, AuditContextFields, CreateMcpToolCollectorOptions, DeclareToolsOptions, McpMeta, McpToolCollector, McpToolDescriptor, PayloadMcpRequest, PayloadMcpTool, ToPayloadMcpToolOptions, } from './mcp/index.js';
9
7
  export { defaultLogger, createNamedLogger } from './logger/index.js';
10
- export { documentContentHash, unwrapRelationshipId } from './utils/index.js';
8
+ export { documentContentHash, formatZodIssues, sha256Hex, unwrapRelationshipId, } from './utils/index.js';
11
9
  export type { DocumentContentHashOptions } from './utils/index.js';
12
- export type { AuthenticatedUser, BaseCorePluginOptions, CorePlugin, Logger, McpAuthResult, McpAuthenticator, McpToolContext, McpToolDefinition, PluginRegistry, PluginRegistryEntry, } from '@forumone/throughline-plugin-contract';
10
+ export type { AuthenticatedUser, BaseCorePluginOptions, CorePlugin, Logger, McpToolContext, McpToolDefinition, PluginRegistry, PluginRegistryEntry, } from '@forumone/throughline-plugin-contract';
13
11
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,aAAa,EACb,iBAAiB,EACjB,kBAAkB,EAClB,WAAW,EACX,qBAAqB,EACrB,iBAAiB,EACjB,cAAc,GACf,MAAM,kBAAkB,CAAA;AACzB,YAAY,EACV,WAAW,EACX,UAAU,EACV,sBAAsB,EACtB,eAAe,EACf,cAAc,EACd,kBAAkB,EAClB,WAAW,EACX,kBAAkB,GACnB,MAAM,kBAAkB,CAAA;AAEzB,OAAO,EACL,qBAAqB,EACrB,uBAAuB,EACvB,8BAA8B,EAC9B,cAAc,EACd,SAAS,GACV,MAAM,iBAAiB,CAAA;AACxB,YAAY,EAAE,wBAAwB,EAAE,+BAA+B,EAAE,MAAM,iBAAiB,CAAA;AAEhG,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;AACvD,YAAY,EAAE,UAAU,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAA;AAE1F,OAAO,EACL,aAAa,EACb,YAAY,EACZ,cAAc,EACd,gBAAgB,EAChB,sBAAsB,EACtB,gBAAgB,EAChB,iBAAiB,EACjB,QAAQ,GACT,MAAM,gBAAgB,CAAA;AACvB,YAAY,EACV,eAAe,EACf,kBAAkB,EAClB,6BAA6B,EAC7B,iBAAiB,EACjB,OAAO,EACP,gBAAgB,EAChB,iBAAiB,EACjB,cAAc,EACd,uBAAuB,GACxB,MAAM,gBAAgB,CAAA;AAEvB,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AAEpE,OAAO,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAA;AAC5E,YAAY,EAAE,0BAA0B,EAAE,MAAM,kBAAkB,CAAA;AAIlE,YAAY,EACV,iBAAiB,EACjB,qBAAqB,EACrB,UAAU,EACV,MAAM,EACN,aAAa,EACb,gBAAgB,EAChB,cAAc,EACd,iBAAiB,EACjB,cAAc,EACd,mBAAmB,GACpB,MAAM,uCAAuC,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,aAAa,EACb,iBAAiB,EACjB,kBAAkB,EAClB,WAAW,EACX,qBAAqB,EACrB,iBAAiB,EACjB,cAAc,GACf,MAAM,kBAAkB,CAAA;AACzB,YAAY,EACV,WAAW,EACX,UAAU,EACV,sBAAsB,EACtB,eAAe,EACf,cAAc,EACd,kBAAkB,EAClB,WAAW,EACX,kBAAkB,GACnB,MAAM,kBAAkB,CAAA;AAEzB,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;AACvD,YAAY,EAAE,UAAU,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAA;AAE1F,OAAO,EACL,aAAa,EACb,YAAY,EACZ,cAAc,EACd,sBAAsB,EACtB,gBAAgB,EAChB,iBAAiB,EACjB,QAAQ,GACT,MAAM,gBAAgB,CAAA;AACvB,YAAY,EACV,eAAe,EACf,kBAAkB,EAClB,6BAA6B,EAC7B,mBAAmB,EACnB,OAAO,EACP,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,EACjB,cAAc,EACd,uBAAuB,GACxB,MAAM,gBAAgB,CAAA;AAEvB,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AAEpE,OAAO,EACL,mBAAmB,EACnB,eAAe,EACf,SAAS,EACT,oBAAoB,GACrB,MAAM,kBAAkB,CAAA;AACzB,YAAY,EAAE,0BAA0B,EAAE,MAAM,kBAAkB,CAAA;AAIlE,YAAY,EACV,iBAAiB,EACjB,qBAAqB,EACrB,UAAU,EACV,MAAM,EACN,cAAc,EACd,iBAAiB,EACjB,cAAc,EACd,mBAAmB,GACpB,MAAM,uCAAuC,CAAA"}
package/dist/index.js CHANGED
@@ -1,9 +1,8 @@
1
1
  // Subsystems are re-exported as they are added during C4. The aggregated
2
2
  // surface here mirrors the package's `./<subpath>` exports.
3
3
  export { AUDIT_ACTIONS, AUDIT_MCP_SERVERS, DEFAULT_AUDIT_SLUG, auditPlugin, createAuditCollection, createAuditWriter, getAuditWriter, } from './audit/index.js';
4
- export { DEFAULT_API_KEYS_SLUG, createApiKeysCollection, createBearerTokenAuthenticator, generateApiKey, sha256Hex, } from './auth/index.js';
5
4
  export { createInngestClient } from './events/index.js';
6
- export { McpMetaSchema, auditContext, deniedEnvelope, createMcpHandler, createMcpToolCollector, toPayloadMcpTool, toPayloadMcpTools, withMeta, } from './mcp/index.js';
5
+ export { McpMetaSchema, auditContext, deniedEnvelope, createMcpToolCollector, toPayloadMcpTool, toPayloadMcpTools, withMeta, } from './mcp/index.js';
7
6
  export { defaultLogger, createNamedLogger } from './logger/index.js';
8
- export { documentContentHash, unwrapRelationshipId } from './utils/index.js';
7
+ export { documentContentHash, formatZodIssues, sha256Hex, unwrapRelationshipId, } from './utils/index.js';
9
8
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,4DAA4D;AAE5D,OAAO,EACL,aAAa,EACb,iBAAiB,EACjB,kBAAkB,EAClB,WAAW,EACX,qBAAqB,EACrB,iBAAiB,EACjB,cAAc,GACf,MAAM,kBAAkB,CAAA;AAYzB,OAAO,EACL,qBAAqB,EACrB,uBAAuB,EACvB,8BAA8B,EAC9B,cAAc,EACd,SAAS,GACV,MAAM,iBAAiB,CAAA;AAGxB,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;AAGvD,OAAO,EACL,aAAa,EACb,YAAY,EACZ,cAAc,EACd,gBAAgB,EAChB,sBAAsB,EACtB,gBAAgB,EAChB,iBAAiB,EACjB,QAAQ,GACT,MAAM,gBAAgB,CAAA;AAavB,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AAEpE,OAAO,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,4DAA4D;AAE5D,OAAO,EACL,aAAa,EACb,iBAAiB,EACjB,kBAAkB,EAClB,WAAW,EACX,qBAAqB,EACrB,iBAAiB,EACjB,cAAc,GACf,MAAM,kBAAkB,CAAA;AAYzB,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;AAGvD,OAAO,EACL,aAAa,EACb,YAAY,EACZ,cAAc,EACd,sBAAsB,EACtB,gBAAgB,EAChB,iBAAiB,EACjB,QAAQ,GACT,MAAM,gBAAgB,CAAA;AAcvB,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AAEpE,OAAO,EACL,mBAAmB,EACnB,eAAe,EACf,SAAS,EACT,oBAAoB,GACrB,MAAM,kBAAkB,CAAA"}
@@ -1,18 +1,33 @@
1
1
  import type { McpToolDefinition } from '@forumone/throughline-plugin-contract';
2
2
  import { type PayloadMcpTool, type ToPayloadMcpToolOptions } from './payload-mcp.js';
3
+ /** What `plugin-mcp` needs about a tool while the config is being built. */
4
+ export interface McpToolDescriptor {
5
+ name: string;
6
+ description: string;
7
+ }
3
8
  export interface McpToolCollector {
4
9
  /**
5
- * The array to hand `mcpPlugin`. Empty until the plugins initialise, and the
6
- * same array afterwards do not copy or spread it at config time, or the
7
- * tools will be added to something nobody reads.
10
+ * The array to hand `mcpPlugin`. Filled by `declare` at config time and
11
+ * completed by `add` at `onInit` and the same array throughout, so do not
12
+ * copy or spread it, or the tools will be added to something nobody reads.
8
13
  */
9
14
  readonly tools: PayloadMcpTool[];
10
- /** Called by a plugin at `onInit`, once it can build its tools. */
15
+ /**
16
+ * Called by a plugin as the config is built, with its tools' names and
17
+ * descriptions. This is what `plugin-mcp` turns into per-key checkboxes.
18
+ */
19
+ declare(descriptors: readonly McpToolDescriptor[], options?: DeclareToolsOptions): void;
20
+ /** Called by a plugin at `onInit`, once it can build its handlers. */
11
21
  add(tools: McpToolDefinition[], options?: AddToolsOptions): void;
12
- /** Which servers have contributed, in the order they initialised. */
22
+ /** Which servers have declared, in the order they did. */
13
23
  readonly servers: string[];
24
+ /**
25
+ * Tools declared and never bound. Empty after every server's `onInit` has
26
+ * run; anything left is a server that declared a tool it does not build.
27
+ */
28
+ readonly unbound: string[];
14
29
  }
15
- export interface AddToolsOptions extends ToPayloadMcpToolOptions {
30
+ export interface DeclareToolsOptions {
16
31
  /**
17
32
  * Which server these came from — `'publishing'`, `'approvals'`. Used to name
18
33
  * both sides of a duplicate-name collision, which is the only thing that
@@ -20,6 +35,8 @@ export interface AddToolsOptions extends ToPayloadMcpToolOptions {
20
35
  */
21
36
  serverName?: string;
22
37
  }
38
+ export interface AddToolsOptions extends ToPayloadMcpToolOptions, DeclareToolsOptions {
39
+ }
23
40
  export type CreateMcpToolCollectorOptions = ToPayloadMcpToolOptions;
24
41
  /**
25
42
  * Somewhere for the plugins to put their tools, that the host can pass to
@@ -1 +1 @@
1
- {"version":3,"file":"collector.d.ts","sourceRoot":"","sources":["../../src/mcp/collector.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAA;AAC9E,OAAO,EAAqB,KAAK,cAAc,EAAE,KAAK,uBAAuB,EAAE,MAAM,kBAAkB,CAAA;AA6BvG,MAAM,WAAW,gBAAgB;IAC/B;;;;OAIG;IACH,QAAQ,CAAC,KAAK,EAAE,cAAc,EAAE,CAAA;IAChC,mEAAmE;IACnE,GAAG,CAAC,KAAK,EAAE,iBAAiB,EAAE,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,IAAI,CAAA;IAChE,qEAAqE;IACrE,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,CAAA;CAC3B;AAED,MAAM,WAAW,eAAgB,SAAQ,uBAAuB;IAC9D;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAED,MAAM,MAAM,6BAA6B,GAAG,uBAAuB,CAAA;AAEnE;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,GAAE,6BAAkC,GAC1C,gBAAgB,CA2BlB"}
1
+ {"version":3,"file":"collector.d.ts","sourceRoot":"","sources":["../../src/mcp/collector.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAA;AAC9E,OAAO,EAAqB,KAAK,cAAc,EAAE,KAAK,uBAAuB,EAAE,MAAM,kBAAkB,CAAA;AA4CvG,4EAA4E;AAC5E,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;CACpB;AAED,MAAM,WAAW,gBAAgB;IAC/B;;;;OAIG;IACH,QAAQ,CAAC,KAAK,EAAE,cAAc,EAAE,CAAA;IAChC;;;OAGG;IACH,OAAO,CAAC,WAAW,EAAE,SAAS,iBAAiB,EAAE,EAAE,OAAO,CAAC,EAAE,mBAAmB,GAAG,IAAI,CAAA;IACvF,sEAAsE;IACtE,GAAG,CAAC,KAAK,EAAE,iBAAiB,EAAE,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,IAAI,CAAA;IAChE,0DAA0D;IAC1D,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,CAAA;IAC1B;;;OAGG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,CAAA;CAC3B;AAED,MAAM,WAAW,mBAAmB;IAClC;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAED,MAAM,WAAW,eAAgB,SAAQ,uBAAuB,EAAE,mBAAmB;CAAG;AAExF,MAAM,MAAM,6BAA6B,GAAG,uBAAuB,CAAA;AAEnE;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,GAAE,6BAAkC,GAC1C,gBAAgB,CA+ElB"}
@@ -11,24 +11,67 @@ import { toPayloadMcpTools } from './payload-mcp.js';
11
11
  export function createMcpToolCollector(options = {}) {
12
12
  const tools = [];
13
13
  const servers = [];
14
- const byName = new Map();
14
+ const declaredBy = new Map();
15
+ const slots = new Map();
16
+ const bound = new Set();
15
17
  return {
16
18
  tools,
17
19
  servers,
18
- add(incoming, addOptions = {}) {
19
- const { serverName = 'an unnamed server', ...toolOptions } = addOptions;
20
- for (const tool of incoming) {
21
- const existing = byName.get(tool.name);
20
+ get unbound() {
21
+ return [...declaredBy.keys()].filter(name => !bound.has(name));
22
+ },
23
+ declare(descriptors, declareOptions = {}) {
24
+ const { serverName = 'an unnamed server' } = declareOptions;
25
+ for (const descriptor of descriptors) {
26
+ const existing = declaredBy.get(descriptor.name);
22
27
  if (existing !== undefined) {
23
- throw new Error(`Two MCP tools are called "${tool.name}" — one from ${existing}, one from ` +
28
+ throw new Error(`Two MCP tools are called "${descriptor.name}" — one from ${existing}, one from ` +
24
29
  `${serverName}. Under a single MCP server a tool name is a namespace, and a client ` +
25
30
  `offered both gets whichever registered last. Rename one.`);
26
31
  }
27
- byName.set(tool.name, serverName);
32
+ declaredBy.set(descriptor.name, serverName);
33
+ /*
34
+ A slot, not a tool. `name` and `description` are everything the plugin
35
+ reads now; `parameters` and `handler` arrive at `onInit`, on this same
36
+ object, because the array identity is what the host handed over.
37
+ */
38
+ const slot = {
39
+ name: descriptor.name,
40
+ description: descriptor.description,
41
+ parameters: {},
42
+ handler: () => {
43
+ throw new Error(`MCP tool "${descriptor.name}" was declared by ${serverName} and never bound. ` +
44
+ `A server declares its tools as the config is built and binds their handlers at ` +
45
+ `onInit; this one did not reach the second step, so the tool is advertised and ` +
46
+ `cannot run.`);
47
+ },
48
+ };
49
+ slots.set(descriptor.name, slot);
50
+ tools.push(slot);
28
51
  }
29
- tools.push(...toPayloadMcpTools(incoming, { ...options, ...toolOptions }));
30
52
  servers.push(serverName);
31
53
  },
54
+ add(incoming, addOptions = {}) {
55
+ const { serverName = 'an unnamed server', ...toolOptions } = addOptions;
56
+ for (const tool of toPayloadMcpTools(incoming, { ...options, ...toolOptions })) {
57
+ const slot = slots.get(tool.name);
58
+ if (!slot) {
59
+ throw new Error(`${serverName} built an MCP tool called "${tool.name}" that it never declared. ` +
60
+ `Add it to that package's tool descriptors: a tool the collector does not know ` +
61
+ `about while the config is built gets no per-key checkbox, and \`plugin-mcp\` ` +
62
+ `then denies it to every key with no error anywhere.`);
63
+ }
64
+ /*
65
+ Mutated rather than replaced. `mcpPlugin` was handed this array at config
66
+ time and reads it per request; swapping the element would leave the
67
+ checkbox pointing at an object nobody serves.
68
+ */
69
+ slot.description = tool.description;
70
+ slot.parameters = tool.parameters;
71
+ slot.handler = tool.handler;
72
+ bound.add(tool.name);
73
+ }
74
+ },
32
75
  };
33
76
  }
34
77
  //# sourceMappingURL=collector.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"collector.js","sourceRoot":"","sources":["../../src/mcp/collector.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAqD,MAAM,kBAAkB,CAAA;AAqDvG;;;;;;;;GAQG;AACH,MAAM,UAAU,sBAAsB,CACpC,UAAyC,EAAE;IAE3C,MAAM,KAAK,GAAqB,EAAE,CAAA;IAClC,MAAM,OAAO,GAAa,EAAE,CAAA;IAC5B,MAAM,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAA;IAExC,OAAO;QACL,KAAK;QACL,OAAO;QACP,GAAG,CAAC,QAAQ,EAAE,UAAU,GAAG,EAAE;YAC3B,MAAM,EAAE,UAAU,GAAG,mBAAmB,EAAE,GAAG,WAAW,EAAE,GAAG,UAAU,CAAA;YAEvE,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;gBAC5B,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;gBACtC,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;oBAC3B,MAAM,IAAI,KAAK,CACb,6BAA6B,IAAI,CAAC,IAAI,gBAAgB,QAAQ,aAAa;wBACzE,GAAG,UAAU,uEAAuE;wBACpF,0DAA0D,CAC7D,CAAA;gBACH,CAAC;gBACD,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,CAAA;YACnC,CAAC;YAED,KAAK,CAAC,IAAI,CAAC,GAAG,iBAAiB,CAAC,QAAQ,EAAE,EAAE,GAAG,OAAO,EAAE,GAAG,WAAW,EAAE,CAAC,CAAC,CAAA;YAC1E,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;QAC1B,CAAC;KACF,CAAA;AACH,CAAC"}
1
+ {"version":3,"file":"collector.js","sourceRoot":"","sources":["../../src/mcp/collector.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,3 @@
1
- export { createMcpHandler } from './handler.js';
2
- export type { McpHandlerOptions } from './handler.js';
3
1
  export { McpMetaSchema, withMeta } from './meta.js';
4
2
  export type { McpMeta } from './meta.js';
5
3
  export { auditContext } from './audit-context.js';
@@ -7,6 +5,6 @@ export type { AuditContextFields } from './audit-context.js';
7
5
  export { toPayloadMcpTool, toPayloadMcpTools } from './payload-mcp.js';
8
6
  export type { PayloadMcpRequest, PayloadMcpTool, ToPayloadMcpToolOptions, } from './payload-mcp.js';
9
7
  export { createMcpToolCollector } from './collector.js';
10
- export type { AddToolsOptions, CreateMcpToolCollectorOptions, McpToolCollector, } from './collector.js';
8
+ export type { AddToolsOptions, CreateMcpToolCollectorOptions, DeclareToolsOptions, McpToolCollector, McpToolDescriptor, } from './collector.js';
11
9
  export { deniedEnvelope } from './envelope.js';
12
10
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/mcp/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AAC/C,YAAY,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAA;AAErD,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAA;AACnD,YAAY,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAExC,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACjD,YAAY,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAA;AAE5D,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAA;AACtE,YAAY,EACV,iBAAiB,EACjB,cAAc,EACd,uBAAuB,GACxB,MAAM,kBAAkB,CAAA;AAEzB,OAAO,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAA;AACvD,YAAY,EACV,eAAe,EACf,6BAA6B,EAC7B,gBAAgB,GACjB,MAAM,gBAAgB,CAAA;AAEvB,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/mcp/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAA;AACnD,YAAY,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAExC,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACjD,YAAY,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAA;AAE5D,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAA;AACtE,YAAY,EACV,iBAAiB,EACjB,cAAc,EACd,uBAAuB,GACxB,MAAM,kBAAkB,CAAA;AAEzB,OAAO,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAA;AACvD,YAAY,EACV,eAAe,EACf,6BAA6B,EAC7B,mBAAmB,EACnB,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,gBAAgB,CAAA;AAEvB,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA"}
package/dist/mcp/index.js CHANGED
@@ -1,4 +1,3 @@
1
- export { createMcpHandler } from './handler.js';
2
1
  export { McpMetaSchema, withMeta } from './meta.js';
3
2
  export { auditContext } from './audit-context.js';
4
3
  export { toPayloadMcpTool, toPayloadMcpTools } from './payload-mcp.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/mcp/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AAG/C,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAA;AAGnD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAGjD,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAA;AAOtE,OAAO,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAA;AAOvD,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/mcp/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAA;AAGnD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAGjD,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAA;AAOtE,OAAO,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAA;AASvD,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"payload-mcp.d.ts","sourceRoot":"","sources":["../../src/mcp/payload-mcp.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,KAAK,EAAE,MAAM,EAAkB,iBAAiB,EAAE,MAAM,uCAAuC,CAAA;AAsBtG,wEAAwE;AACxE,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,UAAU,EAAE,CAAC,CAAC,WAAW,CAAA;IACzB,OAAO,EAAE,CACP,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,GAAG,EAAE,iBAAiB,EACtB,KAAK,EAAE,OAAO,KACX,OAAO,CAAC;QAAE,OAAO,EAAE,KAAK,CAAC;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,CAAA;SAAE,CAAC,CAAA;KAAE,CAAC,CAAA;CACjE;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,iBAAiB;IAChC,IAAI,CAAC,EAAE;QAAE,EAAE,CAAC,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAC;QAAC,IAAI,CAAC,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI,CAAA;IAClG,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;CAC9B;AAED,MAAM,WAAW,uBAAuB;IACtC;;;;;;;OAOG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,iBAAiB,EACvB,OAAO,GAAE,uBAA4B,GACpC,cAAc,CAYhB;AAED,2CAA2C;AAC3C,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,iBAAiB,EAAE,EAC1B,OAAO,GAAE,uBAA4B,GACpC,cAAc,EAAE,CAElB"}
1
+ {"version":3,"file":"payload-mcp.d.ts","sourceRoot":"","sources":["../../src/mcp/payload-mcp.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,KAAK,EAAE,MAAM,EAAkB,iBAAiB,EAAE,MAAM,uCAAuC,CAAA;AAwBtG,wEAAwE;AACxE,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,UAAU,EAAE,CAAC,CAAC,WAAW,CAAA;IACzB,OAAO,EAAE,CACP,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,GAAG,EAAE,iBAAiB,EACtB,KAAK,EAAE,OAAO,KACX,OAAO,CAAC;QAAE,OAAO,EAAE,KAAK,CAAC;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,CAAA;SAAE,CAAC,CAAA;KAAE,CAAC,CAAA;CACjE;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,iBAAiB;IAChC,IAAI,CAAC,EAAE;QAAE,EAAE,CAAC,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAC;QAAC,IAAI,CAAC,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI,CAAA;IAClG,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;CAC9B;AAED,MAAM,WAAW,uBAAuB;IACtC;;;;;;;OAOG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,iBAAiB,EACvB,OAAO,GAAE,uBAA4B,GACpC,cAAc,CAYhB;AAED,2CAA2C;AAC3C,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,iBAAiB,EAAE,EAC1B,OAAO,GAAE,uBAA4B,GACpC,cAAc,EAAE,CAElB"}
@@ -1 +1 @@
1
- {"version":3,"file":"payload-mcp.js","sourceRoot":"","sources":["../../src/mcp/payload-mcp.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AA4DlD;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,gBAAgB,CAC9B,IAAuB,EACvB,UAAmC,EAAE;IAErC,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAE3B,OAAO;QACL,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,WAAW,EAAE,IAAI,CAAC,WAAW;QAC7B,UAAU,EAAE,KAAK;QACjB,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE;YAC3B,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,WAAW,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,CAAA;YAClE,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAA;QAC/E,CAAC;KACF,CAAA;AACH,CAAC;AAED,2CAA2C;AAC3C,MAAM,UAAU,iBAAiB,CAC/B,KAA0B,EAC1B,UAAmC,EAAE;IAErC,OAAO,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,gBAAgB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAA;AAC3D,CAAC;AAED,SAAS,OAAO,CAAC,IAAuB;IACtC,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW,CAAA;IAC/B,IAAI,MAAM,YAAY,CAAC,CAAC,SAAS;QAAE,OAAO,MAAM,CAAC,KAAsB,CAAA;IACvE,MAAM,IAAI,KAAK,CACb,SAAS,IAAI,CAAC,IAAI,2EAA2E;QAC3F,0FAA0F,CAC7F,CAAA;AACH,CAAC;AAED,SAAS,WAAW,CAAC,GAAsB,EAAE,OAAgC;IAC3E,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI;QACnB,CAAC,CAAC;YACE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC;YAC7B,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;YACnC,IAAI,EAAE,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;YACnD,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAE,GAAG,CAAC,IAAI,CAAC,KAAkB,CAAC,CAAC,CAAC,EAAE;YACxE,MAAM,EAAE,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAE,GAAG,CAAC,IAAI,CAAC,MAAmB,CAAC,CAAC,CAAC,EAAE;SAC5E;QACH,CAAC,CAAC,IAAI,CAAA;IAER,OAAO;QACL,IAAI;QACJ;;;;;UAKE;QACF,UAAU,EAAE,OAAO,CAAC,UAAU,IAAI,CAAC,GAAG,CAAC,UAAU,KAAK,KAAK,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC;QACjF,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,GAAG,CAAC,OAAO,EAAE,MAAM,IAAI,aAAa;KAC/D,CAAA;AACH,CAAC"}
1
+ {"version":3,"file":"payload-mcp.js","sourceRoot":"","sources":["../../src/mcp/payload-mcp.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AA8DlD;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,gBAAgB,CAC9B,IAAuB,EACvB,UAAmC,EAAE;IAErC,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAE3B,OAAO;QACL,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,WAAW,EAAE,IAAI,CAAC,WAAW;QAC7B,UAAU,EAAE,KAAK;QACjB,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE;YAC3B,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,WAAW,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,CAAA;YAClE,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAA;QAC/E,CAAC;KACF,CAAA;AACH,CAAC;AAED,2CAA2C;AAC3C,MAAM,UAAU,iBAAiB,CAC/B,KAA0B,EAC1B,UAAmC,EAAE;IAErC,OAAO,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,gBAAgB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAA;AAC3D,CAAC;AAED,SAAS,OAAO,CAAC,IAAuB;IACtC,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW,CAAA;IAC/B,IAAI,MAAM,YAAY,CAAC,CAAC,SAAS;QAAE,OAAO,MAAM,CAAC,KAAsB,CAAA;IACvE,MAAM,IAAI,KAAK,CACb,SAAS,IAAI,CAAC,IAAI,2EAA2E;QAC3F,0FAA0F,CAC7F,CAAA;AACH,CAAC;AAED,SAAS,WAAW,CAAC,GAAsB,EAAE,OAAgC;IAC3E,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI;QACnB,CAAC,CAAC;YACE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC;YAC7B,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;YACnC,IAAI,EAAE,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;YACnD,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAE,GAAG,CAAC,IAAI,CAAC,KAAkB,CAAC,CAAC,CAAC,EAAE;YACxE,MAAM,EAAE,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAE,GAAG,CAAC,IAAI,CAAC,MAAmB,CAAC,CAAC,CAAC,EAAE;SAC5E;QACH,CAAC,CAAC,IAAI,CAAA;IAER,OAAO;QACL,IAAI;QACJ;;;;;UAKE;QACF,UAAU,EAAE,OAAO,CAAC,UAAU,IAAI,CAAC,GAAG,CAAC,UAAU,KAAK,KAAK,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC;QACjF,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,GAAG,CAAC,OAAO,EAAE,MAAM,IAAI,aAAa;KAC/D,CAAA;AACH,CAAC"}
@@ -1,4 +1,4 @@
1
- import { sha256Hex } from '../auth/api-keys.js';
1
+ import { sha256Hex } from './sha256.js';
2
2
  /**
3
3
  * Fields that move without the content moving. Stripped at every level of
4
4
  * the document before hashing.
@@ -1 +1 @@
1
- {"version":3,"file":"content-hash.js","sourceRoot":"","sources":["../../src/utils/content-hash.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAA;AAE/C;;;;;;;;;;;;GAYG;AACH,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC,CAAC,WAAW,EAAE,WAAW,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,EAAE,YAAY,CAAC,CAAC,CAAA;AAWlG;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,QAAiC,EACjC,UAAsC,EAAE;IAExC,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,eAAe,CAAC,CAAA;IACzC,KAAK,MAAM,KAAK,IAAI,OAAO,CAAC,OAAO,IAAI,EAAE;QAAE,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;IAC9D,OAAO,SAAS,CAAC,eAAe,CAAC,SAAS,CAAC,QAAQ,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAC,CAAA;AACxE,CAAC;AAED;;;;;;;;;GASG;AACH,SAAS,SAAS,CAAC,KAAc,EAAE,QAAqB,EAAE,QAAQ,GAAG,KAAK;IACxE,IAAI,KAAK,YAAY,IAAI;QAAE,OAAO,KAAK,CAAC,WAAW,EAAE,CAAA;IACrD,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,SAAS,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAA;IACjF,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAA;IAE7D,MAAM,MAAM,GAA4B,EAAE,CAAA;IAC1C,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAgC,CAAC,EAAE,CAAC;QAC5E,IAAI,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,SAAQ;QAC/B,IAAI,QAAQ,IAAI,GAAG,KAAK,IAAI;YAAE,SAAQ;QACtC,uEAAuE;QACvE,wEAAwE;QACxE,0BAA0B;QAC1B,IAAI,KAAK,KAAK,SAAS;YAAE,SAAQ;QACjC,MAAM,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAA;IAC1C,CAAC;IACD,OAAO,MAAM,CAAA;AACf,CAAC;AAED;;;;;;;;GAQG;AACH,SAAS,eAAe,CAAC,KAAc;IACrC,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,IAAI,KAAK,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAA;IACpD,CAAC;IACD,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAChD,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,KAAgC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CACjF,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAC3B,CAAA;QACD,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,eAAe,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAA;IAC/F,CAAC;IACD,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,MAAM,CAAA;AACxC,CAAC"}
1
+ {"version":3,"file":"content-hash.js","sourceRoot":"","sources":["../../src/utils/content-hash.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAEvC;;;;;;;;;;;;GAYG;AACH,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC,CAAC,WAAW,EAAE,WAAW,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,EAAE,YAAY,CAAC,CAAC,CAAA;AAWlG;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,QAAiC,EACjC,UAAsC,EAAE;IAExC,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,eAAe,CAAC,CAAA;IACzC,KAAK,MAAM,KAAK,IAAI,OAAO,CAAC,OAAO,IAAI,EAAE;QAAE,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;IAC9D,OAAO,SAAS,CAAC,eAAe,CAAC,SAAS,CAAC,QAAQ,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAC,CAAA;AACxE,CAAC;AAED;;;;;;;;;GASG;AACH,SAAS,SAAS,CAAC,KAAc,EAAE,QAAqB,EAAE,QAAQ,GAAG,KAAK;IACxE,IAAI,KAAK,YAAY,IAAI;QAAE,OAAO,KAAK,CAAC,WAAW,EAAE,CAAA;IACrD,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,SAAS,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAA;IACjF,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAA;IAE7D,MAAM,MAAM,GAA4B,EAAE,CAAA;IAC1C,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAgC,CAAC,EAAE,CAAC;QAC5E,IAAI,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,SAAQ;QAC/B,IAAI,QAAQ,IAAI,GAAG,KAAK,IAAI;YAAE,SAAQ;QACtC,uEAAuE;QACvE,wEAAwE;QACxE,0BAA0B;QAC1B,IAAI,KAAK,KAAK,SAAS;YAAE,SAAQ;QACjC,MAAM,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAA;IAC1C,CAAC;IACD,OAAO,MAAM,CAAA;AACf,CAAC;AAED;;;;;;;;GAQG;AACH,SAAS,eAAe,CAAC,KAAc;IACrC,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,IAAI,KAAK,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAA;IACpD,CAAC;IACD,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAChD,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,KAAgC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CACjF,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAC3B,CAAA;QACD,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,eAAe,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAA;IAC/F,CAAC;IACD,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,MAAM,CAAA;AACxC,CAAC"}
@@ -1,4 +1,6 @@
1
1
  export { documentContentHash } from './content-hash.js';
2
2
  export type { DocumentContentHashOptions } from './content-hash.js';
3
+ export { sha256Hex } from './sha256.js';
3
4
  export { unwrapRelationshipId } from './relationships.js';
5
+ export { formatZodIssues } from './zod-issues.js';
4
6
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;AACvD,YAAY,EAAE,0BAA0B,EAAE,MAAM,mBAAmB,CAAA;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;AACvD,YAAY,EAAE,0BAA0B,EAAE,MAAM,mBAAmB,CAAA;AACnE,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AACvC,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAA;AACzD,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA"}
@@ -1,3 +1,5 @@
1
1
  export { documentContentHash } from './content-hash.js';
2
+ export { sha256Hex } from './sha256.js';
2
3
  export { unwrapRelationshipId } from './relationships.js';
4
+ export { formatZodIssues } from './zod-issues.js';
3
5
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;AAEvD,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;AAEvD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AACvC,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAA;AACzD,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Hashes a string with SHA-256 using the Web Crypto API; returns lowercase hex.
3
+ *
4
+ * Lived in `auth/api-keys.ts` while this package minted and stored its own MCP
5
+ * keys. Those are gone — `@payloadcms/plugin-mcp` owns key storage now — and
6
+ * `documentContentHash` is the remaining caller, so the function moved to sit
7
+ * beside it rather than being deleted with the collection it was written for.
8
+ */
9
+ export declare function sha256Hex(input: string): Promise<string>;
10
+ //# sourceMappingURL=sha256.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sha256.d.ts","sourceRoot":"","sources":["../../src/utils/sha256.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,wBAAsB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAM9D"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Hashes a string with SHA-256 using the Web Crypto API; returns lowercase hex.
3
+ *
4
+ * Lived in `auth/api-keys.ts` while this package minted and stored its own MCP
5
+ * keys. Those are gone — `@payloadcms/plugin-mcp` owns key storage now — and
6
+ * `documentContentHash` is the remaining caller, so the function moved to sit
7
+ * beside it rather than being deleted with the collection it was written for.
8
+ */
9
+ export async function sha256Hex(input) {
10
+ const data = new TextEncoder().encode(input);
11
+ const buffer = await crypto.subtle.digest('SHA-256', data);
12
+ return Array.from(new Uint8Array(buffer))
13
+ .map((b) => b.toString(16).padStart(2, '0'))
14
+ .join('');
15
+ }
16
+ //# sourceMappingURL=sha256.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sha256.js","sourceRoot":"","sources":["../../src/utils/sha256.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,KAAa;IAC3C,MAAM,IAAI,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;IAC5C,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,IAAI,CAAC,CAAA;IAC1D,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC;SACtC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;SAC3C,IAAI,CAAC,EAAE,CAAC,CAAA;AACb,CAAC"}
@@ -0,0 +1,19 @@
1
+ import type { z } from 'zod';
2
+ /**
3
+ * Zod's issues as an indented list, one per line.
4
+ *
5
+ * `componentsPlugin`'s options and a publishable collection's config formatted
6
+ * them identically, because the shape is what makes a config error readable:
7
+ * the path to the field, then what is wrong with it. Both plugins already
8
+ * depend on this package, so sharing costs nothing.
9
+ *
10
+ * `(root)` for an issue with no path — what a schema-level refinement produces,
11
+ * and what an empty `join('.')` would otherwise render as nothing at all.
12
+ *
13
+ * A third copy lives in `design-contract`'s loader and stays there. That
14
+ * package depends on `zod` and nothing else, which is what lets the scaffolder
15
+ * and a standalone design system consume it; trading that for four lines would
16
+ * pull the whole plugin surface behind it.
17
+ */
18
+ export declare function formatZodIssues(error: z.ZodError): string;
19
+ //# sourceMappingURL=zod-issues.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"zod-issues.d.ts","sourceRoot":"","sources":["../../src/utils/zod-issues.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAE5B;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,CAAC,CAAC,QAAQ,GAAG,MAAM,CAIzD"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Zod's issues as an indented list, one per line.
3
+ *
4
+ * `componentsPlugin`'s options and a publishable collection's config formatted
5
+ * them identically, because the shape is what makes a config error readable:
6
+ * the path to the field, then what is wrong with it. Both plugins already
7
+ * depend on this package, so sharing costs nothing.
8
+ *
9
+ * `(root)` for an issue with no path — what a schema-level refinement produces,
10
+ * and what an empty `join('.')` would otherwise render as nothing at all.
11
+ *
12
+ * A third copy lives in `design-contract`'s loader and stays there. That
13
+ * package depends on `zod` and nothing else, which is what lets the scaffolder
14
+ * and a standalone design system consume it; trading that for four lines would
15
+ * pull the whole plugin surface behind it.
16
+ */
17
+ export function formatZodIssues(error) {
18
+ return error.issues
19
+ .map((issue) => ` - ${issue.path.join('.') || '(root)'}: ${issue.message}`)
20
+ .join('\n');
21
+ }
22
+ //# sourceMappingURL=zod-issues.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"zod-issues.js","sourceRoot":"","sources":["../../src/utils/zod-issues.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,eAAe,CAAC,KAAiB;IAC/C,OAAO,KAAK,CAAC,MAAM;SAChB,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,QAAQ,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC;SAC3E,IAAI,CAAC,IAAI,CAAC,CAAA;AACf,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@forumone/throughline-core",
3
- "version": "0.6.0",
3
+ "version": "0.8.0",
4
4
  "description": "Core plumbing for Throughline: audit log, MCP authentication and handler, event taxonomy + Inngest client factory, logger, shared utilities.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -58,7 +58,7 @@
58
58
  "dependencies": {
59
59
  "zod": "^3.23.0",
60
60
  "zod-to-json-schema": "^3.25.2",
61
- "@forumone/throughline-plugin-contract": "0.3.0"
61
+ "@forumone/throughline-plugin-contract": "0.4.0"
62
62
  },
63
63
  "devDependencies": {
64
64
  "@types/node": "^20.17.0",
@@ -1,21 +0,0 @@
1
- import type { CollectionConfig } from 'payload';
2
- export interface ApiKeysCollectionOptions {
3
- /** Override the collection slug. Default: `'mcp-api-keys'`. */
4
- slug?: string;
5
- /** Slug of the users collection the key links to. Default: `'users'`. */
6
- usersSlug?: string;
7
- /** Allowed scope strings shown in the admin UI. */
8
- availableScopes?: string[];
9
- }
10
- export declare const DEFAULT_API_KEYS_SLUG = "mcp-api-keys";
11
- /**
12
- * Builds the API-keys collection config. Stores keys as SHA-256 hashes;
13
- * raw keys are surfaced one-time via the `keyDisplay` field on create
14
- * so the admin UI can show them to the operator.
15
- */
16
- export declare function createApiKeysCollection(options?: ApiKeysCollectionOptions): CollectionConfig;
17
- /** Generates a random API key prefixed with `tl_`. */
18
- export declare function generateApiKey(): string;
19
- /** Hashes a string with SHA-256 using the Web Crypto API; returns lowercase hex. */
20
- export declare function sha256Hex(input: string): Promise<string>;
21
- //# sourceMappingURL=api-keys.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"api-keys.d.ts","sourceRoot":"","sources":["../../src/auth/api-keys.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAU,gBAAgB,EAAE,MAAM,SAAS,CAAA;AAEvD,MAAM,WAAW,wBAAwB;IACvC,+DAA+D;IAC/D,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,yEAAyE;IACzE,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,mDAAmD;IACnD,eAAe,CAAC,EAAE,MAAM,EAAE,CAAA;CAC3B;AAED,eAAO,MAAM,qBAAqB,iBAAiB,CAAA;AAwBnD;;;;GAIG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,GAAE,wBAA6B,GACrC,gBAAgB,CAyElB;AAED,sDAAsD;AACtD,wBAAgB,cAAc,IAAI,MAAM,CAOvC;AAED,oFAAoF;AACpF,wBAAsB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAM9D"}
@@ -1,115 +0,0 @@
1
- export const DEFAULT_API_KEYS_SLUG = 'mcp-api-keys';
2
- const DEFAULT_SCOPES = [
3
- 'content.read',
4
- 'content.write',
5
- 'design.read',
6
- 'publishing.execute',
7
- 'approvals.request',
8
- 'approvals.decide',
9
- 'forms.manage',
10
- 'integrations.trigger',
11
- 'audit.read',
12
- ];
13
- /**
14
- * Returns true when the requesting user has the `admin` role. Used as the
15
- * default access check for the keys collection — keys grant capability,
16
- * so creating/reading them must be tightly scoped.
17
- */
18
- const adminOnly = ({ req }) => {
19
- const roles = req.user?.['roles'] ?? [];
20
- return roles.includes('admin');
21
- };
22
- /**
23
- * Builds the API-keys collection config. Stores keys as SHA-256 hashes;
24
- * raw keys are surfaced one-time via the `keyDisplay` field on create
25
- * so the admin UI can show them to the operator.
26
- */
27
- export function createApiKeysCollection(options = {}) {
28
- const slug = options.slug ?? DEFAULT_API_KEYS_SLUG;
29
- const usersSlug = options.usersSlug ?? 'users';
30
- const availableScopes = options.availableScopes ?? [...DEFAULT_SCOPES];
31
- return {
32
- slug,
33
- admin: {
34
- useAsTitle: 'name',
35
- defaultColumns: ['name', 'linkedUser', 'enabled', 'lastUsedAt'],
36
- description: 'API keys for MCP clients. Each key inherits the linked user\'s access control; keys are stored as SHA-256 hashes.',
37
- },
38
- access: {
39
- read: adminOnly,
40
- create: adminOnly,
41
- update: adminOnly,
42
- delete: adminOnly,
43
- },
44
- fields: [
45
- { name: 'name', type: 'text', required: true },
46
- {
47
- name: 'linkedUser',
48
- type: 'relationship',
49
- relationTo: usersSlug,
50
- required: true,
51
- admin: { description: 'The user whose access control this key inherits.' },
52
- },
53
- {
54
- name: 'scopes',
55
- type: 'select',
56
- hasMany: true,
57
- required: true,
58
- options: availableScopes.map((value) => ({ label: value, value })),
59
- },
60
- { name: 'enabled', type: 'checkbox', defaultValue: true, required: true },
61
- {
62
- name: 'keyHash',
63
- type: 'text',
64
- required: true,
65
- admin: {
66
- readOnly: true,
67
- description: 'SHA-256 hash of the key. The raw key is never stored.',
68
- },
69
- },
70
- {
71
- name: 'keyDisplay',
72
- type: 'text',
73
- admin: {
74
- readOnly: true,
75
- description: 'First and last 4 characters of the key for identification.',
76
- },
77
- },
78
- { name: 'expiresAt', type: 'date' },
79
- { name: 'lastUsedAt', type: 'date', admin: { readOnly: true } },
80
- ],
81
- hooks: {
82
- beforeChange: [
83
- async ({ data, operation }) => {
84
- if (operation !== 'create')
85
- return data;
86
- if (data['keyHash'])
87
- return data;
88
- const rawKey = generateApiKey();
89
- data['keyHash'] = await sha256Hex(rawKey);
90
- data['keyDisplay'] = `${rawKey.slice(0, 8)}...${rawKey.slice(-4)}`;
91
- data.__rawKey = rawKey;
92
- return data;
93
- },
94
- ],
95
- },
96
- };
97
- }
98
- /** Generates a random API key prefixed with `tl_`. */
99
- export function generateApiKey() {
100
- const bytes = new Uint8Array(32);
101
- crypto.getRandomValues(bytes);
102
- const hex = Array.from(bytes)
103
- .map((b) => b.toString(16).padStart(2, '0'))
104
- .join('');
105
- return `tl_${hex}`;
106
- }
107
- /** Hashes a string with SHA-256 using the Web Crypto API; returns lowercase hex. */
108
- export async function sha256Hex(input) {
109
- const data = new TextEncoder().encode(input);
110
- const buffer = await crypto.subtle.digest('SHA-256', data);
111
- return Array.from(new Uint8Array(buffer))
112
- .map((b) => b.toString(16).padStart(2, '0'))
113
- .join('');
114
- }
115
- //# sourceMappingURL=api-keys.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"api-keys.js","sourceRoot":"","sources":["../../src/auth/api-keys.ts"],"names":[],"mappings":"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"}
@@ -1,19 +0,0 @@
1
- import type { Payload } from 'payload';
2
- import type { McpAuthenticator } from '@forumone/throughline-plugin-contract';
3
- export interface BearerTokenAuthenticatorOptions {
4
- payload: Payload;
5
- /** Slug for the API-keys collection. Default: `'mcp-api-keys'`. */
6
- collectionSlug?: string;
7
- }
8
- /**
9
- * Authenticates incoming MCP requests by looking up the bearer token's hash
10
- * against the API-keys collection. Returns the linked user plus key metadata
11
- * on success, `null` on any failure (no token, unknown token, disabled key,
12
- * key without linked user, expired key).
13
- *
14
- * The key's `scopes` come back with it. They are what the handler holds a
15
- * scoped tool against; until they did, the field was a label on a key that
16
- * could do everything its linked user could.
17
- */
18
- export declare function createBearerTokenAuthenticator(options: BearerTokenAuthenticatorOptions): McpAuthenticator;
19
- //# sourceMappingURL=authenticator.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"authenticator.d.ts","sourceRoot":"","sources":["../../src/auth/authenticator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AACtC,OAAO,KAAK,EAGV,gBAAgB,EACjB,MAAM,uCAAuC,CAAA;AAG9C,MAAM,WAAW,+BAA+B;IAC9C,OAAO,EAAE,OAAO,CAAA;IAChB,mEAAmE;IACnE,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB;AAED;;;;;;;;;GASG;AACH,wBAAgB,8BAA8B,CAC5C,OAAO,EAAE,+BAA+B,GACvC,gBAAgB,CAyClB"}
@@ -1,74 +0,0 @@
1
- import { DEFAULT_API_KEYS_SLUG, sha256Hex } from './api-keys.js';
2
- /**
3
- * Authenticates incoming MCP requests by looking up the bearer token's hash
4
- * against the API-keys collection. Returns the linked user plus key metadata
5
- * on success, `null` on any failure (no token, unknown token, disabled key,
6
- * key without linked user, expired key).
7
- *
8
- * The key's `scopes` come back with it. They are what the handler holds a
9
- * scoped tool against; until they did, the field was a label on a key that
10
- * could do everything its linked user could.
11
- */
12
- export function createBearerTokenAuthenticator(options) {
13
- const { payload, collectionSlug = DEFAULT_API_KEYS_SLUG } = options;
14
- return {
15
- async authenticate(request) {
16
- const token = extractBearerToken(request);
17
- if (!token)
18
- return null;
19
- const hash = await sha256Hex(token);
20
- const result = await payload.find({
21
- collection: collectionSlug,
22
- where: {
23
- and: [{ keyHash: { equals: hash } }, { enabled: { equals: true } }],
24
- },
25
- limit: 1,
26
- depth: 1,
27
- });
28
- const apiKey = result.docs[0];
29
- if (!apiKey)
30
- return null;
31
- const expiresAt = apiKey['expiresAt'];
32
- if (typeof expiresAt === 'string' && Date.parse(expiresAt) <= Date.now()) {
33
- return null;
34
- }
35
- const linkedUser = apiKey['linkedUser'];
36
- if (!linkedUser || typeof linkedUser !== 'object')
37
- return null;
38
- const user = toAuthenticatedUser(linkedUser);
39
- if (!user)
40
- return null;
41
- return {
42
- user,
43
- apiKeyName: String(apiKey['name'] ?? ''),
44
- apiKeyId: String(apiKey['id']),
45
- scopes: toScopes(apiKey['scopes']),
46
- };
47
- },
48
- };
49
- }
50
- function extractBearerToken(request) {
51
- const header = request.headers.get('authorization');
52
- if (!header)
53
- return null;
54
- const match = /^Bearer\s+(.+)$/i.exec(header);
55
- return match?.[1]?.trim() || null;
56
- }
57
- function toAuthenticatedUser(raw) {
58
- if (raw['id'] === undefined || raw['email'] === undefined)
59
- return null;
60
- return {
61
- id: String(raw['id']),
62
- email: String(raw['email']),
63
- name: String(raw['name'] ?? raw['email']),
64
- roles: raw['roles'] ?? [],
65
- groups: raw['groups'] ?? [],
66
- };
67
- }
68
- /** The stored `scopes` as a string list, whatever shape the row came back in. */
69
- function toScopes(raw) {
70
- if (!Array.isArray(raw))
71
- return [];
72
- return raw.filter((scope) => typeof scope === 'string');
73
- }
74
- //# sourceMappingURL=authenticator.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"authenticator.js","sourceRoot":"","sources":["../../src/auth/authenticator.ts"],"names":[],"mappings":"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"}
@@ -1,5 +0,0 @@
1
- export { createBearerTokenAuthenticator } from './authenticator.js';
2
- export type { BearerTokenAuthenticatorOptions } from './authenticator.js';
3
- export { createApiKeysCollection, generateApiKey, sha256Hex, DEFAULT_API_KEYS_SLUG, } from './api-keys.js';
4
- export type { ApiKeysCollectionOptions } from './api-keys.js';
5
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,8BAA8B,EAAE,MAAM,oBAAoB,CAAA;AACnE,YAAY,EAAE,+BAA+B,EAAE,MAAM,oBAAoB,CAAA;AAEzE,OAAO,EACL,uBAAuB,EACvB,cAAc,EACd,SAAS,EACT,qBAAqB,GACtB,MAAM,eAAe,CAAA;AACtB,YAAY,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAA"}
@@ -1,3 +0,0 @@
1
- export { createBearerTokenAuthenticator } from './authenticator.js';
2
- export { createApiKeysCollection, generateApiKey, sha256Hex, DEFAULT_API_KEYS_SLUG, } from './api-keys.js';
3
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,8BAA8B,EAAE,MAAM,oBAAoB,CAAA;AAGnE,OAAO,EACL,uBAAuB,EACvB,cAAc,EACd,SAAS,EACT,qBAAqB,GACtB,MAAM,eAAe,CAAA"}
@@ -1,20 +0,0 @@
1
- import type { Payload } from 'payload';
2
- import type { Logger, McpAuthenticator, McpToolDefinition } from '@forumone/throughline-plugin-contract';
3
- export interface McpHandlerOptions {
4
- payload: Payload;
5
- /** Server identifier surfaced in logs (e.g. `'publishing'`). */
6
- serverName: string;
7
- /** Tools the server exposes via `tools/list` and `tools/call`. */
8
- tools: McpToolDefinition[];
9
- /** Optional override; defaults to a bearer-token authenticator. */
10
- authenticator?: McpAuthenticator;
11
- /** Optional logger; defaults to the framework's console logger. */
12
- logger?: Logger;
13
- }
14
- /**
15
- * Returns an HTTP handler that implements the Model Context Protocol's
16
- * JSON-RPC subset over a single POST endpoint. Handles authentication,
17
- * tool listing, tool dispatch, and error formatting.
18
- */
19
- export declare function createMcpHandler(options: McpHandlerOptions): (request: Request) => Promise<Response>;
20
- //# sourceMappingURL=handler.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../src/mcp/handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AAGtC,OAAO,KAAK,EACV,MAAM,EACN,gBAAgB,EAChB,iBAAiB,EAClB,MAAM,uCAAuC,CAAA;AAI9C,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,OAAO,CAAA;IAChB,gEAAgE;IAChE,UAAU,EAAE,MAAM,CAAA;IAClB,kEAAkE;IAClE,KAAK,EAAE,iBAAiB,EAAE,CAAA;IAC1B,mEAAmE;IACnE,aAAa,CAAC,EAAE,gBAAgB,CAAA;IAChC,mEAAmE;IACnE,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,iBAAiB,GAAG,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,CAsGpG"}
@@ -1,132 +0,0 @@
1
- import { z } from 'zod';
2
- import { zodToJsonSchema } from 'zod-to-json-schema';
3
- import { createBearerTokenAuthenticator } from '../auth/index.js';
4
- import { createNamedLogger, defaultLogger } from '../logger/index.js';
5
- /**
6
- * Returns an HTTP handler that implements the Model Context Protocol's
7
- * JSON-RPC subset over a single POST endpoint. Handles authentication,
8
- * tool listing, tool dispatch, and error formatting.
9
- */
10
- export function createMcpHandler(options) {
11
- const authenticator = options.authenticator ?? createBearerTokenAuthenticator({ payload: options.payload });
12
- const toolsByName = new Map(options.tools.map((t) => [t.name, t]));
13
- const logger = options.logger ?? defaultLogger;
14
- const tag = `[${options.serverName}]`;
15
- // `createNamedLogger` is forty lines away in this same package and does
16
- // exactly this. The handler used to rebuild it inline.
17
- const toolLogger = createNamedLogger(options.serverName, logger);
18
- return async function handleMcp(request) {
19
- const auth = await authenticator.authenticate(request);
20
- if (!auth)
21
- return jsonResponse({ error: 'Unauthorized' }, 401);
22
- let body;
23
- try {
24
- body = await request.json();
25
- }
26
- catch {
27
- return jsonRpcError(null, JSON_RPC_PARSE_ERROR, 'Parse error');
28
- }
29
- const parsed = JsonRpcRequestSchema.safeParse(body);
30
- if (!parsed.success)
31
- return jsonRpcError(null, JSON_RPC_INVALID_REQUEST, 'Invalid request');
32
- const rpc = parsed.data;
33
- const id = rpc.id ?? null;
34
- try {
35
- if (rpc.method === 'tools/list') {
36
- /*
37
- Only what this key may actually call.
38
-
39
- An agent shown a tool it will be refused for will try it, be refused,
40
- and try something else — and the transcript reads like the tool is
41
- broken rather than like the key is narrow. Hiding it is the difference
42
- between "you cannot publish" and "publishing is unavailable", and only
43
- one of those is true.
44
- */
45
- return jsonRpcResult(id, {
46
- tools: options.tools.filter(permits(auth.scopes)).map((tool) => ({
47
- name: tool.name,
48
- description: tool.description,
49
- inputSchema: zodToJsonSchema(tool.inputSchema, { target: 'jsonSchema7' }),
50
- })),
51
- });
52
- }
53
- if (rpc.method === 'tools/call') {
54
- const params = ToolCallParamsSchema.safeParse(rpc.params);
55
- if (!params.success) {
56
- return jsonRpcError(id, JSON_RPC_INVALID_PARAMS, 'Invalid params');
57
- }
58
- const tool = toolsByName.get(params.data.name);
59
- if (!tool) {
60
- return jsonRpcError(id, JSON_RPC_METHOD_NOT_FOUND, `Unknown tool: ${params.data.name}`);
61
- }
62
- // Named rather than merely refused: a caller that cannot see why it was
63
- // turned away has no way to ask for the right key.
64
- if (!permits(auth.scopes)(tool)) {
65
- logger.warn(`${tag} refused ${tool.name}: key "${auth.apiKeyName}" lacks scope ${String(tool.requiredScope)}`);
66
- return jsonRpcError(id, JSON_RPC_INVALID_REQUEST, `This API key does not carry the "${String(tool.requiredScope)}" scope, which ${tool.name} requires.`);
67
- }
68
- const inputResult = tool.inputSchema.safeParse(params.data.arguments ?? {});
69
- if (!inputResult.success) {
70
- return jsonRpcError(id, JSON_RPC_INVALID_PARAMS, `Invalid arguments: ${inputResult.error.message}`);
71
- }
72
- const result = await tool.handler(inputResult.data, {
73
- user: auth.user,
74
- apiKeyName: auth.apiKeyName,
75
- logger: toolLogger,
76
- });
77
- return jsonRpcResult(id, {
78
- content: [
79
- {
80
- type: 'text',
81
- text: typeof result === 'string' ? result : JSON.stringify(result),
82
- },
83
- ],
84
- });
85
- }
86
- return jsonRpcError(id, JSON_RPC_METHOD_NOT_FOUND, `Method not found: ${rpc.method}`);
87
- }
88
- catch (error) {
89
- logger.error(`${tag} MCP handler error`, { error: String(error), method: rpc.method });
90
- return jsonRpcError(id, JSON_RPC_INTERNAL_ERROR, 'Internal error');
91
- }
92
- };
93
- }
94
- const JSON_RPC_PARSE_ERROR = -32700;
95
- const JSON_RPC_INVALID_REQUEST = -32600;
96
- const JSON_RPC_METHOD_NOT_FOUND = -32601;
97
- const JSON_RPC_INVALID_PARAMS = -32602;
98
- const JSON_RPC_INTERNAL_ERROR = -32603;
99
- const JsonRpcRequestSchema = z.object({
100
- jsonrpc: z.literal('2.0'),
101
- id: z.union([z.string(), z.number(), z.null()]).optional(),
102
- method: z.string(),
103
- params: z.unknown().optional(),
104
- });
105
- const ToolCallParamsSchema = z.object({
106
- name: z.string(),
107
- arguments: z.record(z.string(), z.unknown()).optional(),
108
- });
109
- function jsonResponse(body, status = 200) {
110
- return new Response(JSON.stringify(body), {
111
- status,
112
- headers: { 'content-type': 'application/json' },
113
- });
114
- }
115
- function jsonRpcResult(id, result) {
116
- return jsonResponse({ jsonrpc: '2.0', id, result });
117
- }
118
- function jsonRpcError(id, code, message) {
119
- return jsonResponse({ jsonrpc: '2.0', id, error: { code, message } });
120
- }
121
- /**
122
- * Whether a key holding `scopes` may call a given tool.
123
- *
124
- * A tool declaring no `requiredScope` is callable by any authenticated key —
125
- * the right default for a read. A tool that declares one needs it named on the
126
- * key, and a key carrying no scopes at all passes nothing.
127
- */
128
- function permits(scopes) {
129
- const held = new Set(scopes ?? []);
130
- return (tool) => tool.requiredScope === undefined || held.has(tool.requiredScope);
131
- }
132
- //# sourceMappingURL=handler.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"handler.js","sourceRoot":"","sources":["../../src/mcp/handler.ts"],"names":[],"mappings":"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"}