@forumone/throughline-core 0.8.1 → 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/CHANGELOG.md CHANGED
@@ -1,5 +1,63 @@
1
1
  # @forumone/throughline-core
2
2
 
3
+ ## 0.9.0
4
+
5
+ ### Minor Changes
6
+
7
+ - debfcd2: `system.error` now has a writer. Every MCP tool handler the suite serves is
8
+ wrapped, so a tool that throws records one `system.error` audit row — the
9
+ server, the tool, the caller, the caller's `_meta`, and the error's message —
10
+ before the throw propagates to the MCP client as it did before.
11
+
12
+ The row carries no stack and no arguments: `error_message` is readable by every
13
+ admin and editor, a stack names file paths, and a tool's input can hold a draft
14
+ body or a form submission. A failure inside the recording is logged and
15
+ swallowed, so this wrapper can never replace a tool's real error with its own.
16
+
17
+ `mcpServer` is resolved through a map rather than from the collector's own
18
+ server name, because the two vocabularies disagree: the components server
19
+ declares itself `components` and the audit enum's value is `component`. A
20
+ server that passes an audit writer and has no name in that map is now a
21
+ boot-time refusal instead of a row Payload silently rejects. New export:
22
+ `auditServerFor`.
23
+
24
+ Each of the six servers passes its audit writer to `collector.add`, alongside
25
+ the logger it already passed. A host wiring a tool by hand passes none and gets
26
+ the previous behaviour.
27
+
28
+ ## 0.8.2
29
+
30
+ ### Patch Changes
31
+
32
+ - 262768a: The five publishing MCP tools now refuse an unauthenticated call and run their
33
+ reads and writes as the caller.
34
+
35
+ `publish`, `unpublish`, `rollback`, `schedulePublish` and `getPublishStatus`
36
+ built their actor without `enforceAccessAs`, which is the only thing that makes
37
+ the service pass `{ user, overrideAccess: false }` to Payload. So every one of
38
+ them ran at the Local API default of `overrideAccess: true` — publish,
39
+ unpublish, roll back or schedule any document in any collection with no
40
+ authorization check. `rollback` called `restoreVersion` with no user and no
41
+ override flag at all.
42
+
43
+ `tools/actor.ts` refuses when there is no identity and hands the caller to the
44
+ service as the principal to enforce against. Deliberately not a role gate: the
45
+ admin HTTP path already requires a user, sets `enforceAccessAs`, and lets the
46
+ collection's own `update` rule decide. The MCP path now participates in that
47
+ rather than carrying a second policy.
48
+
49
+ **Behavioural change for consumers.** A tool call arriving with no `ctx.user`
50
+ now returns `{ error: 'Must be authenticated…' }` instead of performing the
51
+ operation. In practice that is every `Bearer`-authenticated MCP call, because
52
+ `@payloadcms/plugin-mcp` does not assign `req.user` — which is why the audit,
53
+ integrations and approvals servers already denied and these five did not.
54
+
55
+ `@forumone/throughline-core`'s README claimed `requiredScope` is enforced —
56
+ hidden from `tools/list` and refused unless granted. It was, by an `auth.ts`
57
+ that "one MCP transport, not seven" (#80) removed along with the six
58
+ per-server endpoints. The declarations survived; the enforcement did not. The
59
+ README now says so, and says what gates a tool instead.
60
+
3
61
  ## 0.8.1
4
62
 
5
63
  ### Patch Changes
package/README.md CHANGED
@@ -104,9 +104,34 @@ const publishTool: McpToolDefinition = {
104
104
  }
105
105
  ```
106
106
 
107
- A tool that declares no `requiredScope` is callable by any authenticated key, which is the right default for a read. A tool that declares one is **hidden from `tools/list`** and refused on a direct call unless the key names that scope — hidden as well as refused, because an agent shown a tool it will be turned away from will try it, fail, and report the tool as broken when what is narrow is the key.
108
-
109
- A key carrying no scopes at all passes nothing scoped. Absent is read as none, not as everything.
107
+ > **Nothing enforces this today.** The paragraphs below describe how
108
+ > `requiredScope` behaved when each server mounted its own `/api/<server>/mcp`
109
+ > endpoint behind a hand-written JSON-RPC handler. That handler — and the
110
+ > `auth.ts` that held callers to their scopes — were removed by "one MCP
111
+ > transport, not seven" (#80), which consolidated every server onto Payload's
112
+ > `/api/mcp`. The scope declarations survived the refactor; the enforcement did
113
+ > not, and this section was not updated to say so. Audit 04 F-02.
114
+ >
115
+ > **What gates a tool now** is the per-key checkbox `@payloadcms/plugin-mcp`
116
+ > generates, one per tool name. Two consequences worth knowing before relying
117
+ > on either: all 27 of them **default to `true`**
118
+ > (`createApiKeysCollection.js:4-15`), and a checkbox list cannot express
119
+ > "writes off until granted, reads on" the way a scope can.
120
+ >
121
+ > The declarations are kept because they are the tool → scope mapping a
122
+ > scope-aware default would be built from — see the note on `requiredScope` in
123
+ > `@forumone/throughline-plugin-contract`, which states the same thing at the
124
+ > type. Reinstating enforcement means putting it on the surviving transport.
125
+
126
+ Historically, and as the intended design: a tool that declares no
127
+ `requiredScope` is callable by any authenticated key, which is the right
128
+ default for a read. A tool that declares one was **hidden from `tools/list`**
129
+ and refused on a direct call unless the key named that scope — hidden as well
130
+ as refused, because an agent shown a tool it will be turned away from will try
131
+ it, fail, and report the tool as broken when what is narrow is the key.
132
+
133
+ A key carrying no scopes at all passed nothing scoped. Absent was read as none,
134
+ not as everything.
110
135
 
111
136
  The consequential tools in this suite and the scopes they require:
112
137
 
@@ -0,0 +1,13 @@
1
+ import { type AuditMcpServer } from '../audit/types.js';
2
+ /**
3
+ * The audit log's name for a collector server name, or `undefined` if there
4
+ * isn't one.
5
+ *
6
+ * `undefined` rather than a fallback: a row attributed to the wrong server is
7
+ * worse than a boot that stops and says which two lists to reconcile. The
8
+ * caller is `collector.add`, which throws — see `mcpServerRefusal`.
9
+ */
10
+ export declare function auditServerFor(serverName: string): AuditMcpServer | undefined;
11
+ /** The message `collector.add` throws with when a server has no audit name. */
12
+ export declare function mcpServerRefusal(serverName: string): string;
13
+ //# sourceMappingURL=audit-server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit-server.d.ts","sourceRoot":"","sources":["../../src/mcp/audit-server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,KAAK,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAwC1E;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS,CAW7E;AAED,+EAA+E;AAC/E,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAS3D"}
@@ -0,0 +1,68 @@
1
+ import { AUDIT_MCP_SERVERS } from '../audit/types.js';
2
+ /*
3
+ The collector's server names are not the audit log's server names, and one pair
4
+ disagrees.
5
+
6
+ `collector.ts` takes a `serverName` for its error messages — the string a
7
+ plugin passes to `declare` and `add`. The audit collection takes an
8
+ `mcpServer`, a Postgres enum (`enum_audit_events_mcp_server`). Six of the seven
9
+ names line up. The seventh does not:
10
+
11
+ collector audit enum
12
+ approvals approvals
13
+ audit audit
14
+ components -> component <- singular
15
+ forms forms
16
+ integrations integrations
17
+ publishing publishing
18
+ - payload
19
+
20
+ So `mcpServer: serverName as AuditMcpServer` compiles and is wrong for the
21
+ components server. It would be wrong *silently*: Payload rejects a select value
22
+ outside the options, `createAuditWriter` swallows every write failure by design
23
+ — "never let audit failures break the original action" — and the result is one
24
+ server whose rows are missing from the log with a `logger.error` nobody reads.
25
+
26
+ Hence a map, and hence `auditServerFor` refusing rather than guessing. The
27
+ refusal happens where the map is consulted, which is `add` — config time, once,
28
+ at boot — rather than inside a request.
29
+ */
30
+ const AUDIT_SERVER_BY_COLLECTOR_NAME = {
31
+ approvals: 'approvals',
32
+ audit: 'audit',
33
+ components: 'component',
34
+ forms: 'forms',
35
+ integrations: 'integrations',
36
+ payload: 'payload',
37
+ publishing: 'publishing',
38
+ };
39
+ /**
40
+ * The audit log's name for a collector server name, or `undefined` if there
41
+ * isn't one.
42
+ *
43
+ * `undefined` rather than a fallback: a row attributed to the wrong server is
44
+ * worse than a boot that stops and says which two lists to reconcile. The
45
+ * caller is `collector.add`, which throws — see `mcpServerRefusal`.
46
+ */
47
+ export function auditServerFor(serverName) {
48
+ /*
49
+ `hasOwn` rather than a bare index, because a bare index into an object
50
+ literal answers for `constructor` and `toString` — and the return type says
51
+ `AuditMcpServer | undefined`, so `auditServerFor('constructor')` would hand
52
+ back `Object` typed as a Postgres enum value and pass every check between
53
+ here and the insert.
54
+ */
55
+ return Object.hasOwn(AUDIT_SERVER_BY_COLLECTOR_NAME, serverName)
56
+ ? AUDIT_SERVER_BY_COLLECTOR_NAME[serverName]
57
+ : undefined;
58
+ }
59
+ /** The message `collector.add` throws with when a server has no audit name. */
60
+ export function mcpServerRefusal(serverName) {
61
+ return (`MCP server "${serverName}" passed an audit writer but has no name in the audit log's ` +
62
+ `mcpServer enum, so a \`system.error\` row for its tools could not be written. ` +
63
+ `Known collector names: ${Object.keys(AUDIT_SERVER_BY_COLLECTOR_NAME).join(', ')}. ` +
64
+ `Audit enum values: ${AUDIT_MCP_SERVERS.join(', ')}. Add "${serverName}" to the map in ` +
65
+ `core/src/mcp/audit-server.ts, and — if the enum needs a new value — to AUDIT_MCP_SERVERS ` +
66
+ `with a migration in the host that adds it to enum_audit_events_mcp_server.`);
67
+ }
68
+ //# sourceMappingURL=audit-server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit-server.js","sourceRoot":"","sources":["../../src/mcp/audit-server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAuB,MAAM,mBAAmB,CAAA;AAE1E;;;;;;;;;;;;;;;;;;;;;;;;;;;EA2BE;AACF,MAAM,8BAA8B,GAA6C;IAC/E,SAAS,EAAE,WAAW;IACtB,KAAK,EAAE,OAAO;IACd,UAAU,EAAE,WAAW;IACvB,KAAK,EAAE,OAAO;IACd,YAAY,EAAE,cAAc;IAC5B,OAAO,EAAE,SAAS;IAClB,UAAU,EAAE,YAAY;CACzB,CAAA;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,cAAc,CAAC,UAAkB;IAC/C;;;;;;MAME;IACF,OAAO,MAAM,CAAC,MAAM,CAAC,8BAA8B,EAAE,UAAU,CAAC;QAC9D,CAAC,CAAC,8BAA8B,CAAC,UAAU,CAAC;QAC5C,CAAC,CAAC,SAAS,CAAA;AACf,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,gBAAgB,CAAC,UAAkB;IACjD,OAAO,CACL,eAAe,UAAU,8DAA8D;QACvF,gFAAgF;QAChF,0BAA0B,MAAM,CAAC,IAAI,CAAC,8BAA8B,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI;QACpF,sBAAsB,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,UAAU,kBAAkB;QACxF,2FAA2F;QAC3F,4EAA4E,CAC7E,CAAA;AACH,CAAC"}
@@ -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;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"}
1
+ {"version":3,"file":"collector.d.ts","sourceRoot":"","sources":["../../src/mcp/collector.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAA;AAE9E,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,CAkGlB"}
@@ -1,3 +1,4 @@
1
+ import { auditServerFor, mcpServerRefusal } from './audit-server.js';
1
2
  import { toPayloadMcpTools } from './payload-mcp.js';
2
3
  /**
3
4
  * Somewhere for the plugins to put their tools, that the host can pass to
@@ -53,7 +54,25 @@ export function createMcpToolCollector(options = {}) {
53
54
  },
54
55
  add(incoming, addOptions = {}) {
55
56
  const { serverName = 'an unnamed server', ...toolOptions } = addOptions;
56
- for (const tool of toPayloadMcpTools(incoming, { ...options, ...toolOptions })) {
57
+ /*
58
+ Which `mcpServer` this server's `system.error` rows carry, resolved once
59
+ per server at `onInit` rather than per request — and refused rather than
60
+ guessed, because the collector's names and the audit enum's names are two
61
+ lists that already disagree about one entry. See `audit-server.ts`.
62
+
63
+ Only when a writer was actually passed. A host wiring tools by hand
64
+ supplies no `audit`, and it should not have to invent a server name to do
65
+ that.
66
+ */
67
+ const auditServer = auditServerFor(serverName);
68
+ if (toolOptions.audit && !auditServer) {
69
+ throw new Error(mcpServerRefusal(serverName));
70
+ }
71
+ for (const tool of toPayloadMcpTools(incoming, {
72
+ ...options,
73
+ ...toolOptions,
74
+ ...(auditServer ? { auditServer } : {}),
75
+ })) {
57
76
  const slot = slots.get(tool.name);
58
77
  if (!slot) {
59
78
  throw new Error(`${serverName} built an MCP tool called "${tool.name}" that it never declared. ` +
@@ -1 +1 @@
1
- {"version":3,"file":"collector.js","sourceRoot":"","sources":["../../src/mcp/collector.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"collector.js","sourceRoot":"","sources":["../../src/mcp/collector.ts"],"names":[],"mappings":"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"}
@@ -7,4 +7,5 @@ export type { PayloadMcpRequest, PayloadMcpTool, ToPayloadMcpToolOptions, } from
7
7
  export { createMcpToolCollector } from './collector.js';
8
8
  export type { AddToolsOptions, CreateMcpToolCollectorOptions, DeclareToolsOptions, McpToolCollector, McpToolDescriptor, } from './collector.js';
9
9
  export { deniedEnvelope } from './envelope.js';
10
+ export { auditServerFor, mcpServerRefusal } from './audit-server.js';
10
11
  //# 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,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"}
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;AAE9C,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA"}
package/dist/mcp/index.js CHANGED
@@ -3,4 +3,5 @@ export { auditContext } from './audit-context.js';
3
3
  export { toPayloadMcpTool, toPayloadMcpTools } from './payload-mcp.js';
4
4
  export { createMcpToolCollector } from './collector.js';
5
5
  export { deniedEnvelope } from './envelope.js';
6
+ export { auditServerFor, mcpServerRefusal } from './audit-server.js';
6
7
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
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
+ {"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;AAE9C,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA"}
@@ -1,5 +1,7 @@
1
1
  import { z } from 'zod';
2
2
  import type { Logger, McpToolDefinition } from '@forumone/throughline-plugin-contract';
3
+ import type { AuditMcpServer } from '../audit/types.js';
4
+ import type { AuditWriter } from '../audit/writer.js';
3
5
  /** The tool shape `plugin-mcp` accepts under its `mcp.tools` option. */
4
6
  export interface PayloadMcpTool {
5
7
  name: string;
@@ -44,6 +46,20 @@ export interface ToPayloadMcpToolOptions {
44
46
  */
45
47
  apiKeyName?: string;
46
48
  logger?: Logger;
49
+ /**
50
+ * Where a tool's unhandled throw is recorded, as `system.error`.
51
+ *
52
+ * Optional, and absent means the previous behaviour: the throw reaches
53
+ * `plugin-mcp`, becomes a JSON-RPC error, and leaves no trace. Every server
54
+ * in the suite passes one; a host wiring a tool by hand need not.
55
+ */
56
+ audit?: AuditWriter;
57
+ /**
58
+ * Which `mcpServer` those rows are attributed to. Derived from the collector's
59
+ * `serverName` by `auditServerFor`, which is not the identity function — see
60
+ * `audit-server.ts`.
61
+ */
62
+ auditServer?: AuditMcpServer;
47
63
  }
48
64
  /**
49
65
  * Wraps one Throughline tool so Payload's MCP plugin can serve it.
@@ -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;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
+ {"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;AACtG,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AACvD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AA0BrD,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;IACf;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,WAAW,CAAA;IACnB;;;;OAIG;IACH,WAAW,CAAC,EAAE,cAAc,CAAA;CAC7B;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,iBAAiB,EACvB,OAAO,GAAE,uBAA4B,GACpC,cAAc,CAkBhB;AA0ED,2CAA2C;AAC3C,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,iBAAiB,EAAE,EAC1B,OAAO,GAAE,uBAA4B,GACpC,cAAc,EAAE,CAElB"}
@@ -1,5 +1,7 @@
1
1
  import { z } from 'zod';
2
2
  import { defaultLogger } from '../logger/index.js';
3
+ import { auditContext } from './audit-context.js';
4
+ import { McpMetaSchema } from './meta.js';
3
5
  /**
4
6
  * Wraps one Throughline tool so Payload's MCP plugin can serve it.
5
7
  *
@@ -22,11 +24,82 @@ export function toPayloadMcpTool(tool, options = {}) {
22
24
  description: tool.description,
23
25
  parameters: shape,
24
26
  handler: async (args, req) => {
25
- const result = await tool.handler(args, contextFrom(req, options));
26
- return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
27
+ const context = contextFrom(req, options);
28
+ try {
29
+ const result = await tool.handler(args, context);
30
+ return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
31
+ }
32
+ catch (error) {
33
+ await recordToolFailure(tool.name, error, args, context, options);
34
+ throw error;
35
+ }
27
36
  },
28
37
  };
29
38
  }
39
+ /*
40
+ The one place a tool's crash becomes a row, and the reason `system.error` had a
41
+ name in the taxonomy and no writer.
42
+
43
+ Audit 12 H3: `'system.error'` was declared in `audit/types.ts`, present in the
44
+ Postgres enum, and written by nothing — while `observability.md` opened with
45
+ "the audit log is the single most useful debugging tool" and listed errors among
46
+ what lands there. A tool that returns `deniedEnvelope` or an `{ error }` result
47
+ audits itself; a tool that *throws* did not, so the failures most worth reading
48
+ were the only ones absent.
49
+
50
+ This is the choke point every tool in the suite passes through — all six
51
+ servers, every tool — so wrapping here is one wrap rather than one per tool,
52
+ and a tool added tomorrow is covered without its author knowing this file
53
+ exists. It also covers the tools that audit nothing else: `list_components`,
54
+ `get_contract`, `get_variants`, `get_tokens` and the five audit reads write no
55
+ row on success, so a crash is the only thing they have ever recorded.
56
+
57
+ Three properties it has to have, in order:
58
+
59
+ **The original error still propagates.** `plugin-mcp` turns a throw into a
60
+ JSON-RPC error and the client needs that. Recording is a side effect, not a
61
+ handler.
62
+
63
+ **Recording cannot itself fail the call.** `createAuditWriter` already swallows
64
+ its own write failures, but `options.audit` is an interface and a caller may
65
+ pass something less careful, so the `await` is wrapped too. An audit miss is a
66
+ gap in a log; a throw from here would replace the tool's real error with this
67
+ file's, which is the one outcome that would make debugging worse rather than
68
+ better.
69
+
70
+ **The message is the error's, and nothing else.** No stack: `errorMessage` is a
71
+ `varchar` on a table admins and editors can read through the admin UI, and a
72
+ stack names file paths and sometimes argument values. The arguments are not
73
+ recorded either — a tool's input can carry a form submission or a draft — but
74
+ `_meta` is, because the agent's own prompt and reasoning are what make a crash
75
+ row legible, and they are already recorded on every successful write.
76
+ */
77
+ async function recordToolFailure(toolName, error, args, context, options) {
78
+ const { audit, auditServer } = options;
79
+ const logger = context.logger ?? defaultLogger;
80
+ const message = error instanceof Error ? error.message : String(error);
81
+ logger.error(`MCP tool "${toolName}" threw`, { tool: toolName, error: message });
82
+ if (!audit || !auditServer)
83
+ return;
84
+ try {
85
+ const meta = McpMetaSchema.safeParse(args['_meta']);
86
+ await audit({
87
+ ...auditContext(context, meta.success ? meta.data : undefined),
88
+ action: 'system.error',
89
+ mcpServer: auditServer,
90
+ mcpTool: toolName,
91
+ summary: `${toolName} threw: ${message}`,
92
+ success: false,
93
+ errorMessage: message,
94
+ });
95
+ }
96
+ catch (recordError) {
97
+ logger.error('Recording an MCP tool failure failed', {
98
+ tool: toolName,
99
+ error: String(recordError),
100
+ });
101
+ }
102
+ }
30
103
  /** Every tool in a server, in one call. */
31
104
  export function toPayloadMcpTools(tools, options = {}) {
32
105
  return tools.map(tool => toPayloadMcpTool(tool, options));
@@ -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;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
+ {"version":3,"file":"payload-mcp.js","sourceRoot":"","sources":["../../src/mcp/payload-mcp.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@forumone/throughline-core",
3
- "version": "0.8.1",
3
+ "version": "0.9.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",
@@ -66,7 +66,7 @@
66
66
  "inngest": "^4.2.0",
67
67
  "payload": "^3.83.0",
68
68
  "typescript": "^5.6.0",
69
- "vitest": "^2.1.0",
69
+ "vitest": "^4.1.10",
70
70
  "@forumone/throughline-eslint-config": "0.0.0",
71
71
  "@forumone/throughline-tsconfig": "0.0.0"
72
72
  },