@particle-academy/agent-integrations 0.49.0 → 0.51.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 +68 -0
- package/README.md +11 -0
- package/dist/bridges/artboard.d.cts +3 -3
- package/dist/bridges/artboard.d.ts +3 -3
- package/dist/bridges/catalog.d.cts +3 -3
- package/dist/bridges/catalog.d.ts +3 -3
- package/dist/bridges/charts.d.cts +3 -3
- package/dist/bridges/charts.d.ts +3 -3
- package/dist/bridges/cms.d.cts +3 -3
- package/dist/bridges/cms.d.ts +3 -3
- package/dist/bridges/code.d.cts +3 -3
- package/dist/bridges/code.d.ts +3 -3
- package/dist/bridges/doc.d.cts +3 -3
- package/dist/bridges/doc.d.ts +3 -3
- package/dist/bridges/features.d.cts +3 -3
- package/dist/bridges/features.d.ts +3 -3
- package/dist/bridges/files.d.cts +3 -3
- package/dist/bridges/files.d.ts +3 -3
- package/dist/bridges/flow.d.cts +3 -3
- package/dist/bridges/flow.d.ts +3 -3
- package/dist/bridges/forms.d.cts +3 -3
- package/dist/bridges/forms.d.ts +3 -3
- package/dist/bridges/git.d.cts +3 -3
- package/dist/bridges/git.d.ts +3 -3
- package/dist/bridges/grid.d.cts +3 -3
- package/dist/bridges/grid.d.ts +3 -3
- package/dist/bridges/map.d.cts +3 -3
- package/dist/bridges/map.d.ts +3 -3
- package/dist/bridges/navigation.d.cts +3 -3
- package/dist/bridges/navigation.d.ts +3 -3
- package/dist/bridges/passkeys.d.cts +3 -3
- package/dist/bridges/passkeys.d.ts +3 -3
- package/dist/bridges/scene.d.cts +3 -3
- package/dist/bridges/scene.d.ts +3 -3
- package/dist/bridges/screen-doc.d.cts +3 -3
- package/dist/bridges/screen-doc.d.ts +3 -3
- package/dist/bridges/screens.d.cts +3 -3
- package/dist/bridges/screens.d.ts +3 -3
- package/dist/bridges/sheets.d.cts +3 -3
- package/dist/bridges/sheets.d.ts +3 -3
- package/dist/bridges/slides.d.cts +3 -3
- package/dist/bridges/slides.d.ts +3 -3
- package/dist/bridges/terminal.d.cts +3 -3
- package/dist/bridges/terminal.d.ts +3 -3
- package/dist/bridges/tui.d.cts +2 -2
- package/dist/bridges/tui.d.ts +2 -2
- package/dist/bridges/whiteboard.d.cts +3 -3
- package/dist/bridges/whiteboard.d.ts +3 -3
- package/dist/bridges-artboard.cjs +11 -5
- package/dist/bridges-artboard.cjs.map +1 -1
- package/dist/bridges-artboard.js +6 -4
- package/dist/bridges-artboard.js.map +1 -1
- package/dist/bridges-catalog.cjs +35 -13
- package/dist/bridges-catalog.cjs.map +1 -1
- package/dist/bridges-catalog.js +3 -3
- package/dist/bridges-charts.cjs +11 -5
- package/dist/bridges-charts.cjs.map +1 -1
- package/dist/bridges-charts.js +3 -3
- package/dist/bridges-cms.cjs +11 -5
- package/dist/bridges-cms.cjs.map +1 -1
- package/dist/bridges-cms.js +4 -4
- package/dist/bridges-code.cjs +11 -5
- package/dist/bridges-code.cjs.map +1 -1
- package/dist/bridges-code.js +3 -3
- package/dist/bridges-doc.cjs +11 -5
- package/dist/bridges-doc.cjs.map +1 -1
- package/dist/bridges-doc.js +3 -3
- package/dist/bridges-features.cjs +21 -11
- package/dist/bridges-features.cjs.map +1 -1
- package/dist/bridges-features.js +3 -3
- package/dist/bridges-files.cjs +11 -5
- package/dist/bridges-files.cjs.map +1 -1
- package/dist/bridges-files.js +3 -3
- package/dist/bridges-flow.cjs +11 -5
- package/dist/bridges-flow.cjs.map +1 -1
- package/dist/bridges-flow.js +6 -4
- package/dist/bridges-flow.js.map +1 -1
- package/dist/bridges-forms.cjs +11 -5
- package/dist/bridges-forms.cjs.map +1 -1
- package/dist/bridges-forms.js +3 -3
- package/dist/bridges-git.cjs +10 -5
- package/dist/bridges-git.cjs.map +1 -1
- package/dist/bridges-git.js +3 -3
- package/dist/bridges-grid.cjs +11 -5
- package/dist/bridges-grid.cjs.map +1 -1
- package/dist/bridges-grid.js +3 -3
- package/dist/bridges-map.cjs +11 -5
- package/dist/bridges-map.cjs.map +1 -1
- package/dist/bridges-map.js +3 -3
- package/dist/bridges-navigation.cjs +15 -9
- package/dist/bridges-navigation.cjs.map +1 -1
- package/dist/bridges-navigation.js +3 -3
- package/dist/bridges-passkeys.cjs +17 -7
- package/dist/bridges-passkeys.cjs.map +1 -1
- package/dist/bridges-passkeys.js +3 -3
- package/dist/bridges-scene.cjs +11 -5
- package/dist/bridges-scene.cjs.map +1 -1
- package/dist/bridges-scene.js +3 -3
- package/dist/bridges-screen-doc.cjs +14 -6
- package/dist/bridges-screen-doc.cjs.map +1 -1
- package/dist/bridges-screen-doc.js +4 -4
- package/dist/bridges-screens.cjs +11 -5
- package/dist/bridges-screens.cjs.map +1 -1
- package/dist/bridges-screens.js +3 -3
- package/dist/bridges-sheets.cjs +11 -5
- package/dist/bridges-sheets.cjs.map +1 -1
- package/dist/bridges-sheets.js +3 -3
- package/dist/bridges-slides.cjs +11 -5
- package/dist/bridges-slides.cjs.map +1 -1
- package/dist/bridges-slides.js +3 -3
- package/dist/bridges-terminal.cjs +11 -5
- package/dist/bridges-terminal.cjs.map +1 -1
- package/dist/bridges-terminal.js +3 -3
- package/dist/bridges-tui.cjs +1 -1
- package/dist/bridges-tui.cjs.map +1 -1
- package/dist/bridges-tui.js +2 -2
- package/dist/bridges-whiteboard.cjs +11 -5
- package/dist/bridges-whiteboard.cjs.map +1 -1
- package/dist/bridges-whiteboard.js +3 -3
- package/dist/{chunk-CZV3WUW5.js → chunk-3GFKC6OK.js} +20 -7
- package/dist/chunk-3GFKC6OK.js.map +1 -0
- package/dist/{chunk-JLHVQWOV.js → chunk-6Q3PMT7K.js} +4 -4
- package/dist/chunk-6Q3PMT7K.js.map +1 -0
- package/dist/{chunk-AXWMWYH5.js → chunk-C4AQ2YBW.js} +7 -6
- package/dist/chunk-C4AQ2YBW.js.map +1 -0
- package/dist/{chunk-CS3CHGYC.js → chunk-CI5ZVHDY.js} +32 -14
- package/dist/chunk-CI5ZVHDY.js.map +1 -0
- package/dist/{chunk-5ZWNCHZS.js → chunk-CKJL5C7A.js} +8 -6
- package/dist/chunk-CKJL5C7A.js.map +1 -0
- package/dist/{chunk-HOZCDDRA.js → chunk-CP3EHLZJ.js} +8 -6
- package/dist/chunk-CP3EHLZJ.js.map +1 -0
- package/dist/{chunk-VFWFT3OK.js → chunk-DNF3QVTW.js} +8 -6
- package/dist/chunk-DNF3QVTW.js.map +1 -0
- package/dist/{chunk-OHNGURUJ.js → chunk-HNVHAY4A.js} +12 -10
- package/dist/chunk-HNVHAY4A.js.map +1 -0
- package/dist/{chunk-GVTBMJU6.js → chunk-KAEPC6N4.js} +18 -12
- package/dist/chunk-KAEPC6N4.js.map +1 -0
- package/dist/{chunk-3WVXAB3D.js → chunk-M423JOQ3.js} +3 -3
- package/dist/{chunk-3WVXAB3D.js.map → chunk-M423JOQ3.js.map} +1 -1
- package/dist/{chunk-SWWJUOCY.js → chunk-MKC633WU.js} +3 -3
- package/dist/{chunk-SWWJUOCY.js.map → chunk-MKC633WU.js.map} +1 -1
- package/dist/{chunk-LQB42OSA.js → chunk-MKJE6V4Z.js} +8 -6
- package/dist/chunk-MKJE6V4Z.js.map +1 -0
- package/dist/{chunk-MIDZWKIF.js → chunk-NB5AQIR2.js} +8 -6
- package/dist/chunk-NB5AQIR2.js.map +1 -0
- package/dist/{chunk-VMRUW4B4.js → chunk-OUUHFR4N.js} +8 -6
- package/dist/chunk-OUUHFR4N.js.map +1 -0
- package/dist/{chunk-FCXSR7I5.js → chunk-P6SJBP5T.js} +8 -6
- package/dist/chunk-P6SJBP5T.js.map +1 -0
- package/dist/{chunk-5JLTXHX6.js → chunk-PMPBI6I3.js} +7 -5
- package/dist/chunk-PMPBI6I3.js.map +1 -0
- package/dist/{chunk-G6CRHFWU.js → chunk-PV4FZDYX.js} +14 -8
- package/dist/chunk-PV4FZDYX.js.map +1 -0
- package/dist/{chunk-3UUF5KKZ.js → chunk-QEVSNDJW.js} +8 -6
- package/dist/chunk-QEVSNDJW.js.map +1 -0
- package/dist/{chunk-VOCUGTZB.js → chunk-S4DA2UTJ.js} +8 -6
- package/dist/chunk-S4DA2UTJ.js.map +1 -0
- package/dist/{chunk-RVMM4BHK.js → chunk-V6EHKHSF.js} +8 -6
- package/dist/chunk-V6EHKHSF.js.map +1 -0
- package/dist/{chunk-36MKPTVD.js → chunk-VE7TRWZR.js} +8 -6
- package/dist/chunk-VE7TRWZR.js.map +1 -0
- package/dist/{chunk-Z5NL5D4J.js → chunk-VFUKZ6UA.js} +8 -6
- package/dist/chunk-VFUKZ6UA.js.map +1 -0
- package/dist/{chunk-3HVYUMQF.js → chunk-VHB3VE53.js} +8 -6
- package/dist/chunk-VHB3VE53.js.map +1 -0
- package/dist/{chunk-R4XXOGQH.js → chunk-ZDKYKJFH.js} +10 -6
- package/dist/chunk-ZDKYKJFH.js.map +1 -0
- package/dist/components-shared-whiteboard.cjs +29 -10
- package/dist/components-shared-whiteboard.cjs.map +1 -1
- package/dist/components-shared-whiteboard.js +3 -3
- package/dist/dom-navigation/index.d.cts +3 -3
- package/dist/dom-navigation/index.d.ts +3 -3
- package/dist/index.cjs +140 -64
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -5
- package/dist/index.d.ts +5 -5
- package/dist/index.js +26 -26
- package/dist/mcp/index.d.cts +5 -5
- package/dist/mcp/index.d.ts +5 -5
- package/dist/mcp/stdio.d.cts +3 -3
- package/dist/mcp/stdio.d.ts +3 -3
- package/dist/mcp.cjs +18 -5
- package/dist/mcp.cjs.map +1 -1
- package/dist/mcp.js +1 -1
- package/dist/presence/index.d.cts +1 -1
- package/dist/presence/index.d.ts +1 -1
- package/dist/{server-1y0n61R5.d.cts → server-DJJygNo1.d.cts} +2 -2
- package/dist/{server-vq6qVl3T.d.ts → server-Dwo9LOxh.d.ts} +2 -2
- package/dist/sharing/index.d.cts +3 -3
- package/dist/sharing/index.d.ts +3 -3
- package/dist/sheets-adapter.d.cts +3 -3
- package/dist/sheets-adapter.d.ts +3 -3
- package/dist/{tool-host-LYfdPE8u.d.ts → tool-host-BBSaU7IJ.d.cts} +10 -4
- package/dist/{tool-host-D67N2a2h.d.cts → tool-host-BqJRPr_T.d.ts} +10 -4
- package/dist/{types-DP5yQZQU.d.cts → types-D_H2f-wF.d.cts} +1 -1
- package/dist/{types-VX_9je7w.d.ts → types-D_TzdBsK.d.ts} +1 -1
- package/dist/{types-gzIpsUDE.d.cts → types-ITRQFAir.d.cts} +26 -1
- package/dist/{types-gzIpsUDE.d.ts → types-ITRQFAir.d.ts} +26 -1
- package/dist/undo/index.d.cts +2 -2
- package/dist/undo/index.d.ts +2 -2
- package/dist/undo.cjs +7 -3
- package/dist/undo.cjs.map +1 -1
- package/dist/undo.js +3 -3
- package/package.json +1 -1
- package/dist/chunk-36MKPTVD.js.map +0 -1
- package/dist/chunk-3HVYUMQF.js.map +0 -1
- package/dist/chunk-3UUF5KKZ.js.map +0 -1
- package/dist/chunk-5JLTXHX6.js.map +0 -1
- package/dist/chunk-5ZWNCHZS.js.map +0 -1
- package/dist/chunk-AXWMWYH5.js.map +0 -1
- package/dist/chunk-CS3CHGYC.js.map +0 -1
- package/dist/chunk-CZV3WUW5.js.map +0 -1
- package/dist/chunk-FCXSR7I5.js.map +0 -1
- package/dist/chunk-G6CRHFWU.js.map +0 -1
- package/dist/chunk-GVTBMJU6.js.map +0 -1
- package/dist/chunk-HOZCDDRA.js.map +0 -1
- package/dist/chunk-JLHVQWOV.js.map +0 -1
- package/dist/chunk-LQB42OSA.js.map +0 -1
- package/dist/chunk-MIDZWKIF.js.map +0 -1
- package/dist/chunk-OHNGURUJ.js.map +0 -1
- package/dist/chunk-R4XXOGQH.js.map +0 -1
- package/dist/chunk-RVMM4BHK.js.map +0 -1
- package/dist/chunk-VFWFT3OK.js.map +0 -1
- package/dist/chunk-VMRUW4B4.js.map +0 -1
- package/dist/chunk-VOCUGTZB.js.map +0 -1
- package/dist/chunk-Z5NL5D4J.js.map +0 -1
package/dist/bridges-catalog.cjs
CHANGED
|
@@ -48,6 +48,7 @@ function extractMeta(result) {
|
|
|
48
48
|
|
|
49
49
|
// src/undo/undo-tools.ts
|
|
50
50
|
var installedHosts = /* @__PURE__ */ new WeakSet();
|
|
51
|
+
var UNDO_TOOLS_OWNER = "agent-undo";
|
|
51
52
|
function ensureUndoToolsRegistered(host, options = {}) {
|
|
52
53
|
if (installedHosts.has(host)) return;
|
|
53
54
|
installedHosts.add(host);
|
|
@@ -72,7 +73,8 @@ function registerUndoTools(host, options = {}) {
|
|
|
72
73
|
const entry = await fancyAutoCommon.undoOne(agentOf(args));
|
|
73
74
|
if (!entry) return errorResult("Nothing to undo.");
|
|
74
75
|
return textResult(`Undid: ${entry.label}`, { entry: serialize(entry) });
|
|
75
|
-
}
|
|
76
|
+
},
|
|
77
|
+
{ owner: UNDO_TOOLS_OWNER }
|
|
76
78
|
)
|
|
77
79
|
);
|
|
78
80
|
disposers.push(
|
|
@@ -90,7 +92,8 @@ function registerUndoTools(host, options = {}) {
|
|
|
90
92
|
const entry = await fancyAutoCommon.redoOne(agentOf(args));
|
|
91
93
|
if (!entry) return errorResult("Nothing to redo.");
|
|
92
94
|
return textResult(`Redid: ${entry.label}`, { entry: serialize(entry) });
|
|
93
|
-
}
|
|
95
|
+
},
|
|
96
|
+
{ owner: UNDO_TOOLS_OWNER }
|
|
94
97
|
)
|
|
95
98
|
);
|
|
96
99
|
disposers.push(
|
|
@@ -108,7 +111,8 @@ function registerUndoTools(host, options = {}) {
|
|
|
108
111
|
const history = fancyAutoCommon.readHistory(agentOf(args)).map(serialize);
|
|
109
112
|
const text = history.map((e) => `${new Date(e.timestamp).toISOString()} ${e.bridgeId} ${e.action}: ${e.label}`).join("\n");
|
|
110
113
|
return textResult(text || "(empty)", history);
|
|
111
|
-
}
|
|
114
|
+
},
|
|
115
|
+
{ owner: UNDO_TOOLS_OWNER }
|
|
112
116
|
)
|
|
113
117
|
);
|
|
114
118
|
return () => disposers.forEach((d) => d());
|
|
@@ -132,6 +136,7 @@ function registerCatalogBridge(host, options) {
|
|
|
132
136
|
const pendingMode = options.pendingMode ?? true;
|
|
133
137
|
const catalogId = adapter.id ?? "catalog";
|
|
134
138
|
const disposers = [];
|
|
139
|
+
const bridgeId = `catalog:${catalogId}`;
|
|
135
140
|
ensureUndoToolsRegistered(host, { defaultAgentId: agent.id });
|
|
136
141
|
const target = (elementId, label) => ({
|
|
137
142
|
kind: "custom",
|
|
@@ -157,7 +162,8 @@ function registerCatalogBridge(host, options) {
|
|
|
157
162
|
disposers.push(
|
|
158
163
|
host.registerTool(
|
|
159
164
|
{ name, description, inputSchema: { type: "object", properties, required, additionalProperties: false } },
|
|
160
|
-
final
|
|
165
|
+
final,
|
|
166
|
+
{ owner: bridgeId }
|
|
161
167
|
)
|
|
162
168
|
);
|
|
163
169
|
};
|
|
@@ -254,8 +260,12 @@ function registerCatalogBridge(host, options) {
|
|
|
254
260
|
bridgeId: catalogId,
|
|
255
261
|
action: "catalog_create_product",
|
|
256
262
|
label: `Created product ${product.id} (${product.name})`,
|
|
257
|
-
undo: () =>
|
|
258
|
-
|
|
263
|
+
undo: async () => {
|
|
264
|
+
await adapter.products.remove(product.id);
|
|
265
|
+
},
|
|
266
|
+
redo: async () => {
|
|
267
|
+
await adapter.createProduct({ ...product });
|
|
268
|
+
}
|
|
259
269
|
});
|
|
260
270
|
return textResult(`Created product ${product.id} (${product.name})`, product);
|
|
261
271
|
},
|
|
@@ -296,8 +306,12 @@ function registerCatalogBridge(host, options) {
|
|
|
296
306
|
bridgeId: catalogId,
|
|
297
307
|
action: "catalog_create_price",
|
|
298
308
|
label: `Created price ${price.id} on ${productId}`,
|
|
299
|
-
undo: () =>
|
|
300
|
-
|
|
309
|
+
undo: async () => {
|
|
310
|
+
await adapter.prices.remove(price.id);
|
|
311
|
+
},
|
|
312
|
+
redo: async () => {
|
|
313
|
+
await adapter.createPrice({ ...price });
|
|
314
|
+
}
|
|
301
315
|
});
|
|
302
316
|
return textResult(`Created ${type} price ${price.id} on ${productId}`, price);
|
|
303
317
|
},
|
|
@@ -321,8 +335,12 @@ function registerCatalogBridge(host, options) {
|
|
|
321
335
|
bridgeId: catalogId,
|
|
322
336
|
action: "catalog_delete_product",
|
|
323
337
|
label: `Deleted product ${id} (${product.name})`,
|
|
324
|
-
undo: () =>
|
|
325
|
-
|
|
338
|
+
undo: async () => {
|
|
339
|
+
await adapter.createProduct({ ...snapshot });
|
|
340
|
+
},
|
|
341
|
+
redo: async () => {
|
|
342
|
+
await adapter.products.remove(id);
|
|
343
|
+
}
|
|
326
344
|
});
|
|
327
345
|
return textResult(`Deleted product ${id}`, { id });
|
|
328
346
|
},
|
|
@@ -346,8 +364,12 @@ function registerCatalogBridge(host, options) {
|
|
|
346
364
|
bridgeId: catalogId,
|
|
347
365
|
action: "catalog_delete_price",
|
|
348
366
|
label: `Deleted price ${id}`,
|
|
349
|
-
undo: () =>
|
|
350
|
-
|
|
367
|
+
undo: async () => {
|
|
368
|
+
await adapter.createPrice({ ...snapshot });
|
|
369
|
+
},
|
|
370
|
+
redo: async () => {
|
|
371
|
+
await adapter.prices.remove(id);
|
|
372
|
+
}
|
|
351
373
|
});
|
|
352
374
|
return textResult(`Deleted price ${id}`, { id });
|
|
353
375
|
},
|
|
@@ -415,7 +437,7 @@ function registerCatalogBridge(host, options) {
|
|
|
415
437
|
(args) => target(str(args.priceId), `checkout ${str(args.priceId)}`)
|
|
416
438
|
);
|
|
417
439
|
return {
|
|
418
|
-
id:
|
|
440
|
+
id: bridgeId,
|
|
419
441
|
title: adapter.title ?? "Catalog",
|
|
420
442
|
dispose: () => {
|
|
421
443
|
for (const d of disposers.splice(0)) d();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/mcp/server.ts","../src/presence/wrap-tool-with-activity.ts","../src/undo/undo-tools.ts","../src/bridges/catalog.ts"],"names":["emitActivity","undoOne","redoOne","readHistory","pushUndoEntry"],"mappings":"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","file":"bridges-catalog.cjs","sourcesContent":["import {\n type CallToolResult,\n type JsonObject,\n type JsonRpcMessage,\n type JsonRpcRequest,\n type JsonRpcId,\n type RegisteredTool,\n type ServerCapabilities,\n type ServerInfo,\n type ToolDefinition,\n type ToolHandler,\n JSONRPC_INTERNAL_ERROR,\n JSONRPC_INVALID_PARAMS,\n JSONRPC_METHOD_NOT_FOUND,\n MCP_PROTOCOL_VERSION,\n} from \"./types\";\nimport { ToolRegistry } from \"./tool-host\";\n\nexport type McpServerOptions = {\n info: ServerInfo;\n /** Defaults to { tools: { listChanged: true } } */\n capabilities?: ServerCapabilities;\n /** Free-text instructions surfaced to clients during initialize. */\n instructions?: string;\n /**\n * The protocol revisions this server speaks, NEWEST FIRST.\n *\n * `initialize` echoes the client's requested revision when it is in this\n * list, and answers the first entry otherwise — the spec's rule, which leaves\n * the client to decide whether it can live with the answer.\n *\n * Defaults to `[MCP_PROTOCOL_VERSION]`: one revision, answered whatever the\n * client asks, which is exactly what this server did before the option\n * existed. Only list a revision the tools you register are correct under.\n */\n protocolVersions?: readonly string[];\n};\n\nexport type Transport = {\n /** Called by the server when it has a message to deliver to the client. */\n send: (message: JsonRpcMessage) => void;\n /** Called by the server when it's torn down so the transport can clean up. */\n close?: () => void;\n};\n\n/**\n * MicroMcpServer — protocol-level MCP server, transport-agnostic.\n *\n * Use it like:\n *\n * const server = new MicroMcpServer({ info: { name: \"session\", version: \"0.1\" } });\n * server.registerTool({ name: \"...\", inputSchema: { type: \"object\" } }, async (args) => ({...}));\n * const transport = new InProcessTransport();\n * server.attach(transport);\n * transport.deliver({ ... }); // client → server frames\n *\n * The same server can serve multiple transports (e.g. an in-process agent\n * AND a relayed external client) by attaching each one.\n */\nexport class MicroMcpServer extends ToolRegistry {\n private transports = new Set<Transport>();\n /**\n * Transports owed a `tools/list_changed` at the end of this tick. Empty when\n * none is scheduled. See {@link scheduleListChangedNotification}.\n */\n private listChangedOwed = new Set<Transport>();\n\n readonly info: ServerInfo;\n readonly capabilities: ServerCapabilities;\n readonly instructions?: string;\n readonly protocolVersions: readonly string[];\n\n constructor(options: McpServerOptions) {\n super();\n this.info = options.info;\n this.capabilities = options.capabilities ?? { tools: { listChanged: true } };\n this.instructions = options.instructions;\n if (options.protocolVersions && options.protocolVersions.length === 0) {\n // No answer exists for a client's initialize. Fail here, next to the\n // mistake, rather than in a handshake nobody is watching.\n throw new Error(\"MicroMcpServer: protocolVersions is empty — a server must speak at least one protocol revision.\");\n }\n this.protocolVersions = options.protocolVersions ? [...options.protocolVersions] : [MCP_PROTOCOL_VERSION];\n }\n\n attach(transport: Transport): () => void {\n this.transports.add(transport);\n return () => this.detach(transport);\n }\n\n detach(transport: Transport): void {\n if (this.transports.delete(transport)) {\n transport.close?.();\n }\n }\n\n unregisterTool(name: string): void {\n if (this.tools.delete(name)) {\n this.scheduleListChangedNotification();\n }\n }\n\n protected onToolsChanged(): void {\n this.scheduleListChangedNotification();\n }\n\n /**\n * Receive a JSON-RPC frame from a client (called by the transport).\n * The transport is responsible for sending the response back.\n */\n async receive(transport: Transport, message: JsonRpcMessage): Promise<void> {\n if (!(\"method\" in message)) return; // It's a response, not a request — ignore.\n\n const isNotification = !(\"id\" in message);\n if (isNotification) {\n // Notifications are fire-and-forget. We ignore unknown methods.\n return;\n }\n\n const request = message as JsonRpcRequest;\n try {\n const result = await this.handle(request, transport);\n transport.send({ jsonrpc: \"2.0\", id: request.id, result });\n } catch (err) {\n transport.send({\n jsonrpc: \"2.0\",\n id: request.id,\n error: this.toRpcError(err),\n });\n }\n }\n\n private async handle(request: JsonRpcRequest, transport: Transport): Promise<any> {\n const { method, params } = request;\n switch (method) {\n case \"initialize\":\n return {\n protocolVersion: this.negotiate(params?.protocolVersion),\n capabilities: this.capabilities,\n serverInfo: this.info,\n ...(this.instructions ? { instructions: this.instructions } : {}),\n };\n\n case \"tools/list\":\n return { tools: this.listTools() };\n\n case \"tools/call\": {\n const name = params?.name;\n const args = (params?.arguments ?? {}) as JsonObject;\n if (typeof name !== \"string\") {\n throw rpcError(JSONRPC_INVALID_PARAMS, \"tools/call requires `name`\");\n }\n const tool = this.tools.get(name);\n if (!tool) {\n throw rpcError(JSONRPC_METHOD_NOT_FOUND, this.missingToolMessage(name));\n }\n const result = await tool.handler(args, { transport });\n return result satisfies CallToolResult;\n }\n\n case \"ping\":\n return {};\n\n default:\n throw rpcError(JSONRPC_METHOD_NOT_FOUND, `Unsupported method: ${method}`);\n }\n }\n\n /** The revision to answer `initialize` with: the one asked for if spoken, else the newest. */\n private negotiate(requested: unknown): string {\n return typeof requested === \"string\" && this.protocolVersions.includes(requested)\n ? requested\n : this.protocolVersions[0];\n }\n\n /**\n * Tell the transports that SAW the old tool list that it changed.\n *\n * Changes in one tick coalesce into one notification. The recipients are the\n * transports attached at the moment of a change, not at the moment the\n * notification goes out: a transport attached afterwards never had the old\n * list, so \"your list is stale\" is noise to it — and on stdio, where a host\n * builds the server and attaches stdin/stdout in the same tick, it was the\n * first frame a client received, before it had even sent `initialize`.\n */\n private scheduleListChangedNotification(): void {\n if (this.transports.size === 0) return;\n const scheduled = this.listChangedOwed.size > 0;\n for (const t of this.transports) this.listChangedOwed.add(t);\n if (scheduled) return;\n queueMicrotask(() => {\n const owed = this.listChangedOwed;\n this.listChangedOwed = new Set();\n for (const t of owed) {\n // Detached since the change: it is not listening any more.\n if (this.transports.has(t)) t.send({ jsonrpc: \"2.0\", method: \"notifications/tools/list_changed\" });\n }\n });\n }\n\n /** Send an application notification to every client, or one attached transport. */\n notify(message: JsonRpcMessage, transport?: Transport): void {\n if (transport) transport.send(message);\n else this.broadcast(message);\n }\n\n private broadcast(message: JsonRpcMessage): void {\n for (const t of this.transports) t.send(message);\n }\n\n private toRpcError(err: unknown): { code: number; message: string; data?: any } {\n if (err && typeof err === \"object\" && \"code\" in err && \"message\" in err) {\n return err as any;\n }\n return {\n code: JSONRPC_INTERNAL_ERROR,\n message: err instanceof Error ? err.message : String(err),\n };\n }\n}\n\nexport function rpcError(code: number, message: string, data?: any) {\n return { code, message, ...(data !== undefined ? { data } : {}) };\n}\n\n/**\n * Helper to build a CallToolResult from a string or structured value.\n */\nexport function textResult(text: string, structured?: any): CallToolResult {\n return {\n content: [{ type: \"text\", text }],\n ...(structured !== undefined ? { structuredContent: structured } : {}),\n };\n}\n\nexport function errorResult(text: string): CallToolResult {\n return { content: [{ type: \"text\", text }], isError: true };\n}\n\n// Internal helper so the JsonRpcId import isn't dropped by tsup\ntype _KeepIdImport = JsonRpcId;\n","import type { CallToolResult } from \"../mcp/types\";\nimport { emitActivity } from \"./registry\";\nimport type { AgentTarget } from \"./types\";\n\nexport type ActivityAgent = { id: string; name?: string; color?: string };\n\nexport type ActivityResolverContext<TArgs = Record<string, unknown>> = {\n /** Tool name as registered. */\n toolName: string;\n /** Arguments the tool was called with. */\n args: TArgs;\n /** The CallToolResult the underlying handler produced. */\n result: CallToolResult;\n};\n\n/**\n * Resolves an `AgentTarget` for an executed tool. Bridges declare one of\n * these per registration so the wrapper knows which surface / element /\n * screen the activity belongs to.\n *\n * The resolver runs AFTER the tool handler so it can inspect the result\n * (e.g. read a newly-created item id from `structuredContent`).\n */\nexport type ActivityTargetResolver<TArgs = Record<string, unknown>> = (\n ctx: ActivityResolverContext<TArgs>,\n) => AgentTarget | null;\n\nexport type ToolHandler<TArgs = Record<string, unknown>> = (\n args: TArgs,\n) => Promise<CallToolResult> | CallToolResult;\n\n/**\n * wrapToolWithActivity — decorate a bridge tool handler so every successful\n * call emits an `AgentActivityEvent`. Returns a new handler with the same shape.\n *\n * Usage in a bridge:\n *\n * server.registerTool(\n * definition,\n * wrapToolWithActivity(\n * handler,\n * { agent, kind: \"whiteboard\", resolveTarget: ({ args }) => ({\n * kind: \"whiteboard\", elementId: args.id as string,\n * }) },\n * ),\n * );\n */\nexport function wrapToolWithActivity<TArgs = Record<string, unknown>>(\n handler: ToolHandler<TArgs>,\n options: {\n toolName: string;\n agent: ActivityAgent;\n /** Optional fancy-screens screen id this bridge is scoped to. */\n screenId?: string;\n /** Default target kind if the resolver returns one without `kind`. */\n kind: AgentTarget[\"kind\"];\n /** Per-call resolver. Return `null` to skip emitting (e.g. for read-only tools). */\n resolveTarget?: ActivityTargetResolver<TArgs>;\n /** Optional ttl override. */\n ttlMs?: number;\n /**\n * Build the `meta` broadcast to all relay peers. Defaults to the tool's full\n * `structuredContent`. Override to REDACT sensitive fields before fan-out —\n * e.g. the terminal bridge strips raw command/keystroke bytes so a command\n * line (or its secrets) is never broadcast verbatim to every peer.\n */\n buildMeta?: (result: CallToolResult) => Record<string, unknown> | undefined;\n },\n): ToolHandler<TArgs> {\n return async (args) => {\n const result = await handler(args);\n if (result.isError) return result;\n\n let target: AgentTarget | null;\n if (options.resolveTarget) {\n target = options.resolveTarget({ toolName: options.toolName, args, result });\n } else {\n target = { kind: options.kind, screenId: options.screenId };\n }\n if (!target) return result;\n\n emitActivity({\n agentId: options.agent.id,\n agentName: options.agent.name,\n agentColor: options.agent.color,\n target: { ...target, kind: target.kind ?? options.kind, screenId: target.screenId ?? options.screenId },\n action: options.toolName,\n timestamp: Date.now(),\n meta: options.buildMeta ? options.buildMeta(result) : extractMeta(result),\n ttlMs: options.ttlMs,\n });\n return result;\n };\n}\n\nfunction extractMeta(result: CallToolResult): Record<string, unknown> | undefined {\n const sc = result.structuredContent;\n if (sc && typeof sc === \"object\" && !Array.isArray(sc)) {\n return sc as Record<string, unknown>;\n }\n return undefined;\n}\n","import { textResult, errorResult } from \"../mcp/server\";\nimport type { ToolHost } from \"../mcp/tool-host\";\nimport { readHistory, redoOne, undoOne } from \"./undo-stack\";\n\nexport type UndoToolsOptions = {\n /** Default agent id when the caller doesn't pass one. */\n defaultAgentId?: string;\n};\n\n/**\n * Idempotent tracker so multiple bridges on the same server only register\n * agent_undo / agent_redo / agent_history once.\n */\nconst installedHosts = new WeakSet<ToolHost>();\n\n/**\n * ensureUndoToolsRegistered — bridges call this on construction. Safe to\n * call repeatedly with the same server; subsequent calls are no-ops.\n */\nexport function ensureUndoToolsRegistered(host: ToolHost, options: UndoToolsOptions = {}): void {\n if (installedHosts.has(host)) return;\n installedHosts.add(host);\n registerUndoTools(host, options);\n}\n\n/**\n * registerUndoTools — add agent_undo / agent_redo / agent_history to the\n * server. Returns a disposer that unregisters all three.\n */\nexport function registerUndoTools(host: ToolHost, options: UndoToolsOptions = {}): () => void {\n const defaultAgent = options.defaultAgentId ?? \"agent\";\n const disposers: Array<() => void> = [];\n const agentOf = (args: any): string =>\n typeof args?.agentId === \"string\" ? args.agentId : defaultAgent;\n\n disposers.push(\n host.registerTool(\n {\n name: \"agent_undo\",\n description: \"Undo the most recent action on the agent's stack. Optional agentId targets a specific agent.\",\n inputSchema: {\n type: \"object\",\n properties: { agentId: { type: \"string\" } },\n additionalProperties: false,\n },\n },\n async (args) => {\n const entry = await undoOne(agentOf(args));\n if (!entry) return errorResult(\"Nothing to undo.\");\n return textResult(`Undid: ${entry.label}`, { entry: serialize(entry) });\n },\n ),\n );\n\n disposers.push(\n host.registerTool(\n {\n name: \"agent_redo\",\n description: \"Redo the most recently undone action.\",\n inputSchema: {\n type: \"object\",\n properties: { agentId: { type: \"string\" } },\n additionalProperties: false,\n },\n },\n async (args) => {\n const entry = await redoOne(agentOf(args));\n if (!entry) return errorResult(\"Nothing to redo.\");\n return textResult(`Redid: ${entry.label}`, { entry: serialize(entry) });\n },\n ),\n );\n\n disposers.push(\n host.registerTool(\n {\n name: \"agent_history\",\n description: \"List the agent's undo stack (oldest first). Useful for understanding what's reversible.\",\n inputSchema: {\n type: \"object\",\n properties: { agentId: { type: \"string\" } },\n additionalProperties: false,\n },\n },\n async (args) => {\n const history = readHistory(agentOf(args)).map(serialize);\n const text = history.map((e) => `${new Date(e.timestamp).toISOString()} ${e.bridgeId} ${e.action}: ${e.label}`).join(\"\\n\");\n return textResult(text || \"(empty)\", history);\n },\n ),\n );\n\n return () => disposers.forEach((d) => d());\n}\n\nfunction serialize(entry: import(\"./undo-stack\").UndoEntry) {\n return {\n timestamp: entry.timestamp,\n bridgeId: entry.bridgeId,\n action: entry.action,\n label: entry.label,\n };\n}\n","import { textResult, errorResult } from \"../mcp/server\";\nimport type { ToolHost } from \"../mcp/tool-host\";\nimport type { JsonObject } from \"../mcp/types\";\nimport type { Bridge } from \"./types\";\nimport { wrapToolWithActivity } from \"../presence/wrap-tool-with-activity\";\nimport type { AgentTarget } from \"../presence/types\";\nimport { pushUndoEntry } from \"../undo/undo-stack\";\nimport { ensureUndoToolsRegistered } from \"../undo/undo-tools\";\n\n/**\n * Headless bridge for `@particle-academy/fancy-catalog` — a Stripe catalog with\n * NO UI surface. The adapter exposes the catalog's STORES + operations (not UI\n * getters/setters), and the tools are CRUD over products / prices + checkout +\n * Stripe sync. Mutations still funnel through `wrapToolWithActivity` so presence\n * + undo compose, and the destructive delete is `pendingMode`-gated.\n *\n * The adapter shapes below are STRUCTURAL mirrors of fancy-catalog's public\n * `Catalog` + store interfaces, defined LOCALLY so this bridge builds with the\n * sibling package absent (it's an optional peer). A real `Catalog` instance is\n * assignable to `CatalogBridgeAdapter` with no import — TypeScript is structural.\n */\n\n/** Minimal product shape crossing the MCP wire (mirror of fancy-catalog `Product`). */\nexport type CatalogProduct = {\n id: string;\n name: string;\n description?: string | null;\n active?: boolean;\n lookupKey?: string | null;\n externalId?: string | null;\n metadata?: Record<string, unknown> | null;\n [k: string]: unknown;\n};\n\n/** Minimal price shape crossing the MCP wire (mirror of fancy-catalog `Price`). */\nexport type CatalogPrice = {\n id: string;\n productId: string;\n active?: boolean;\n currency: string;\n unitAmount: number;\n type: \"recurring\" | \"one_time\";\n externalId?: string | null;\n [k: string]: unknown;\n};\n\n/** Common checkout args (mirror of fancy-catalog `CheckoutArgs`). */\nexport type CatalogCheckoutArgs = {\n customer?: string;\n successUrl: string;\n cancelUrl: string;\n metadata?: Record<string, string>;\n /** One-time checkouts only. */\n quantity?: number;\n};\n\n/**\n * Adapter = the catalog instance / stores. A live `Catalog` from fancy-catalog\n * satisfies this directly (`catalog.products`, `catalog.createProduct`, …); a\n * host can also hand-roll one over its own persistence.\n */\nexport type CatalogBridgeAdapter = {\n /** Stable id for this catalog instance (multiple catalogs ⇒ distinct ids). */\n id?: string;\n /** Display label for logs / presence. */\n title?: string;\n /** Optional fancy-screens screen id (usually unset — this is headless). */\n screenId?: string;\n\n /** Product store — `catalog.products`. */\n products: {\n find(id: string, opts?: { withTrashed?: boolean }): CatalogProduct | null | Promise<CatalogProduct | null>;\n all(opts?: { withTrashed?: boolean }): CatalogProduct[] | Promise<CatalogProduct[]>;\n remove(id: string): void | Promise<void>;\n };\n /** Price store — `catalog.prices`. */\n prices: {\n find(id: string, opts?: { withTrashed?: boolean }): CatalogPrice | null | Promise<CatalogPrice | null>;\n forProduct(productId: string, opts?: { withTrashed?: boolean }): CatalogPrice[] | Promise<CatalogPrice[]>;\n all(opts?: { withTrashed?: boolean }): CatalogPrice[] | Promise<CatalogPrice[]>;\n remove(id: string): void | Promise<void>;\n };\n\n /** Authoring helpers — `catalog.createProduct` / `catalog.createPrice` (ULIDs auto-assigned). */\n createProduct(input: Partial<CatalogProduct> & { name: string }): Promise<CatalogProduct> | CatalogProduct;\n createPrice(\n input: Partial<CatalogPrice> & { productId: string; currency: string; unitAmount: number; type: \"recurring\" | \"one_time\" },\n ): Promise<CatalogPrice> | CatalogPrice;\n\n /** Stripe sync — `catalog.syncProductAndPrices`. Optional (no-op when absent). */\n syncProductAndPrices?(product: CatalogProduct): Promise<CatalogProduct> | CatalogProduct;\n /** Connection test — `catalog.testConnection`. Optional. */\n testConnection?(): Promise<{ success: boolean; message: string; productCount?: number }> | { success: boolean; message: string; productCount?: number };\n\n /** Hosted Checkout — `catalog.getSubscriptionCheckoutUrl` / `getOneTimeCheckoutUrl`. Optional. */\n getSubscriptionCheckoutUrl?(price: CatalogPrice, args: CatalogCheckoutArgs): Promise<string> | string;\n getOneTimeCheckoutUrl?(price: CatalogPrice, args: CatalogCheckoutArgs): Promise<string> | string;\n};\n\nexport type CatalogBridgeOptions = {\n adapter: CatalogBridgeAdapter;\n /** Identity stamped on activity + undo entries. */\n agent?: { id: string; name?: string; color?: string };\n /**\n * Trust-but-verify. When on (default), destructive ops (`catalog_delete_product`,\n * `catalog_delete_price`) route through `adapter`-less staging: they require an\n * explicit `confirm: true` arg OR a host `confirm` callback. Read + create +\n * checkout-url tools are unaffected.\n */\n pendingMode?: boolean;\n /** Host confirm hook for destructive ops (pendingMode). Resolves true to proceed. */\n confirm?: (req: { action: string; id: string; label: string }) => Promise<boolean> | boolean;\n};\n\nconst DEFAULT_AGENT = { id: \"agent\", name: \"Agent\", color: \"#a855f7\" };\n\nconst str = (v: unknown, fallback = \"\"): string => (typeof v === \"string\" ? v : fallback);\nconst num = (v: unknown, fallback = 0): number => (typeof v === \"number\" && Number.isFinite(v) ? v : fallback);\n\n/**\n * registerCatalogBridge — full MCP tool set over a headless Stripe catalog.\n *\n * catalog_list_products list products ({ id, name, active, priceCount })\n * catalog_get_product full product JSON + its prices\n * catalog_create_product create a product (ULID auto-assigned)\n * catalog_delete_product soft-delete a product (pendingMode-gated, undoable*)\n * catalog_list_prices list a product's prices (or all)\n * catalog_create_price create a price under a product\n * catalog_delete_price soft-delete a price (pendingMode-gated)\n * catalog_sync_product push a product + its prices to Stripe\n * catalog_test_connection verify the Stripe connection\n * catalog_create_checkout build a hosted Checkout URL for a price\n *\n * *delete undo is best-effort: stores expose soft-delete (`remove`) but no\n * un-delete, so the undo closure re-creates from the captured snapshot.\n */\nexport function registerCatalogBridge(host: ToolHost, options: CatalogBridgeOptions): Bridge {\n const { adapter } = options;\n const agent = { ...DEFAULT_AGENT, ...(options.agent ?? {}) };\n const pendingMode = options.pendingMode ?? true;\n const catalogId = adapter.id ?? \"catalog\";\n const disposers: Array<() => void> = [];\n\n ensureUndoToolsRegistered(host, { defaultAgentId: agent.id });\n\n const target = (elementId?: string, label?: string): AgentTarget => ({\n kind: \"custom\",\n screenId: adapter.screenId,\n elementId,\n label: label ?? catalogId,\n });\n\n const reg = (\n name: string,\n description: string,\n properties: Record<string, unknown>,\n required: string[],\n handler: (args: JsonObject) => Promise<unknown> | unknown,\n resolveTarget: false | ((args: JsonObject) => AgentTarget),\n ) => {\n const wrapped = async (args: JsonObject) => {\n try {\n return await handler(args);\n } catch (e) {\n return errorResult(e instanceof Error ? e.message : String(e));\n }\n };\n const final = resolveTarget\n ? wrapToolWithActivity(wrapped as never, {\n toolName: name,\n agent,\n kind: \"custom\",\n screenId: adapter.screenId,\n resolveTarget: ({ args }) => resolveTarget(args as JsonObject),\n })\n : wrapped;\n disposers.push(\n host.registerTool(\n { name, description, inputSchema: { type: \"object\", properties: properties as Record<string, never>, required, additionalProperties: false } },\n final as never,\n ),\n );\n };\n\n /** Stage a destructive op behind the human (pendingMode). Returns null to proceed, or an errorResult to block. */\n const guardDestructive = async (action: string, id: string, label: string, hasConfirmArg: boolean) => {\n if (!pendingMode) return null;\n if (options.confirm) {\n const ok = await options.confirm({ action, id, label });\n return ok ? null : errorResult(`Declined: ${action} ${id} (human did not confirm).`);\n }\n // No host confirm hook → require an explicit confirm:true arg as the staged ack.\n if (!hasConfirmArg) {\n return errorResult(`${action} is staged (pendingMode). Re-call with confirm:true to apply, or wire a host confirm hook.`);\n }\n return null;\n };\n\n // ─── Read tools ──────────────────────────────────────────────────────────\n\n reg(\n \"catalog_list_products\",\n \"List products: { id, name, active, lookupKey, priceCount }. Pass withTrashed:true to include soft-deleted.\",\n { withTrashed: { type: \"boolean\" } },\n [],\n async (args) => {\n const products = await adapter.products.all({ withTrashed: args.withTrashed === true });\n const list = await Promise.all(\n products.map(async (p) => ({\n id: p.id,\n name: p.name,\n active: p.active ?? true,\n lookupKey: p.lookupKey ?? null,\n priceCount: (await adapter.prices.forProduct(p.id)).length,\n })),\n );\n return textResult(JSON.stringify(list, null, 2), list);\n },\n false,\n );\n\n reg(\n \"catalog_get_product\",\n \"Read a product's full JSON plus its prices.\",\n { id: { type: \"string\" }, withTrashed: { type: \"boolean\" } },\n [\"id\"],\n async (args) => {\n const id = str(args.id);\n const product = await adapter.products.find(id, { withTrashed: args.withTrashed === true });\n if (!product) return errorResult(`No product with id ${id}`);\n const prices = await adapter.prices.forProduct(id, { withTrashed: args.withTrashed === true });\n const out = { product, prices };\n return textResult(JSON.stringify(out, null, 2), out);\n },\n false,\n );\n\n reg(\n \"catalog_list_prices\",\n \"List prices for a product (pass productId), or every price (omit it).\",\n { productId: { type: \"string\" }, withTrashed: { type: \"boolean\" } },\n [],\n async (args) => {\n const withTrashed = args.withTrashed === true;\n const prices = args.productId !== undefined\n ? await adapter.prices.forProduct(str(args.productId), { withTrashed })\n : await adapter.prices.all({ withTrashed });\n const list = prices.map((p) => ({\n id: p.id,\n productId: p.productId,\n currency: p.currency,\n unitAmount: p.unitAmount,\n type: p.type,\n active: p.active ?? true,\n externalId: p.externalId ?? null,\n }));\n return textResult(JSON.stringify(list, null, 2), list);\n },\n false,\n );\n\n // ─── Create tools ────────────────────────────────────────────────────────\n\n reg(\n \"catalog_create_product\",\n \"Create a product. `name` is required; id (ULID) is auto-assigned. Returns the created product.\",\n {\n name: { type: \"string\" },\n description: { type: \"string\" },\n active: { type: \"boolean\" },\n lookupKey: { type: \"string\" },\n metadata: { type: \"object\" },\n },\n [\"name\"],\n async (args) => {\n const name = str(args.name);\n if (!name) return errorResult(\"name is required.\");\n const product = await adapter.createProduct({\n name,\n ...(args.description !== undefined ? { description: str(args.description) } : {}),\n ...(args.active !== undefined ? { active: args.active === true } : {}),\n ...(args.lookupKey !== undefined ? { lookupKey: str(args.lookupKey) } : {}),\n ...(args.metadata && typeof args.metadata === \"object\" ? { metadata: args.metadata as Record<string, unknown> } : {}),\n });\n pushUndoEntry(agent.id, {\n timestamp: Date.now(),\n bridgeId: catalogId,\n action: \"catalog_create_product\",\n label: `Created product ${product.id} (${product.name})`,\n undo: () => void adapter.products.remove(product.id),\n redo: () => void adapter.createProduct({ ...product }),\n });\n return textResult(`Created product ${product.id} (${product.name})`, product);\n },\n (args) => target(undefined, `create product ${str(args.name)}`),\n );\n\n reg(\n \"catalog_create_price\",\n \"Create a price under a product. unitAmount is integer minor units (cents). type is 'recurring' | 'one_time'.\",\n {\n productId: { type: \"string\" },\n currency: { type: \"string\", description: \"ISO-4217, e.g. 'USD'.\" },\n unitAmount: { type: \"number\", description: \"Price in cents.\" },\n type: { type: \"string\", enum: [\"recurring\", \"one_time\"] },\n recurringInterval: { type: \"string\", description: \"'month' | 'year' | … (recurring only).\" },\n nickname: { type: \"string\" },\n lookupKey: { type: \"string\" },\n metadata: { type: \"object\" },\n },\n [\"productId\", \"currency\", \"unitAmount\", \"type\"],\n async (args) => {\n const productId = str(args.productId);\n const product = await adapter.products.find(productId);\n if (!product) return errorResult(`No product with id ${productId}`);\n const type = str(args.type) as \"recurring\" | \"one_time\";\n if (type !== \"recurring\" && type !== \"one_time\") return errorResult(\"type must be 'recurring' or 'one_time'.\");\n const price = await adapter.createPrice({\n productId,\n currency: str(args.currency),\n unitAmount: num(args.unitAmount),\n type,\n ...(args.recurringInterval !== undefined ? { recurringInterval: str(args.recurringInterval) } : {}),\n ...(args.nickname !== undefined ? { nickname: str(args.nickname) } : {}),\n ...(args.lookupKey !== undefined ? { lookupKey: str(args.lookupKey) } : {}),\n ...(args.metadata && typeof args.metadata === \"object\" ? { metadata: args.metadata as Record<string, unknown> } : {}),\n });\n pushUndoEntry(agent.id, {\n timestamp: Date.now(),\n bridgeId: catalogId,\n action: \"catalog_create_price\",\n label: `Created price ${price.id} on ${productId}`,\n undo: () => void adapter.prices.remove(price.id),\n redo: () => void adapter.createPrice({ ...price }),\n });\n return textResult(`Created ${type} price ${price.id} on ${productId}`, price);\n },\n (args) => target(str(args.productId), `create price on ${str(args.productId)}`),\n );\n\n // ─── Destructive tools (pendingMode-gated) ───────────────────────────────\n\n reg(\n \"catalog_delete_product\",\n \"Soft-delete a product (preserves financial history). Staged in pendingMode — pass confirm:true or wire a host confirm hook.\",\n { id: { type: \"string\" }, confirm: { type: \"boolean\" } },\n [\"id\"],\n async (args) => {\n const id = str(args.id);\n const product = await adapter.products.find(id, { withTrashed: true });\n if (!product) return errorResult(`No product with id ${id}`);\n const blocked = await guardDestructive(\"catalog_delete_product\", id, product.name, args.confirm === true);\n if (blocked) return blocked;\n const snapshot = { ...product };\n await adapter.products.remove(id);\n pushUndoEntry(agent.id, {\n timestamp: Date.now(),\n bridgeId: catalogId,\n action: \"catalog_delete_product\",\n label: `Deleted product ${id} (${product.name})`,\n undo: () => void adapter.createProduct({ ...snapshot }),\n redo: () => void adapter.products.remove(id),\n });\n return textResult(`Deleted product ${id}`, { id });\n },\n (args) => target(str(args.id), `delete product ${str(args.id)}`),\n );\n\n reg(\n \"catalog_delete_price\",\n \"Soft-delete a price (mirrors Stripe archiving). Staged in pendingMode — pass confirm:true or wire a host confirm hook.\",\n { id: { type: \"string\" }, confirm: { type: \"boolean\" } },\n [\"id\"],\n async (args) => {\n const id = str(args.id);\n const price = await adapter.prices.find(id, { withTrashed: true });\n if (!price) return errorResult(`No price with id ${id}`);\n const blocked = await guardDestructive(\"catalog_delete_price\", id, id, args.confirm === true);\n if (blocked) return blocked;\n const snapshot = { ...price };\n await adapter.prices.remove(id);\n pushUndoEntry(agent.id, {\n timestamp: Date.now(),\n bridgeId: catalogId,\n action: \"catalog_delete_price\",\n label: `Deleted price ${id}`,\n undo: () => void adapter.createPrice({ ...snapshot }),\n redo: () => void adapter.prices.remove(id),\n });\n return textResult(`Deleted price ${id}`, { id });\n },\n (args) => target(str(args.id), `delete price ${str(args.id)}`),\n );\n\n // ─── Stripe sync ─────────────────────────────────────────────────────────\n\n reg(\n \"catalog_sync_product\",\n \"Push a product + its prices to Stripe (creates/updates the Stripe Product + Prices, stamps external ids).\",\n { id: { type: \"string\" } },\n [\"id\"],\n async (args) => {\n if (!adapter.syncProductAndPrices) return errorResult(\"Host did not wire Stripe sync.\");\n const id = str(args.id);\n const product = await adapter.products.find(id);\n if (!product) return errorResult(`No product with id ${id}`);\n const synced = await adapter.syncProductAndPrices(product);\n return textResult(`Synced product ${id} to Stripe (${synced.externalId ?? \"no external id\"})`, synced);\n },\n (args) => target(str(args.id), `sync product ${str(args.id)}`),\n );\n\n reg(\n \"catalog_test_connection\",\n \"Verify the Stripe connection — returns { success, message, productCount? }.\",\n {},\n [],\n async () => {\n if (!adapter.testConnection) return errorResult(\"Host did not wire a Stripe connection test.\");\n const result = await adapter.testConnection();\n return textResult(JSON.stringify(result, null, 2), result);\n },\n false,\n );\n\n // ─── Checkout ────────────────────────────────────────────────────────────\n\n reg(\n \"catalog_create_checkout\",\n \"Build a hosted Stripe Checkout URL for a price. Recurring prices → subscription; one-time → payment (pass quantity). Requires the price be synced to Stripe first.\",\n {\n priceId: { type: \"string\" },\n successUrl: { type: \"string\" },\n cancelUrl: { type: \"string\" },\n customer: { type: \"string\", description: \"Stripe customer id (optional — Checkout collects one if omitted).\" },\n quantity: { type: \"number\", description: \"One-time checkouts only. Default 1.\" },\n metadata: { type: \"object\" },\n },\n [\"priceId\", \"successUrl\", \"cancelUrl\"],\n async (args) => {\n const priceId = str(args.priceId);\n const price = await adapter.prices.find(priceId);\n if (!price) return errorResult(`No price with id ${priceId}`);\n const checkoutArgs: CatalogCheckoutArgs = {\n successUrl: str(args.successUrl),\n cancelUrl: str(args.cancelUrl),\n ...(args.customer !== undefined ? { customer: str(args.customer) } : {}),\n ...(args.metadata && typeof args.metadata === \"object\" ? { metadata: args.metadata as Record<string, string> } : {}),\n };\n let url: string;\n if (price.type === \"recurring\") {\n if (!adapter.getSubscriptionCheckoutUrl) return errorResult(\"Host did not wire subscription checkout.\");\n url = await adapter.getSubscriptionCheckoutUrl(price, checkoutArgs);\n } else {\n if (!adapter.getOneTimeCheckoutUrl) return errorResult(\"Host did not wire one-time checkout.\");\n url = await adapter.getOneTimeCheckoutUrl(price, { ...checkoutArgs, quantity: num(args.quantity, 1) });\n }\n return textResult(url || \"(no url)\", { priceId, type: price.type, url });\n },\n (args) => target(str(args.priceId), `checkout ${str(args.priceId)}`),\n );\n\n return {\n id: `catalog:${catalogId}`,\n title: adapter.title ?? \"Catalog\",\n dispose: () => {\n for (const d of disposers.splice(0)) d();\n },\n };\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/mcp/server.ts","../src/presence/wrap-tool-with-activity.ts","../src/undo/undo-tools.ts","../src/bridges/catalog.ts"],"names":["emitActivity","undoOne","redoOne","readHistory","pushUndoEntry"],"mappings":"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","file":"bridges-catalog.cjs","sourcesContent":["import {\n type CallToolResult,\n type JsonObject,\n type JsonRpcMessage,\n type JsonRpcRequest,\n type JsonRpcId,\n type RegisteredTool,\n type ServerCapabilities,\n type ServerInfo,\n type ToolDefinition,\n type ToolHandler,\n JSONRPC_INTERNAL_ERROR,\n JSONRPC_INVALID_PARAMS,\n JSONRPC_METHOD_NOT_FOUND,\n MCP_PROTOCOL_VERSION,\n} from \"./types\";\nimport { ToolRegistry } from \"./tool-host\";\n\nexport type McpServerOptions = {\n info: ServerInfo;\n /** Defaults to { tools: { listChanged: true } } */\n capabilities?: ServerCapabilities;\n /** Free-text instructions surfaced to clients during initialize. */\n instructions?: string;\n /**\n * The protocol revisions this server speaks, NEWEST FIRST.\n *\n * `initialize` echoes the client's requested revision when it is in this\n * list, and answers the first entry otherwise — the spec's rule, which leaves\n * the client to decide whether it can live with the answer.\n *\n * Defaults to `[MCP_PROTOCOL_VERSION]`: one revision, answered whatever the\n * client asks, which is exactly what this server did before the option\n * existed. Only list a revision the tools you register are correct under.\n */\n protocolVersions?: readonly string[];\n};\n\nexport type Transport = {\n /** Called by the server when it has a message to deliver to the client. */\n send: (message: JsonRpcMessage) => void;\n /** Called by the server when it's torn down so the transport can clean up. */\n close?: () => void;\n};\n\n/**\n * MicroMcpServer — protocol-level MCP server, transport-agnostic.\n *\n * Use it like:\n *\n * const server = new MicroMcpServer({ info: { name: \"session\", version: \"0.1\" } });\n * server.registerTool({ name: \"...\", inputSchema: { type: \"object\" } }, async (args) => ({...}));\n * const transport = new InProcessTransport();\n * server.attach(transport);\n * transport.deliver({ ... }); // client → server frames\n *\n * The same server can serve multiple transports (e.g. an in-process agent\n * AND a relayed external client) by attaching each one.\n */\nexport class MicroMcpServer extends ToolRegistry {\n private transports = new Set<Transport>();\n /**\n * Transports owed a `tools/list_changed` at the end of this tick. Empty when\n * none is scheduled. See {@link scheduleListChangedNotification}.\n */\n private listChangedOwed = new Set<Transport>();\n\n readonly info: ServerInfo;\n readonly capabilities: ServerCapabilities;\n readonly instructions?: string;\n readonly protocolVersions: readonly string[];\n\n constructor(options: McpServerOptions) {\n super();\n this.info = options.info;\n this.capabilities = options.capabilities ?? { tools: { listChanged: true } };\n this.instructions = options.instructions;\n if (options.protocolVersions && options.protocolVersions.length === 0) {\n // No answer exists for a client's initialize. Fail here, next to the\n // mistake, rather than in a handshake nobody is watching.\n throw new Error(\"MicroMcpServer: protocolVersions is empty — a server must speak at least one protocol revision.\");\n }\n this.protocolVersions = options.protocolVersions ? [...options.protocolVersions] : [MCP_PROTOCOL_VERSION];\n }\n\n attach(transport: Transport): () => void {\n this.transports.add(transport);\n return () => this.detach(transport);\n }\n\n detach(transport: Transport): void {\n if (this.transports.delete(transport)) {\n transport.close?.();\n }\n }\n\n unregisterTool(name: string): void {\n if (this.tools.delete(name)) {\n this.scheduleListChangedNotification();\n }\n }\n\n protected onToolsChanged(): void {\n this.scheduleListChangedNotification();\n }\n\n /**\n * Receive a JSON-RPC frame from a client (called by the transport).\n * The transport is responsible for sending the response back.\n */\n async receive(transport: Transport, message: JsonRpcMessage): Promise<void> {\n if (!(\"method\" in message)) return; // It's a response, not a request — ignore.\n\n const isNotification = !(\"id\" in message);\n if (isNotification) {\n // Notifications are fire-and-forget. We ignore unknown methods.\n return;\n }\n\n const request = message as JsonRpcRequest;\n try {\n const result = await this.handle(request, transport);\n transport.send({ jsonrpc: \"2.0\", id: request.id, result });\n } catch (err) {\n transport.send({\n jsonrpc: \"2.0\",\n id: request.id,\n error: this.toRpcError(err),\n });\n }\n }\n\n private async handle(request: JsonRpcRequest, transport: Transport): Promise<any> {\n const { method, params } = request;\n switch (method) {\n case \"initialize\":\n return {\n protocolVersion: this.negotiate(params?.protocolVersion),\n capabilities: this.capabilities,\n serverInfo: this.info,\n ...(this.instructions ? { instructions: this.instructions } : {}),\n };\n\n case \"tools/list\":\n return { tools: this.listTools() };\n\n case \"tools/call\": {\n const name = params?.name;\n const args = (params?.arguments ?? {}) as JsonObject;\n if (typeof name !== \"string\") {\n throw rpcError(JSONRPC_INVALID_PARAMS, \"tools/call requires `name`\");\n }\n const tool = this.tools.get(name);\n if (!tool) {\n throw rpcError(JSONRPC_METHOD_NOT_FOUND, this.missingToolMessage(name));\n }\n const result = await tool.handler(args, { transport });\n return result satisfies CallToolResult;\n }\n\n case \"ping\":\n return {};\n\n default:\n throw rpcError(JSONRPC_METHOD_NOT_FOUND, `Unsupported method: ${method}`);\n }\n }\n\n /** The revision to answer `initialize` with: the one asked for if spoken, else the newest. */\n private negotiate(requested: unknown): string {\n return typeof requested === \"string\" && this.protocolVersions.includes(requested)\n ? requested\n : this.protocolVersions[0];\n }\n\n /**\n * Tell the transports that SAW the old tool list that it changed.\n *\n * Changes in one tick coalesce into one notification. The recipients are the\n * transports attached at the moment of a change, not at the moment the\n * notification goes out: a transport attached afterwards never had the old\n * list, so \"your list is stale\" is noise to it — and on stdio, where a host\n * builds the server and attaches stdin/stdout in the same tick, it was the\n * first frame a client received, before it had even sent `initialize`.\n */\n private scheduleListChangedNotification(): void {\n if (this.transports.size === 0) return;\n const scheduled = this.listChangedOwed.size > 0;\n for (const t of this.transports) this.listChangedOwed.add(t);\n if (scheduled) return;\n queueMicrotask(() => {\n const owed = this.listChangedOwed;\n this.listChangedOwed = new Set();\n for (const t of owed) {\n // Detached since the change: it is not listening any more.\n if (this.transports.has(t)) t.send({ jsonrpc: \"2.0\", method: \"notifications/tools/list_changed\" });\n }\n });\n }\n\n /** Send an application notification to every client, or one attached transport. */\n notify(message: JsonRpcMessage, transport?: Transport): void {\n if (transport) transport.send(message);\n else this.broadcast(message);\n }\n\n private broadcast(message: JsonRpcMessage): void {\n for (const t of this.transports) t.send(message);\n }\n\n private toRpcError(err: unknown): { code: number; message: string; data?: any } {\n if (err && typeof err === \"object\" && \"code\" in err && \"message\" in err) {\n return err as any;\n }\n return {\n code: JSONRPC_INTERNAL_ERROR,\n message: err instanceof Error ? err.message : String(err),\n };\n }\n}\n\nexport function rpcError(code: number, message: string, data?: any) {\n return { code, message, ...(data !== undefined ? { data } : {}) };\n}\n\n/**\n * Helper to build a CallToolResult from a string or structured value.\n */\nexport function textResult(text: string, structured?: any): CallToolResult {\n return {\n content: [{ type: \"text\", text }],\n ...(structured !== undefined ? { structuredContent: structured } : {}),\n };\n}\n\nexport function errorResult(text: string): CallToolResult {\n return { content: [{ type: \"text\", text }], isError: true };\n}\n\n// Internal helper so the JsonRpcId import isn't dropped by tsup\ntype _KeepIdImport = JsonRpcId;\n","import type { CallToolResult } from \"../mcp/types\";\nimport { emitActivity } from \"./registry\";\nimport type { AgentTarget } from \"./types\";\n\nexport type ActivityAgent = { id: string; name?: string; color?: string };\n\nexport type ActivityResolverContext<TArgs = Record<string, unknown>> = {\n /** Tool name as registered. */\n toolName: string;\n /** Arguments the tool was called with. */\n args: TArgs;\n /** The CallToolResult the underlying handler produced. */\n result: CallToolResult;\n};\n\n/**\n * Resolves an `AgentTarget` for an executed tool. Bridges declare one of\n * these per registration so the wrapper knows which surface / element /\n * screen the activity belongs to.\n *\n * The resolver runs AFTER the tool handler so it can inspect the result\n * (e.g. read a newly-created item id from `structuredContent`).\n */\nexport type ActivityTargetResolver<TArgs = Record<string, unknown>> = (\n ctx: ActivityResolverContext<TArgs>,\n) => AgentTarget | null;\n\nexport type ToolHandler<TArgs = Record<string, unknown>> = (\n args: TArgs,\n) => Promise<CallToolResult> | CallToolResult;\n\n/**\n * wrapToolWithActivity — decorate a bridge tool handler so every successful\n * call emits an `AgentActivityEvent`. Returns a new handler with the same shape.\n *\n * Usage in a bridge:\n *\n * server.registerTool(\n * definition,\n * wrapToolWithActivity(\n * handler,\n * { agent, kind: \"whiteboard\", resolveTarget: ({ args }) => ({\n * kind: \"whiteboard\", elementId: args.id as string,\n * }) },\n * ),\n * );\n */\nexport function wrapToolWithActivity<TArgs = Record<string, unknown>>(\n handler: ToolHandler<TArgs>,\n options: {\n toolName: string;\n agent: ActivityAgent;\n /** Optional fancy-screens screen id this bridge is scoped to. */\n screenId?: string;\n /** Default target kind if the resolver returns one without `kind`. */\n kind: AgentTarget[\"kind\"];\n /** Per-call resolver. Return `null` to skip emitting (e.g. for read-only tools). */\n resolveTarget?: ActivityTargetResolver<TArgs>;\n /** Optional ttl override. */\n ttlMs?: number;\n /**\n * Build the `meta` broadcast to all relay peers. Defaults to the tool's full\n * `structuredContent`. Override to REDACT sensitive fields before fan-out —\n * e.g. the terminal bridge strips raw command/keystroke bytes so a command\n * line (or its secrets) is never broadcast verbatim to every peer.\n */\n buildMeta?: (result: CallToolResult) => Record<string, unknown> | undefined;\n },\n): ToolHandler<TArgs> {\n return async (args) => {\n const result = await handler(args);\n if (result.isError) return result;\n\n let target: AgentTarget | null;\n if (options.resolveTarget) {\n target = options.resolveTarget({ toolName: options.toolName, args, result });\n } else {\n target = { kind: options.kind, screenId: options.screenId };\n }\n if (!target) return result;\n\n emitActivity({\n agentId: options.agent.id,\n agentName: options.agent.name,\n agentColor: options.agent.color,\n target: { ...target, kind: target.kind ?? options.kind, screenId: target.screenId ?? options.screenId },\n action: options.toolName,\n timestamp: Date.now(),\n meta: options.buildMeta ? options.buildMeta(result) : extractMeta(result),\n ttlMs: options.ttlMs,\n });\n return result;\n };\n}\n\nfunction extractMeta(result: CallToolResult): Record<string, unknown> | undefined {\n const sc = result.structuredContent;\n if (sc && typeof sc === \"object\" && !Array.isArray(sc)) {\n return sc as Record<string, unknown>;\n }\n return undefined;\n}\n","import { textResult, errorResult } from \"../mcp/server\";\nimport type { ToolHost } from \"../mcp/tool-host\";\nimport { readHistory, redoOne, undoOne } from \"./undo-stack\";\n\nexport type UndoToolsOptions = {\n /** Default agent id when the caller doesn't pass one. */\n defaultAgentId?: string;\n};\n\n/**\n * Idempotent tracker so multiple bridges on the same server only register\n * agent_undo / agent_redo / agent_history once.\n */\nconst installedHosts = new WeakSet<ToolHost>();\n\n/**\n * The one owner every copy of the undo tools registers under. They are SHARED\n * on purpose — every bridge ensures them, and a host may also call\n * `registerUndoTools` itself — so all of those are the same registrant, and a\n * second registration replaces the first instead of being refused as a\n * collision. Anything else claiming `agent_undo` is still refused.\n */\nconst UNDO_TOOLS_OWNER = \"agent-undo\";\n\n/**\n * ensureUndoToolsRegistered — bridges call this on construction. Safe to\n * call repeatedly with the same server; subsequent calls are no-ops.\n */\nexport function ensureUndoToolsRegistered(host: ToolHost, options: UndoToolsOptions = {}): void {\n if (installedHosts.has(host)) return;\n installedHosts.add(host);\n registerUndoTools(host, options);\n}\n\n/**\n * registerUndoTools — add agent_undo / agent_redo / agent_history to the\n * server. Returns a disposer that unregisters all three.\n */\nexport function registerUndoTools(host: ToolHost, options: UndoToolsOptions = {}): () => void {\n const defaultAgent = options.defaultAgentId ?? \"agent\";\n const disposers: Array<() => void> = [];\n const agentOf = (args: any): string =>\n typeof args?.agentId === \"string\" ? args.agentId : defaultAgent;\n\n disposers.push(\n host.registerTool(\n {\n name: \"agent_undo\",\n description: \"Undo the most recent action on the agent's stack. Optional agentId targets a specific agent.\",\n inputSchema: {\n type: \"object\",\n properties: { agentId: { type: \"string\" } },\n additionalProperties: false,\n },\n },\n async (args) => {\n const entry = await undoOne(agentOf(args));\n if (!entry) return errorResult(\"Nothing to undo.\");\n return textResult(`Undid: ${entry.label}`, { entry: serialize(entry) });\n },\n { owner: UNDO_TOOLS_OWNER },\n ),\n );\n\n disposers.push(\n host.registerTool(\n {\n name: \"agent_redo\",\n description: \"Redo the most recently undone action.\",\n inputSchema: {\n type: \"object\",\n properties: { agentId: { type: \"string\" } },\n additionalProperties: false,\n },\n },\n async (args) => {\n const entry = await redoOne(agentOf(args));\n if (!entry) return errorResult(\"Nothing to redo.\");\n return textResult(`Redid: ${entry.label}`, { entry: serialize(entry) });\n },\n { owner: UNDO_TOOLS_OWNER },\n ),\n );\n\n disposers.push(\n host.registerTool(\n {\n name: \"agent_history\",\n description: \"List the agent's undo stack (oldest first). Useful for understanding what's reversible.\",\n inputSchema: {\n type: \"object\",\n properties: { agentId: { type: \"string\" } },\n additionalProperties: false,\n },\n },\n async (args) => {\n const history = readHistory(agentOf(args)).map(serialize);\n const text = history.map((e) => `${new Date(e.timestamp).toISOString()} ${e.bridgeId} ${e.action}: ${e.label}`).join(\"\\n\");\n return textResult(text || \"(empty)\", history);\n },\n { owner: UNDO_TOOLS_OWNER },\n ),\n );\n\n return () => disposers.forEach((d) => d());\n}\n\nfunction serialize(entry: import(\"./undo-stack\").UndoEntry) {\n return {\n timestamp: entry.timestamp,\n bridgeId: entry.bridgeId,\n action: entry.action,\n label: entry.label,\n };\n}\n","import { textResult, errorResult } from \"../mcp/server\";\nimport type { ToolHost } from \"../mcp/tool-host\";\nimport type { JsonObject } from \"../mcp/types\";\nimport type { Bridge } from \"./types\";\nimport { wrapToolWithActivity } from \"../presence/wrap-tool-with-activity\";\nimport type { AgentTarget } from \"../presence/types\";\nimport { pushUndoEntry } from \"../undo/undo-stack\";\nimport { ensureUndoToolsRegistered } from \"../undo/undo-tools\";\n\n/**\n * Headless bridge for `@particle-academy/fancy-catalog` — a Stripe catalog with\n * NO UI surface. The adapter exposes the catalog's STORES + operations (not UI\n * getters/setters), and the tools are CRUD over products / prices + checkout +\n * Stripe sync. Mutations still funnel through `wrapToolWithActivity` so presence\n * + undo compose, and the destructive delete is `pendingMode`-gated.\n *\n * The adapter shapes below are STRUCTURAL mirrors of fancy-catalog's public\n * `Catalog` + store interfaces, defined LOCALLY so this bridge builds with the\n * sibling package absent (it's an optional peer). A real `Catalog` instance is\n * assignable to `CatalogBridgeAdapter` with no import — TypeScript is structural.\n */\n\n/** Minimal product shape crossing the MCP wire (mirror of fancy-catalog `Product`). */\nexport type CatalogProduct = {\n id: string;\n name: string;\n description?: string | null;\n active?: boolean;\n lookupKey?: string | null;\n externalId?: string | null;\n metadata?: Record<string, unknown> | null;\n [k: string]: unknown;\n};\n\n/** Minimal price shape crossing the MCP wire (mirror of fancy-catalog `Price`). */\nexport type CatalogPrice = {\n id: string;\n productId: string;\n active?: boolean;\n currency: string;\n unitAmount: number;\n type: \"recurring\" | \"one_time\";\n externalId?: string | null;\n [k: string]: unknown;\n};\n\n/** Common checkout args (mirror of fancy-catalog `CheckoutArgs`). */\nexport type CatalogCheckoutArgs = {\n customer?: string;\n successUrl: string;\n cancelUrl: string;\n metadata?: Record<string, string>;\n /** One-time checkouts only. */\n quantity?: number;\n};\n\n/**\n * Adapter = the catalog instance / stores. A live `Catalog` from fancy-catalog\n * satisfies this directly (`catalog.products`, `catalog.createProduct`, …); a\n * host can also hand-roll one over its own persistence.\n */\nexport type CatalogBridgeAdapter = {\n /** Stable id for this catalog instance (multiple catalogs ⇒ distinct ids). */\n id?: string;\n /** Display label for logs / presence. */\n title?: string;\n /** Optional fancy-screens screen id (usually unset — this is headless). */\n screenId?: string;\n\n /** Product store — `catalog.products`. */\n products: {\n find(id: string, opts?: { withTrashed?: boolean }): CatalogProduct | null | Promise<CatalogProduct | null>;\n all(opts?: { withTrashed?: boolean }): CatalogProduct[] | Promise<CatalogProduct[]>;\n remove(id: string): void | Promise<void>;\n };\n /** Price store — `catalog.prices`. */\n prices: {\n find(id: string, opts?: { withTrashed?: boolean }): CatalogPrice | null | Promise<CatalogPrice | null>;\n forProduct(productId: string, opts?: { withTrashed?: boolean }): CatalogPrice[] | Promise<CatalogPrice[]>;\n all(opts?: { withTrashed?: boolean }): CatalogPrice[] | Promise<CatalogPrice[]>;\n remove(id: string): void | Promise<void>;\n };\n\n /** Authoring helpers — `catalog.createProduct` / `catalog.createPrice` (ULIDs auto-assigned). */\n createProduct(input: Partial<CatalogProduct> & { name: string }): Promise<CatalogProduct> | CatalogProduct;\n createPrice(\n input: Partial<CatalogPrice> & { productId: string; currency: string; unitAmount: number; type: \"recurring\" | \"one_time\" },\n ): Promise<CatalogPrice> | CatalogPrice;\n\n /** Stripe sync — `catalog.syncProductAndPrices`. Optional (no-op when absent). */\n syncProductAndPrices?(product: CatalogProduct): Promise<CatalogProduct> | CatalogProduct;\n /** Connection test — `catalog.testConnection`. Optional. */\n testConnection?(): Promise<{ success: boolean; message: string; productCount?: number }> | { success: boolean; message: string; productCount?: number };\n\n /** Hosted Checkout — `catalog.getSubscriptionCheckoutUrl` / `getOneTimeCheckoutUrl`. Optional. */\n getSubscriptionCheckoutUrl?(price: CatalogPrice, args: CatalogCheckoutArgs): Promise<string> | string;\n getOneTimeCheckoutUrl?(price: CatalogPrice, args: CatalogCheckoutArgs): Promise<string> | string;\n};\n\nexport type CatalogBridgeOptions = {\n adapter: CatalogBridgeAdapter;\n /** Identity stamped on activity + undo entries. */\n agent?: { id: string; name?: string; color?: string };\n /**\n * Trust-but-verify. When on (default), destructive ops (`catalog_delete_product`,\n * `catalog_delete_price`) route through `adapter`-less staging: they require an\n * explicit `confirm: true` arg OR a host `confirm` callback. Read + create +\n * checkout-url tools are unaffected.\n */\n pendingMode?: boolean;\n /** Host confirm hook for destructive ops (pendingMode). Resolves true to proceed. */\n confirm?: (req: { action: string; id: string; label: string }) => Promise<boolean> | boolean;\n};\n\nconst DEFAULT_AGENT = { id: \"agent\", name: \"Agent\", color: \"#a855f7\" };\n\nconst str = (v: unknown, fallback = \"\"): string => (typeof v === \"string\" ? v : fallback);\nconst num = (v: unknown, fallback = 0): number => (typeof v === \"number\" && Number.isFinite(v) ? v : fallback);\n\n/**\n * registerCatalogBridge — full MCP tool set over a headless Stripe catalog.\n *\n * catalog_list_products list products ({ id, name, active, priceCount })\n * catalog_get_product full product JSON + its prices\n * catalog_create_product create a product (ULID auto-assigned)\n * catalog_delete_product soft-delete a product (pendingMode-gated, undoable*)\n * catalog_list_prices list a product's prices (or all)\n * catalog_create_price create a price under a product\n * catalog_delete_price soft-delete a price (pendingMode-gated)\n * catalog_sync_product push a product + its prices to Stripe\n * catalog_test_connection verify the Stripe connection\n * catalog_create_checkout build a hosted Checkout URL for a price\n *\n * *delete undo is best-effort: stores expose soft-delete (`remove`) but no\n * un-delete, so the undo closure re-creates from the captured snapshot.\n */\nexport function registerCatalogBridge(host: ToolHost, options: CatalogBridgeOptions): Bridge {\n const { adapter } = options;\n const agent = { ...DEFAULT_AGENT, ...(options.agent ?? {}) };\n const pendingMode = options.pendingMode ?? true;\n const catalogId = adapter.id ?? \"catalog\";\n const disposers: Array<() => void> = [];\n // The bridge id is also its registrant identity on the host: the same bridge\n // may re-register (a remount), a different one claiming a name is refused.\n const bridgeId = `catalog:${catalogId}`;\n\n ensureUndoToolsRegistered(host, { defaultAgentId: agent.id });\n\n const target = (elementId?: string, label?: string): AgentTarget => ({\n kind: \"custom\",\n screenId: adapter.screenId,\n elementId,\n label: label ?? catalogId,\n });\n\n const reg = (\n name: string,\n description: string,\n properties: Record<string, unknown>,\n required: string[],\n handler: (args: JsonObject) => Promise<unknown> | unknown,\n resolveTarget: false | ((args: JsonObject) => AgentTarget),\n ) => {\n const wrapped = async (args: JsonObject) => {\n try {\n return await handler(args);\n } catch (e) {\n return errorResult(e instanceof Error ? e.message : String(e));\n }\n };\n const final = resolveTarget\n ? wrapToolWithActivity(wrapped as never, {\n toolName: name,\n agent,\n kind: \"custom\",\n screenId: adapter.screenId,\n resolveTarget: ({ args }) => resolveTarget(args as JsonObject),\n })\n : wrapped;\n disposers.push(\n host.registerTool(\n { name, description, inputSchema: { type: \"object\", properties: properties as Record<string, never>, required, additionalProperties: false } },\n final as never,\n { owner: bridgeId },\n ),\n );\n };\n\n /** Stage a destructive op behind the human (pendingMode). Returns null to proceed, or an errorResult to block. */\n const guardDestructive = async (action: string, id: string, label: string, hasConfirmArg: boolean) => {\n if (!pendingMode) return null;\n if (options.confirm) {\n const ok = await options.confirm({ action, id, label });\n return ok ? null : errorResult(`Declined: ${action} ${id} (human did not confirm).`);\n }\n // No host confirm hook → require an explicit confirm:true arg as the staged ack.\n if (!hasConfirmArg) {\n return errorResult(`${action} is staged (pendingMode). Re-call with confirm:true to apply, or wire a host confirm hook.`);\n }\n return null;\n };\n\n // ─── Read tools ──────────────────────────────────────────────────────────\n\n reg(\n \"catalog_list_products\",\n \"List products: { id, name, active, lookupKey, priceCount }. Pass withTrashed:true to include soft-deleted.\",\n { withTrashed: { type: \"boolean\" } },\n [],\n async (args) => {\n const products = await adapter.products.all({ withTrashed: args.withTrashed === true });\n const list = await Promise.all(\n products.map(async (p) => ({\n id: p.id,\n name: p.name,\n active: p.active ?? true,\n lookupKey: p.lookupKey ?? null,\n priceCount: (await adapter.prices.forProduct(p.id)).length,\n })),\n );\n return textResult(JSON.stringify(list, null, 2), list);\n },\n false,\n );\n\n reg(\n \"catalog_get_product\",\n \"Read a product's full JSON plus its prices.\",\n { id: { type: \"string\" }, withTrashed: { type: \"boolean\" } },\n [\"id\"],\n async (args) => {\n const id = str(args.id);\n const product = await adapter.products.find(id, { withTrashed: args.withTrashed === true });\n if (!product) return errorResult(`No product with id ${id}`);\n const prices = await adapter.prices.forProduct(id, { withTrashed: args.withTrashed === true });\n const out = { product, prices };\n return textResult(JSON.stringify(out, null, 2), out);\n },\n false,\n );\n\n reg(\n \"catalog_list_prices\",\n \"List prices for a product (pass productId), or every price (omit it).\",\n { productId: { type: \"string\" }, withTrashed: { type: \"boolean\" } },\n [],\n async (args) => {\n const withTrashed = args.withTrashed === true;\n const prices = args.productId !== undefined\n ? await adapter.prices.forProduct(str(args.productId), { withTrashed })\n : await adapter.prices.all({ withTrashed });\n const list = prices.map((p) => ({\n id: p.id,\n productId: p.productId,\n currency: p.currency,\n unitAmount: p.unitAmount,\n type: p.type,\n active: p.active ?? true,\n externalId: p.externalId ?? null,\n }));\n return textResult(JSON.stringify(list, null, 2), list);\n },\n false,\n );\n\n // ─── Create tools ────────────────────────────────────────────────────────\n\n reg(\n \"catalog_create_product\",\n \"Create a product. `name` is required; id (ULID) is auto-assigned. Returns the created product.\",\n {\n name: { type: \"string\" },\n description: { type: \"string\" },\n active: { type: \"boolean\" },\n lookupKey: { type: \"string\" },\n metadata: { type: \"object\" },\n },\n [\"name\"],\n async (args) => {\n const name = str(args.name);\n if (!name) return errorResult(\"name is required.\");\n const product = await adapter.createProduct({\n name,\n ...(args.description !== undefined ? { description: str(args.description) } : {}),\n ...(args.active !== undefined ? { active: args.active === true } : {}),\n ...(args.lookupKey !== undefined ? { lookupKey: str(args.lookupKey) } : {}),\n ...(args.metadata && typeof args.metadata === \"object\" ? { metadata: args.metadata as Record<string, unknown> } : {}),\n });\n pushUndoEntry(agent.id, {\n timestamp: Date.now(),\n bridgeId: catalogId,\n action: \"catalog_create_product\",\n label: `Created product ${product.id} (${product.name})`,\n undo: async () => { await adapter.products.remove(product.id); },\n redo: async () => { await adapter.createProduct({ ...product }); },\n });\n return textResult(`Created product ${product.id} (${product.name})`, product);\n },\n (args) => target(undefined, `create product ${str(args.name)}`),\n );\n\n reg(\n \"catalog_create_price\",\n \"Create a price under a product. unitAmount is integer minor units (cents). type is 'recurring' | 'one_time'.\",\n {\n productId: { type: \"string\" },\n currency: { type: \"string\", description: \"ISO-4217, e.g. 'USD'.\" },\n unitAmount: { type: \"number\", description: \"Price in cents.\" },\n type: { type: \"string\", enum: [\"recurring\", \"one_time\"] },\n recurringInterval: { type: \"string\", description: \"'month' | 'year' | … (recurring only).\" },\n nickname: { type: \"string\" },\n lookupKey: { type: \"string\" },\n metadata: { type: \"object\" },\n },\n [\"productId\", \"currency\", \"unitAmount\", \"type\"],\n async (args) => {\n const productId = str(args.productId);\n const product = await adapter.products.find(productId);\n if (!product) return errorResult(`No product with id ${productId}`);\n const type = str(args.type) as \"recurring\" | \"one_time\";\n if (type !== \"recurring\" && type !== \"one_time\") return errorResult(\"type must be 'recurring' or 'one_time'.\");\n const price = await adapter.createPrice({\n productId,\n currency: str(args.currency),\n unitAmount: num(args.unitAmount),\n type,\n ...(args.recurringInterval !== undefined ? { recurringInterval: str(args.recurringInterval) } : {}),\n ...(args.nickname !== undefined ? { nickname: str(args.nickname) } : {}),\n ...(args.lookupKey !== undefined ? { lookupKey: str(args.lookupKey) } : {}),\n ...(args.metadata && typeof args.metadata === \"object\" ? { metadata: args.metadata as Record<string, unknown> } : {}),\n });\n pushUndoEntry(agent.id, {\n timestamp: Date.now(),\n bridgeId: catalogId,\n action: \"catalog_create_price\",\n label: `Created price ${price.id} on ${productId}`,\n undo: async () => { await adapter.prices.remove(price.id); },\n redo: async () => { await adapter.createPrice({ ...price }); },\n });\n return textResult(`Created ${type} price ${price.id} on ${productId}`, price);\n },\n (args) => target(str(args.productId), `create price on ${str(args.productId)}`),\n );\n\n // ─── Destructive tools (pendingMode-gated) ───────────────────────────────\n\n reg(\n \"catalog_delete_product\",\n \"Soft-delete a product (preserves financial history). Staged in pendingMode — pass confirm:true or wire a host confirm hook.\",\n { id: { type: \"string\" }, confirm: { type: \"boolean\" } },\n [\"id\"],\n async (args) => {\n const id = str(args.id);\n const product = await adapter.products.find(id, { withTrashed: true });\n if (!product) return errorResult(`No product with id ${id}`);\n const blocked = await guardDestructive(\"catalog_delete_product\", id, product.name, args.confirm === true);\n if (blocked) return blocked;\n const snapshot = { ...product };\n await adapter.products.remove(id);\n pushUndoEntry(agent.id, {\n timestamp: Date.now(),\n bridgeId: catalogId,\n action: \"catalog_delete_product\",\n label: `Deleted product ${id} (${product.name})`,\n undo: async () => { await adapter.createProduct({ ...snapshot }); },\n redo: async () => { await adapter.products.remove(id); },\n });\n return textResult(`Deleted product ${id}`, { id });\n },\n (args) => target(str(args.id), `delete product ${str(args.id)}`),\n );\n\n reg(\n \"catalog_delete_price\",\n \"Soft-delete a price (mirrors Stripe archiving). Staged in pendingMode — pass confirm:true or wire a host confirm hook.\",\n { id: { type: \"string\" }, confirm: { type: \"boolean\" } },\n [\"id\"],\n async (args) => {\n const id = str(args.id);\n const price = await adapter.prices.find(id, { withTrashed: true });\n if (!price) return errorResult(`No price with id ${id}`);\n const blocked = await guardDestructive(\"catalog_delete_price\", id, id, args.confirm === true);\n if (blocked) return blocked;\n const snapshot = { ...price };\n await adapter.prices.remove(id);\n pushUndoEntry(agent.id, {\n timestamp: Date.now(),\n bridgeId: catalogId,\n action: \"catalog_delete_price\",\n label: `Deleted price ${id}`,\n undo: async () => { await adapter.createPrice({ ...snapshot }); },\n redo: async () => { await adapter.prices.remove(id); },\n });\n return textResult(`Deleted price ${id}`, { id });\n },\n (args) => target(str(args.id), `delete price ${str(args.id)}`),\n );\n\n // ─── Stripe sync ─────────────────────────────────────────────────────────\n\n reg(\n \"catalog_sync_product\",\n \"Push a product + its prices to Stripe (creates/updates the Stripe Product + Prices, stamps external ids).\",\n { id: { type: \"string\" } },\n [\"id\"],\n async (args) => {\n if (!adapter.syncProductAndPrices) return errorResult(\"Host did not wire Stripe sync.\");\n const id = str(args.id);\n const product = await adapter.products.find(id);\n if (!product) return errorResult(`No product with id ${id}`);\n const synced = await adapter.syncProductAndPrices(product);\n return textResult(`Synced product ${id} to Stripe (${synced.externalId ?? \"no external id\"})`, synced);\n },\n (args) => target(str(args.id), `sync product ${str(args.id)}`),\n );\n\n reg(\n \"catalog_test_connection\",\n \"Verify the Stripe connection — returns { success, message, productCount? }.\",\n {},\n [],\n async () => {\n if (!adapter.testConnection) return errorResult(\"Host did not wire a Stripe connection test.\");\n const result = await adapter.testConnection();\n return textResult(JSON.stringify(result, null, 2), result);\n },\n false,\n );\n\n // ─── Checkout ────────────────────────────────────────────────────────────\n\n reg(\n \"catalog_create_checkout\",\n \"Build a hosted Stripe Checkout URL for a price. Recurring prices → subscription; one-time → payment (pass quantity). Requires the price be synced to Stripe first.\",\n {\n priceId: { type: \"string\" },\n successUrl: { type: \"string\" },\n cancelUrl: { type: \"string\" },\n customer: { type: \"string\", description: \"Stripe customer id (optional — Checkout collects one if omitted).\" },\n quantity: { type: \"number\", description: \"One-time checkouts only. Default 1.\" },\n metadata: { type: \"object\" },\n },\n [\"priceId\", \"successUrl\", \"cancelUrl\"],\n async (args) => {\n const priceId = str(args.priceId);\n const price = await adapter.prices.find(priceId);\n if (!price) return errorResult(`No price with id ${priceId}`);\n const checkoutArgs: CatalogCheckoutArgs = {\n successUrl: str(args.successUrl),\n cancelUrl: str(args.cancelUrl),\n ...(args.customer !== undefined ? { customer: str(args.customer) } : {}),\n ...(args.metadata && typeof args.metadata === \"object\" ? { metadata: args.metadata as Record<string, string> } : {}),\n };\n let url: string;\n if (price.type === \"recurring\") {\n if (!adapter.getSubscriptionCheckoutUrl) return errorResult(\"Host did not wire subscription checkout.\");\n url = await adapter.getSubscriptionCheckoutUrl(price, checkoutArgs);\n } else {\n if (!adapter.getOneTimeCheckoutUrl) return errorResult(\"Host did not wire one-time checkout.\");\n url = await adapter.getOneTimeCheckoutUrl(price, { ...checkoutArgs, quantity: num(args.quantity, 1) });\n }\n return textResult(url || \"(no url)\", { priceId, type: price.type, url });\n },\n (args) => target(str(args.priceId), `checkout ${str(args.priceId)}`),\n );\n\n return {\n id: bridgeId,\n title: adapter.title ?? \"Catalog\",\n dispose: () => {\n for (const d of disposers.splice(0)) d();\n },\n };\n}\n"]}
|
package/dist/bridges-catalog.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
export { registerCatalogBridge } from './chunk-
|
|
2
|
-
import './chunk-
|
|
1
|
+
export { registerCatalogBridge } from './chunk-CI5ZVHDY.js';
|
|
2
|
+
import './chunk-ZDKYKJFH.js';
|
|
3
3
|
import './chunk-2VENWGLZ.js';
|
|
4
4
|
import './chunk-C3TYI5TJ.js';
|
|
5
|
-
import './chunk-
|
|
5
|
+
import './chunk-3GFKC6OK.js';
|
|
6
6
|
//# sourceMappingURL=bridges-catalog.js.map
|
|
7
7
|
//# sourceMappingURL=bridges-catalog.js.map
|
package/dist/bridges-charts.cjs
CHANGED
|
@@ -48,6 +48,7 @@ function extractMeta(result) {
|
|
|
48
48
|
|
|
49
49
|
// src/undo/undo-tools.ts
|
|
50
50
|
var installedHosts = /* @__PURE__ */ new WeakSet();
|
|
51
|
+
var UNDO_TOOLS_OWNER = "agent-undo";
|
|
51
52
|
function ensureUndoToolsRegistered(host, options = {}) {
|
|
52
53
|
if (installedHosts.has(host)) return;
|
|
53
54
|
installedHosts.add(host);
|
|
@@ -72,7 +73,8 @@ function registerUndoTools(host, options = {}) {
|
|
|
72
73
|
const entry = await fancyAutoCommon.undoOne(agentOf(args));
|
|
73
74
|
if (!entry) return errorResult("Nothing to undo.");
|
|
74
75
|
return textResult(`Undid: ${entry.label}`, { entry: serialize(entry) });
|
|
75
|
-
}
|
|
76
|
+
},
|
|
77
|
+
{ owner: UNDO_TOOLS_OWNER }
|
|
76
78
|
)
|
|
77
79
|
);
|
|
78
80
|
disposers.push(
|
|
@@ -90,7 +92,8 @@ function registerUndoTools(host, options = {}) {
|
|
|
90
92
|
const entry = await fancyAutoCommon.redoOne(agentOf(args));
|
|
91
93
|
if (!entry) return errorResult("Nothing to redo.");
|
|
92
94
|
return textResult(`Redid: ${entry.label}`, { entry: serialize(entry) });
|
|
93
|
-
}
|
|
95
|
+
},
|
|
96
|
+
{ owner: UNDO_TOOLS_OWNER }
|
|
94
97
|
)
|
|
95
98
|
);
|
|
96
99
|
disposers.push(
|
|
@@ -108,7 +111,8 @@ function registerUndoTools(host, options = {}) {
|
|
|
108
111
|
const history = fancyAutoCommon.readHistory(agentOf(args)).map(serialize);
|
|
109
112
|
const text = history.map((e) => `${new Date(e.timestamp).toISOString()} ${e.bridgeId} ${e.action}: ${e.label}`).join("\n");
|
|
110
113
|
return textResult(text || "(empty)", history);
|
|
111
|
-
}
|
|
114
|
+
},
|
|
115
|
+
{ owner: UNDO_TOOLS_OWNER }
|
|
112
116
|
)
|
|
113
117
|
);
|
|
114
118
|
return () => disposers.forEach((d) => d());
|
|
@@ -128,6 +132,7 @@ function registerChartsBridge(host, options) {
|
|
|
128
132
|
const { adapter } = options;
|
|
129
133
|
const agent = { ...DEFAULT_AGENT, ...options.agent ?? {} };
|
|
130
134
|
const disposers = [];
|
|
135
|
+
const bridgeId = `chart:${adapter.id}`;
|
|
131
136
|
ensureUndoToolsRegistered(host, { defaultAgentId: agent.id });
|
|
132
137
|
const target = {
|
|
133
138
|
kind: "chart",
|
|
@@ -153,7 +158,8 @@ function registerChartsBridge(host, options) {
|
|
|
153
158
|
disposers.push(
|
|
154
159
|
host.registerTool(
|
|
155
160
|
{ name, description, inputSchema: { type: "object", properties, required, additionalProperties: false } },
|
|
156
|
-
final
|
|
161
|
+
final,
|
|
162
|
+
{ owner: bridgeId }
|
|
157
163
|
)
|
|
158
164
|
);
|
|
159
165
|
};
|
|
@@ -229,7 +235,7 @@ function registerChartsBridge(host, options) {
|
|
|
229
235
|
true
|
|
230
236
|
);
|
|
231
237
|
return {
|
|
232
|
-
id:
|
|
238
|
+
id: bridgeId,
|
|
233
239
|
title: adapter.title ?? adapter.id,
|
|
234
240
|
dispose: () => {
|
|
235
241
|
for (const d of disposers) d();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/mcp/server.ts","../src/presence/wrap-tool-with-activity.ts","../src/undo/undo-tools.ts","../src/bridges/charts.ts"],"names":["emitActivity","undoOne","redoOne","readHistory"],"mappings":"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","file":"bridges-charts.cjs","sourcesContent":["import {\n type CallToolResult,\n type JsonObject,\n type JsonRpcMessage,\n type JsonRpcRequest,\n type JsonRpcId,\n type RegisteredTool,\n type ServerCapabilities,\n type ServerInfo,\n type ToolDefinition,\n type ToolHandler,\n JSONRPC_INTERNAL_ERROR,\n JSONRPC_INVALID_PARAMS,\n JSONRPC_METHOD_NOT_FOUND,\n MCP_PROTOCOL_VERSION,\n} from \"./types\";\nimport { ToolRegistry } from \"./tool-host\";\n\nexport type McpServerOptions = {\n info: ServerInfo;\n /** Defaults to { tools: { listChanged: true } } */\n capabilities?: ServerCapabilities;\n /** Free-text instructions surfaced to clients during initialize. */\n instructions?: string;\n /**\n * The protocol revisions this server speaks, NEWEST FIRST.\n *\n * `initialize` echoes the client's requested revision when it is in this\n * list, and answers the first entry otherwise — the spec's rule, which leaves\n * the client to decide whether it can live with the answer.\n *\n * Defaults to `[MCP_PROTOCOL_VERSION]`: one revision, answered whatever the\n * client asks, which is exactly what this server did before the option\n * existed. Only list a revision the tools you register are correct under.\n */\n protocolVersions?: readonly string[];\n};\n\nexport type Transport = {\n /** Called by the server when it has a message to deliver to the client. */\n send: (message: JsonRpcMessage) => void;\n /** Called by the server when it's torn down so the transport can clean up. */\n close?: () => void;\n};\n\n/**\n * MicroMcpServer — protocol-level MCP server, transport-agnostic.\n *\n * Use it like:\n *\n * const server = new MicroMcpServer({ info: { name: \"session\", version: \"0.1\" } });\n * server.registerTool({ name: \"...\", inputSchema: { type: \"object\" } }, async (args) => ({...}));\n * const transport = new InProcessTransport();\n * server.attach(transport);\n * transport.deliver({ ... }); // client → server frames\n *\n * The same server can serve multiple transports (e.g. an in-process agent\n * AND a relayed external client) by attaching each one.\n */\nexport class MicroMcpServer extends ToolRegistry {\n private transports = new Set<Transport>();\n /**\n * Transports owed a `tools/list_changed` at the end of this tick. Empty when\n * none is scheduled. See {@link scheduleListChangedNotification}.\n */\n private listChangedOwed = new Set<Transport>();\n\n readonly info: ServerInfo;\n readonly capabilities: ServerCapabilities;\n readonly instructions?: string;\n readonly protocolVersions: readonly string[];\n\n constructor(options: McpServerOptions) {\n super();\n this.info = options.info;\n this.capabilities = options.capabilities ?? { tools: { listChanged: true } };\n this.instructions = options.instructions;\n if (options.protocolVersions && options.protocolVersions.length === 0) {\n // No answer exists for a client's initialize. Fail here, next to the\n // mistake, rather than in a handshake nobody is watching.\n throw new Error(\"MicroMcpServer: protocolVersions is empty — a server must speak at least one protocol revision.\");\n }\n this.protocolVersions = options.protocolVersions ? [...options.protocolVersions] : [MCP_PROTOCOL_VERSION];\n }\n\n attach(transport: Transport): () => void {\n this.transports.add(transport);\n return () => this.detach(transport);\n }\n\n detach(transport: Transport): void {\n if (this.transports.delete(transport)) {\n transport.close?.();\n }\n }\n\n unregisterTool(name: string): void {\n if (this.tools.delete(name)) {\n this.scheduleListChangedNotification();\n }\n }\n\n protected onToolsChanged(): void {\n this.scheduleListChangedNotification();\n }\n\n /**\n * Receive a JSON-RPC frame from a client (called by the transport).\n * The transport is responsible for sending the response back.\n */\n async receive(transport: Transport, message: JsonRpcMessage): Promise<void> {\n if (!(\"method\" in message)) return; // It's a response, not a request — ignore.\n\n const isNotification = !(\"id\" in message);\n if (isNotification) {\n // Notifications are fire-and-forget. We ignore unknown methods.\n return;\n }\n\n const request = message as JsonRpcRequest;\n try {\n const result = await this.handle(request, transport);\n transport.send({ jsonrpc: \"2.0\", id: request.id, result });\n } catch (err) {\n transport.send({\n jsonrpc: \"2.0\",\n id: request.id,\n error: this.toRpcError(err),\n });\n }\n }\n\n private async handle(request: JsonRpcRequest, transport: Transport): Promise<any> {\n const { method, params } = request;\n switch (method) {\n case \"initialize\":\n return {\n protocolVersion: this.negotiate(params?.protocolVersion),\n capabilities: this.capabilities,\n serverInfo: this.info,\n ...(this.instructions ? { instructions: this.instructions } : {}),\n };\n\n case \"tools/list\":\n return { tools: this.listTools() };\n\n case \"tools/call\": {\n const name = params?.name;\n const args = (params?.arguments ?? {}) as JsonObject;\n if (typeof name !== \"string\") {\n throw rpcError(JSONRPC_INVALID_PARAMS, \"tools/call requires `name`\");\n }\n const tool = this.tools.get(name);\n if (!tool) {\n throw rpcError(JSONRPC_METHOD_NOT_FOUND, this.missingToolMessage(name));\n }\n const result = await tool.handler(args, { transport });\n return result satisfies CallToolResult;\n }\n\n case \"ping\":\n return {};\n\n default:\n throw rpcError(JSONRPC_METHOD_NOT_FOUND, `Unsupported method: ${method}`);\n }\n }\n\n /** The revision to answer `initialize` with: the one asked for if spoken, else the newest. */\n private negotiate(requested: unknown): string {\n return typeof requested === \"string\" && this.protocolVersions.includes(requested)\n ? requested\n : this.protocolVersions[0];\n }\n\n /**\n * Tell the transports that SAW the old tool list that it changed.\n *\n * Changes in one tick coalesce into one notification. The recipients are the\n * transports attached at the moment of a change, not at the moment the\n * notification goes out: a transport attached afterwards never had the old\n * list, so \"your list is stale\" is noise to it — and on stdio, where a host\n * builds the server and attaches stdin/stdout in the same tick, it was the\n * first frame a client received, before it had even sent `initialize`.\n */\n private scheduleListChangedNotification(): void {\n if (this.transports.size === 0) return;\n const scheduled = this.listChangedOwed.size > 0;\n for (const t of this.transports) this.listChangedOwed.add(t);\n if (scheduled) return;\n queueMicrotask(() => {\n const owed = this.listChangedOwed;\n this.listChangedOwed = new Set();\n for (const t of owed) {\n // Detached since the change: it is not listening any more.\n if (this.transports.has(t)) t.send({ jsonrpc: \"2.0\", method: \"notifications/tools/list_changed\" });\n }\n });\n }\n\n /** Send an application notification to every client, or one attached transport. */\n notify(message: JsonRpcMessage, transport?: Transport): void {\n if (transport) transport.send(message);\n else this.broadcast(message);\n }\n\n private broadcast(message: JsonRpcMessage): void {\n for (const t of this.transports) t.send(message);\n }\n\n private toRpcError(err: unknown): { code: number; message: string; data?: any } {\n if (err && typeof err === \"object\" && \"code\" in err && \"message\" in err) {\n return err as any;\n }\n return {\n code: JSONRPC_INTERNAL_ERROR,\n message: err instanceof Error ? err.message : String(err),\n };\n }\n}\n\nexport function rpcError(code: number, message: string, data?: any) {\n return { code, message, ...(data !== undefined ? { data } : {}) };\n}\n\n/**\n * Helper to build a CallToolResult from a string or structured value.\n */\nexport function textResult(text: string, structured?: any): CallToolResult {\n return {\n content: [{ type: \"text\", text }],\n ...(structured !== undefined ? { structuredContent: structured } : {}),\n };\n}\n\nexport function errorResult(text: string): CallToolResult {\n return { content: [{ type: \"text\", text }], isError: true };\n}\n\n// Internal helper so the JsonRpcId import isn't dropped by tsup\ntype _KeepIdImport = JsonRpcId;\n","import type { CallToolResult } from \"../mcp/types\";\nimport { emitActivity } from \"./registry\";\nimport type { AgentTarget } from \"./types\";\n\nexport type ActivityAgent = { id: string; name?: string; color?: string };\n\nexport type ActivityResolverContext<TArgs = Record<string, unknown>> = {\n /** Tool name as registered. */\n toolName: string;\n /** Arguments the tool was called with. */\n args: TArgs;\n /** The CallToolResult the underlying handler produced. */\n result: CallToolResult;\n};\n\n/**\n * Resolves an `AgentTarget` for an executed tool. Bridges declare one of\n * these per registration so the wrapper knows which surface / element /\n * screen the activity belongs to.\n *\n * The resolver runs AFTER the tool handler so it can inspect the result\n * (e.g. read a newly-created item id from `structuredContent`).\n */\nexport type ActivityTargetResolver<TArgs = Record<string, unknown>> = (\n ctx: ActivityResolverContext<TArgs>,\n) => AgentTarget | null;\n\nexport type ToolHandler<TArgs = Record<string, unknown>> = (\n args: TArgs,\n) => Promise<CallToolResult> | CallToolResult;\n\n/**\n * wrapToolWithActivity — decorate a bridge tool handler so every successful\n * call emits an `AgentActivityEvent`. Returns a new handler with the same shape.\n *\n * Usage in a bridge:\n *\n * server.registerTool(\n * definition,\n * wrapToolWithActivity(\n * handler,\n * { agent, kind: \"whiteboard\", resolveTarget: ({ args }) => ({\n * kind: \"whiteboard\", elementId: args.id as string,\n * }) },\n * ),\n * );\n */\nexport function wrapToolWithActivity<TArgs = Record<string, unknown>>(\n handler: ToolHandler<TArgs>,\n options: {\n toolName: string;\n agent: ActivityAgent;\n /** Optional fancy-screens screen id this bridge is scoped to. */\n screenId?: string;\n /** Default target kind if the resolver returns one without `kind`. */\n kind: AgentTarget[\"kind\"];\n /** Per-call resolver. Return `null` to skip emitting (e.g. for read-only tools). */\n resolveTarget?: ActivityTargetResolver<TArgs>;\n /** Optional ttl override. */\n ttlMs?: number;\n /**\n * Build the `meta` broadcast to all relay peers. Defaults to the tool's full\n * `structuredContent`. Override to REDACT sensitive fields before fan-out —\n * e.g. the terminal bridge strips raw command/keystroke bytes so a command\n * line (or its secrets) is never broadcast verbatim to every peer.\n */\n buildMeta?: (result: CallToolResult) => Record<string, unknown> | undefined;\n },\n): ToolHandler<TArgs> {\n return async (args) => {\n const result = await handler(args);\n if (result.isError) return result;\n\n let target: AgentTarget | null;\n if (options.resolveTarget) {\n target = options.resolveTarget({ toolName: options.toolName, args, result });\n } else {\n target = { kind: options.kind, screenId: options.screenId };\n }\n if (!target) return result;\n\n emitActivity({\n agentId: options.agent.id,\n agentName: options.agent.name,\n agentColor: options.agent.color,\n target: { ...target, kind: target.kind ?? options.kind, screenId: target.screenId ?? options.screenId },\n action: options.toolName,\n timestamp: Date.now(),\n meta: options.buildMeta ? options.buildMeta(result) : extractMeta(result),\n ttlMs: options.ttlMs,\n });\n return result;\n };\n}\n\nfunction extractMeta(result: CallToolResult): Record<string, unknown> | undefined {\n const sc = result.structuredContent;\n if (sc && typeof sc === \"object\" && !Array.isArray(sc)) {\n return sc as Record<string, unknown>;\n }\n return undefined;\n}\n","import { textResult, errorResult } from \"../mcp/server\";\nimport type { ToolHost } from \"../mcp/tool-host\";\nimport { readHistory, redoOne, undoOne } from \"./undo-stack\";\n\nexport type UndoToolsOptions = {\n /** Default agent id when the caller doesn't pass one. */\n defaultAgentId?: string;\n};\n\n/**\n * Idempotent tracker so multiple bridges on the same server only register\n * agent_undo / agent_redo / agent_history once.\n */\nconst installedHosts = new WeakSet<ToolHost>();\n\n/**\n * ensureUndoToolsRegistered — bridges call this on construction. Safe to\n * call repeatedly with the same server; subsequent calls are no-ops.\n */\nexport function ensureUndoToolsRegistered(host: ToolHost, options: UndoToolsOptions = {}): void {\n if (installedHosts.has(host)) return;\n installedHosts.add(host);\n registerUndoTools(host, options);\n}\n\n/**\n * registerUndoTools — add agent_undo / agent_redo / agent_history to the\n * server. Returns a disposer that unregisters all three.\n */\nexport function registerUndoTools(host: ToolHost, options: UndoToolsOptions = {}): () => void {\n const defaultAgent = options.defaultAgentId ?? \"agent\";\n const disposers: Array<() => void> = [];\n const agentOf = (args: any): string =>\n typeof args?.agentId === \"string\" ? args.agentId : defaultAgent;\n\n disposers.push(\n host.registerTool(\n {\n name: \"agent_undo\",\n description: \"Undo the most recent action on the agent's stack. Optional agentId targets a specific agent.\",\n inputSchema: {\n type: \"object\",\n properties: { agentId: { type: \"string\" } },\n additionalProperties: false,\n },\n },\n async (args) => {\n const entry = await undoOne(agentOf(args));\n if (!entry) return errorResult(\"Nothing to undo.\");\n return textResult(`Undid: ${entry.label}`, { entry: serialize(entry) });\n },\n ),\n );\n\n disposers.push(\n host.registerTool(\n {\n name: \"agent_redo\",\n description: \"Redo the most recently undone action.\",\n inputSchema: {\n type: \"object\",\n properties: { agentId: { type: \"string\" } },\n additionalProperties: false,\n },\n },\n async (args) => {\n const entry = await redoOne(agentOf(args));\n if (!entry) return errorResult(\"Nothing to redo.\");\n return textResult(`Redid: ${entry.label}`, { entry: serialize(entry) });\n },\n ),\n );\n\n disposers.push(\n host.registerTool(\n {\n name: \"agent_history\",\n description: \"List the agent's undo stack (oldest first). Useful for understanding what's reversible.\",\n inputSchema: {\n type: \"object\",\n properties: { agentId: { type: \"string\" } },\n additionalProperties: false,\n },\n },\n async (args) => {\n const history = readHistory(agentOf(args)).map(serialize);\n const text = history.map((e) => `${new Date(e.timestamp).toISOString()} ${e.bridgeId} ${e.action}: ${e.label}`).join(\"\\n\");\n return textResult(text || \"(empty)\", history);\n },\n ),\n );\n\n return () => disposers.forEach((d) => d());\n}\n\nfunction serialize(entry: import(\"./undo-stack\").UndoEntry) {\n return {\n timestamp: entry.timestamp,\n bridgeId: entry.bridgeId,\n action: entry.action,\n label: entry.label,\n };\n}\n","import { textResult, errorResult } from \"../mcp/server\";\nimport type { ToolHost } from \"../mcp/tool-host\";\nimport type { JsonObject } from \"../mcp/types\";\nimport type { Bridge } from \"./types\";\nimport { wrapToolWithActivity } from \"../presence/wrap-tool-with-activity\";\nimport { ensureUndoToolsRegistered } from \"../undo/undo-tools\";\nimport type { AgentTarget } from \"../presence/types\";\n\n/**\n * Adapter wires a single fancy-echarts chart to the bridge. Charts are\n * already prop-driven, so the adapter just exposes the data + option\n * setters and a way to read what's currently rendered.\n */\nexport type ChartsBridgeAdapter = {\n /** Stable id for this chart instance. */\n id: string;\n title?: string;\n screenId?: string;\n /** Read the current ECharts option object the chart is rendering. */\n getOption: () => Record<string, unknown>;\n /** Replace the entire option. */\n setOption: (option: Record<string, unknown>) => void;\n /** Convenience: shallow-merge a partial option update. */\n updateOption?: (partial: Record<string, unknown>) => void;\n /** Read just the data series (subset of option for quick agent reads). */\n getData?: () => unknown;\n /** Update only the data, leaving axes/colors/etc. alone. */\n updateData?: (data: unknown) => void;\n};\n\nexport type ChartsBridgeOptions = {\n adapter: ChartsBridgeAdapter;\n agent?: { id: string; name?: string; color?: string };\n};\n\nconst DEFAULT_AGENT = { id: \"agent\", name: \"Agent\", color: \"#a855f7\" };\n\n/**\n * registerChartsBridge — schema-aware MCP access to a single chart.\n */\nexport function registerChartsBridge(\n host: ToolHost,\n options: ChartsBridgeOptions,\n): Bridge {\n const { adapter } = options;\n const agent = { ...DEFAULT_AGENT, ...(options.agent ?? {}) };\n const disposers: Array<() => void> = [];\n\n // agent_undo / agent_redo / agent_history are registered whenever any bridge\n // mounts, so undo availability doesn't hinge on which bridges are co-present.\n ensureUndoToolsRegistered(host, { defaultAgentId: agent.id });\n\n const target: AgentTarget = {\n kind: \"chart\",\n screenId: adapter.screenId,\n elementId: adapter.id,\n label: adapter.title ?? adapter.id,\n };\n\n const reg = (\n name: string,\n description: string,\n properties: Record<string, unknown>,\n required: string[],\n handler: (args: JsonObject) => Promise<any> | any,\n isMutation: boolean,\n ) => {\n const wrapped = async (args: JsonObject) => {\n try { return await handler(args); }\n catch (e) { return errorResult(e instanceof Error ? e.message : String(e)); }\n };\n const final = isMutation\n ? wrapToolWithActivity(wrapped, {\n toolName: name, agent, kind: \"chart\", screenId: adapter.screenId,\n resolveTarget: () => target,\n })\n : wrapped;\n disposers.push(\n host.registerTool(\n { name, description, inputSchema: { type: \"object\", properties: properties as any, required, additionalProperties: false } },\n final as any,\n ),\n );\n };\n\n reg(\n \"chart_describe\",\n `Describe the chart \"${adapter.id}\" — series count, type guesses, axis info.`,\n {},\n [],\n () => {\n const opt = adapter.getOption();\n const series = Array.isArray(opt.series) ? opt.series : [];\n const summary = {\n id: adapter.id,\n title: adapter.title,\n seriesCount: series.length,\n seriesTypes: series.map((s: any) => s?.type ?? \"unknown\"),\n hasXAxis: !!opt.xAxis,\n hasYAxis: !!opt.yAxis,\n };\n return textResult(JSON.stringify(summary), summary);\n },\n false,\n );\n\n reg(\n \"chart_get_option\",\n \"Read the full ECharts option object the chart is rendering.\",\n {},\n [],\n () => {\n const opt = adapter.getOption();\n return textResult(JSON.stringify(opt, null, 2), opt);\n },\n false,\n );\n\n reg(\n \"chart_set_option\",\n \"Replace the entire ECharts option. Use chart_update_option for partial updates.\",\n { option: { type: \"object\" } },\n [\"option\"],\n (args) => {\n const opt = (args.option && typeof args.option === \"object\") ? args.option as Record<string, unknown> : {};\n adapter.setOption(opt);\n return textResult(\"Replaced chart option\", { });\n },\n true,\n );\n\n reg(\n \"chart_update_option\",\n \"Shallow-merge a partial option update — only the keys you provide change.\",\n { partial: { type: \"object\" } },\n [\"partial\"],\n (args) => {\n const partial = (args.partial && typeof args.partial === \"object\") ? args.partial as Record<string, unknown> : {};\n if (adapter.updateOption) {\n adapter.updateOption(partial);\n } else {\n adapter.setOption({ ...adapter.getOption(), ...partial });\n }\n return textResult(\"Merged chart option\", { keys: Object.keys(partial) });\n },\n true,\n );\n\n reg(\n \"chart_update_data\",\n \"Update only the data (typically the `series` field). Leaves layout / axes / colors alone.\",\n { data: { description: \"New series array (or whatever shape the host's adapter expects).\" } },\n [\"data\"],\n (args) => {\n if (!adapter.updateData) return errorResult(\"Host did not provide updateData.\");\n adapter.updateData(args.data);\n return textResult(\"Updated chart data\", { });\n },\n true,\n );\n\n return {\n id: `chart:${adapter.id}`,\n title: adapter.title ?? adapter.id,\n dispose: () => { for (const d of disposers) d(); },\n };\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/mcp/server.ts","../src/presence/wrap-tool-with-activity.ts","../src/undo/undo-tools.ts","../src/bridges/charts.ts"],"names":["emitActivity","undoOne","redoOne","readHistory"],"mappings":"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","file":"bridges-charts.cjs","sourcesContent":["import {\n type CallToolResult,\n type JsonObject,\n type JsonRpcMessage,\n type JsonRpcRequest,\n type JsonRpcId,\n type RegisteredTool,\n type ServerCapabilities,\n type ServerInfo,\n type ToolDefinition,\n type ToolHandler,\n JSONRPC_INTERNAL_ERROR,\n JSONRPC_INVALID_PARAMS,\n JSONRPC_METHOD_NOT_FOUND,\n MCP_PROTOCOL_VERSION,\n} from \"./types\";\nimport { ToolRegistry } from \"./tool-host\";\n\nexport type McpServerOptions = {\n info: ServerInfo;\n /** Defaults to { tools: { listChanged: true } } */\n capabilities?: ServerCapabilities;\n /** Free-text instructions surfaced to clients during initialize. */\n instructions?: string;\n /**\n * The protocol revisions this server speaks, NEWEST FIRST.\n *\n * `initialize` echoes the client's requested revision when it is in this\n * list, and answers the first entry otherwise — the spec's rule, which leaves\n * the client to decide whether it can live with the answer.\n *\n * Defaults to `[MCP_PROTOCOL_VERSION]`: one revision, answered whatever the\n * client asks, which is exactly what this server did before the option\n * existed. Only list a revision the tools you register are correct under.\n */\n protocolVersions?: readonly string[];\n};\n\nexport type Transport = {\n /** Called by the server when it has a message to deliver to the client. */\n send: (message: JsonRpcMessage) => void;\n /** Called by the server when it's torn down so the transport can clean up. */\n close?: () => void;\n};\n\n/**\n * MicroMcpServer — protocol-level MCP server, transport-agnostic.\n *\n * Use it like:\n *\n * const server = new MicroMcpServer({ info: { name: \"session\", version: \"0.1\" } });\n * server.registerTool({ name: \"...\", inputSchema: { type: \"object\" } }, async (args) => ({...}));\n * const transport = new InProcessTransport();\n * server.attach(transport);\n * transport.deliver({ ... }); // client → server frames\n *\n * The same server can serve multiple transports (e.g. an in-process agent\n * AND a relayed external client) by attaching each one.\n */\nexport class MicroMcpServer extends ToolRegistry {\n private transports = new Set<Transport>();\n /**\n * Transports owed a `tools/list_changed` at the end of this tick. Empty when\n * none is scheduled. See {@link scheduleListChangedNotification}.\n */\n private listChangedOwed = new Set<Transport>();\n\n readonly info: ServerInfo;\n readonly capabilities: ServerCapabilities;\n readonly instructions?: string;\n readonly protocolVersions: readonly string[];\n\n constructor(options: McpServerOptions) {\n super();\n this.info = options.info;\n this.capabilities = options.capabilities ?? { tools: { listChanged: true } };\n this.instructions = options.instructions;\n if (options.protocolVersions && options.protocolVersions.length === 0) {\n // No answer exists for a client's initialize. Fail here, next to the\n // mistake, rather than in a handshake nobody is watching.\n throw new Error(\"MicroMcpServer: protocolVersions is empty — a server must speak at least one protocol revision.\");\n }\n this.protocolVersions = options.protocolVersions ? [...options.protocolVersions] : [MCP_PROTOCOL_VERSION];\n }\n\n attach(transport: Transport): () => void {\n this.transports.add(transport);\n return () => this.detach(transport);\n }\n\n detach(transport: Transport): void {\n if (this.transports.delete(transport)) {\n transport.close?.();\n }\n }\n\n unregisterTool(name: string): void {\n if (this.tools.delete(name)) {\n this.scheduleListChangedNotification();\n }\n }\n\n protected onToolsChanged(): void {\n this.scheduleListChangedNotification();\n }\n\n /**\n * Receive a JSON-RPC frame from a client (called by the transport).\n * The transport is responsible for sending the response back.\n */\n async receive(transport: Transport, message: JsonRpcMessage): Promise<void> {\n if (!(\"method\" in message)) return; // It's a response, not a request — ignore.\n\n const isNotification = !(\"id\" in message);\n if (isNotification) {\n // Notifications are fire-and-forget. We ignore unknown methods.\n return;\n }\n\n const request = message as JsonRpcRequest;\n try {\n const result = await this.handle(request, transport);\n transport.send({ jsonrpc: \"2.0\", id: request.id, result });\n } catch (err) {\n transport.send({\n jsonrpc: \"2.0\",\n id: request.id,\n error: this.toRpcError(err),\n });\n }\n }\n\n private async handle(request: JsonRpcRequest, transport: Transport): Promise<any> {\n const { method, params } = request;\n switch (method) {\n case \"initialize\":\n return {\n protocolVersion: this.negotiate(params?.protocolVersion),\n capabilities: this.capabilities,\n serverInfo: this.info,\n ...(this.instructions ? { instructions: this.instructions } : {}),\n };\n\n case \"tools/list\":\n return { tools: this.listTools() };\n\n case \"tools/call\": {\n const name = params?.name;\n const args = (params?.arguments ?? {}) as JsonObject;\n if (typeof name !== \"string\") {\n throw rpcError(JSONRPC_INVALID_PARAMS, \"tools/call requires `name`\");\n }\n const tool = this.tools.get(name);\n if (!tool) {\n throw rpcError(JSONRPC_METHOD_NOT_FOUND, this.missingToolMessage(name));\n }\n const result = await tool.handler(args, { transport });\n return result satisfies CallToolResult;\n }\n\n case \"ping\":\n return {};\n\n default:\n throw rpcError(JSONRPC_METHOD_NOT_FOUND, `Unsupported method: ${method}`);\n }\n }\n\n /** The revision to answer `initialize` with: the one asked for if spoken, else the newest. */\n private negotiate(requested: unknown): string {\n return typeof requested === \"string\" && this.protocolVersions.includes(requested)\n ? requested\n : this.protocolVersions[0];\n }\n\n /**\n * Tell the transports that SAW the old tool list that it changed.\n *\n * Changes in one tick coalesce into one notification. The recipients are the\n * transports attached at the moment of a change, not at the moment the\n * notification goes out: a transport attached afterwards never had the old\n * list, so \"your list is stale\" is noise to it — and on stdio, where a host\n * builds the server and attaches stdin/stdout in the same tick, it was the\n * first frame a client received, before it had even sent `initialize`.\n */\n private scheduleListChangedNotification(): void {\n if (this.transports.size === 0) return;\n const scheduled = this.listChangedOwed.size > 0;\n for (const t of this.transports) this.listChangedOwed.add(t);\n if (scheduled) return;\n queueMicrotask(() => {\n const owed = this.listChangedOwed;\n this.listChangedOwed = new Set();\n for (const t of owed) {\n // Detached since the change: it is not listening any more.\n if (this.transports.has(t)) t.send({ jsonrpc: \"2.0\", method: \"notifications/tools/list_changed\" });\n }\n });\n }\n\n /** Send an application notification to every client, or one attached transport. */\n notify(message: JsonRpcMessage, transport?: Transport): void {\n if (transport) transport.send(message);\n else this.broadcast(message);\n }\n\n private broadcast(message: JsonRpcMessage): void {\n for (const t of this.transports) t.send(message);\n }\n\n private toRpcError(err: unknown): { code: number; message: string; data?: any } {\n if (err && typeof err === \"object\" && \"code\" in err && \"message\" in err) {\n return err as any;\n }\n return {\n code: JSONRPC_INTERNAL_ERROR,\n message: err instanceof Error ? err.message : String(err),\n };\n }\n}\n\nexport function rpcError(code: number, message: string, data?: any) {\n return { code, message, ...(data !== undefined ? { data } : {}) };\n}\n\n/**\n * Helper to build a CallToolResult from a string or structured value.\n */\nexport function textResult(text: string, structured?: any): CallToolResult {\n return {\n content: [{ type: \"text\", text }],\n ...(structured !== undefined ? { structuredContent: structured } : {}),\n };\n}\n\nexport function errorResult(text: string): CallToolResult {\n return { content: [{ type: \"text\", text }], isError: true };\n}\n\n// Internal helper so the JsonRpcId import isn't dropped by tsup\ntype _KeepIdImport = JsonRpcId;\n","import type { CallToolResult } from \"../mcp/types\";\nimport { emitActivity } from \"./registry\";\nimport type { AgentTarget } from \"./types\";\n\nexport type ActivityAgent = { id: string; name?: string; color?: string };\n\nexport type ActivityResolverContext<TArgs = Record<string, unknown>> = {\n /** Tool name as registered. */\n toolName: string;\n /** Arguments the tool was called with. */\n args: TArgs;\n /** The CallToolResult the underlying handler produced. */\n result: CallToolResult;\n};\n\n/**\n * Resolves an `AgentTarget` for an executed tool. Bridges declare one of\n * these per registration so the wrapper knows which surface / element /\n * screen the activity belongs to.\n *\n * The resolver runs AFTER the tool handler so it can inspect the result\n * (e.g. read a newly-created item id from `structuredContent`).\n */\nexport type ActivityTargetResolver<TArgs = Record<string, unknown>> = (\n ctx: ActivityResolverContext<TArgs>,\n) => AgentTarget | null;\n\nexport type ToolHandler<TArgs = Record<string, unknown>> = (\n args: TArgs,\n) => Promise<CallToolResult> | CallToolResult;\n\n/**\n * wrapToolWithActivity — decorate a bridge tool handler so every successful\n * call emits an `AgentActivityEvent`. Returns a new handler with the same shape.\n *\n * Usage in a bridge:\n *\n * server.registerTool(\n * definition,\n * wrapToolWithActivity(\n * handler,\n * { agent, kind: \"whiteboard\", resolveTarget: ({ args }) => ({\n * kind: \"whiteboard\", elementId: args.id as string,\n * }) },\n * ),\n * );\n */\nexport function wrapToolWithActivity<TArgs = Record<string, unknown>>(\n handler: ToolHandler<TArgs>,\n options: {\n toolName: string;\n agent: ActivityAgent;\n /** Optional fancy-screens screen id this bridge is scoped to. */\n screenId?: string;\n /** Default target kind if the resolver returns one without `kind`. */\n kind: AgentTarget[\"kind\"];\n /** Per-call resolver. Return `null` to skip emitting (e.g. for read-only tools). */\n resolveTarget?: ActivityTargetResolver<TArgs>;\n /** Optional ttl override. */\n ttlMs?: number;\n /**\n * Build the `meta` broadcast to all relay peers. Defaults to the tool's full\n * `structuredContent`. Override to REDACT sensitive fields before fan-out —\n * e.g. the terminal bridge strips raw command/keystroke bytes so a command\n * line (or its secrets) is never broadcast verbatim to every peer.\n */\n buildMeta?: (result: CallToolResult) => Record<string, unknown> | undefined;\n },\n): ToolHandler<TArgs> {\n return async (args) => {\n const result = await handler(args);\n if (result.isError) return result;\n\n let target: AgentTarget | null;\n if (options.resolveTarget) {\n target = options.resolveTarget({ toolName: options.toolName, args, result });\n } else {\n target = { kind: options.kind, screenId: options.screenId };\n }\n if (!target) return result;\n\n emitActivity({\n agentId: options.agent.id,\n agentName: options.agent.name,\n agentColor: options.agent.color,\n target: { ...target, kind: target.kind ?? options.kind, screenId: target.screenId ?? options.screenId },\n action: options.toolName,\n timestamp: Date.now(),\n meta: options.buildMeta ? options.buildMeta(result) : extractMeta(result),\n ttlMs: options.ttlMs,\n });\n return result;\n };\n}\n\nfunction extractMeta(result: CallToolResult): Record<string, unknown> | undefined {\n const sc = result.structuredContent;\n if (sc && typeof sc === \"object\" && !Array.isArray(sc)) {\n return sc as Record<string, unknown>;\n }\n return undefined;\n}\n","import { textResult, errorResult } from \"../mcp/server\";\nimport type { ToolHost } from \"../mcp/tool-host\";\nimport { readHistory, redoOne, undoOne } from \"./undo-stack\";\n\nexport type UndoToolsOptions = {\n /** Default agent id when the caller doesn't pass one. */\n defaultAgentId?: string;\n};\n\n/**\n * Idempotent tracker so multiple bridges on the same server only register\n * agent_undo / agent_redo / agent_history once.\n */\nconst installedHosts = new WeakSet<ToolHost>();\n\n/**\n * The one owner every copy of the undo tools registers under. They are SHARED\n * on purpose — every bridge ensures them, and a host may also call\n * `registerUndoTools` itself — so all of those are the same registrant, and a\n * second registration replaces the first instead of being refused as a\n * collision. Anything else claiming `agent_undo` is still refused.\n */\nconst UNDO_TOOLS_OWNER = \"agent-undo\";\n\n/**\n * ensureUndoToolsRegistered — bridges call this on construction. Safe to\n * call repeatedly with the same server; subsequent calls are no-ops.\n */\nexport function ensureUndoToolsRegistered(host: ToolHost, options: UndoToolsOptions = {}): void {\n if (installedHosts.has(host)) return;\n installedHosts.add(host);\n registerUndoTools(host, options);\n}\n\n/**\n * registerUndoTools — add agent_undo / agent_redo / agent_history to the\n * server. Returns a disposer that unregisters all three.\n */\nexport function registerUndoTools(host: ToolHost, options: UndoToolsOptions = {}): () => void {\n const defaultAgent = options.defaultAgentId ?? \"agent\";\n const disposers: Array<() => void> = [];\n const agentOf = (args: any): string =>\n typeof args?.agentId === \"string\" ? args.agentId : defaultAgent;\n\n disposers.push(\n host.registerTool(\n {\n name: \"agent_undo\",\n description: \"Undo the most recent action on the agent's stack. Optional agentId targets a specific agent.\",\n inputSchema: {\n type: \"object\",\n properties: { agentId: { type: \"string\" } },\n additionalProperties: false,\n },\n },\n async (args) => {\n const entry = await undoOne(agentOf(args));\n if (!entry) return errorResult(\"Nothing to undo.\");\n return textResult(`Undid: ${entry.label}`, { entry: serialize(entry) });\n },\n { owner: UNDO_TOOLS_OWNER },\n ),\n );\n\n disposers.push(\n host.registerTool(\n {\n name: \"agent_redo\",\n description: \"Redo the most recently undone action.\",\n inputSchema: {\n type: \"object\",\n properties: { agentId: { type: \"string\" } },\n additionalProperties: false,\n },\n },\n async (args) => {\n const entry = await redoOne(agentOf(args));\n if (!entry) return errorResult(\"Nothing to redo.\");\n return textResult(`Redid: ${entry.label}`, { entry: serialize(entry) });\n },\n { owner: UNDO_TOOLS_OWNER },\n ),\n );\n\n disposers.push(\n host.registerTool(\n {\n name: \"agent_history\",\n description: \"List the agent's undo stack (oldest first). Useful for understanding what's reversible.\",\n inputSchema: {\n type: \"object\",\n properties: { agentId: { type: \"string\" } },\n additionalProperties: false,\n },\n },\n async (args) => {\n const history = readHistory(agentOf(args)).map(serialize);\n const text = history.map((e) => `${new Date(e.timestamp).toISOString()} ${e.bridgeId} ${e.action}: ${e.label}`).join(\"\\n\");\n return textResult(text || \"(empty)\", history);\n },\n { owner: UNDO_TOOLS_OWNER },\n ),\n );\n\n return () => disposers.forEach((d) => d());\n}\n\nfunction serialize(entry: import(\"./undo-stack\").UndoEntry) {\n return {\n timestamp: entry.timestamp,\n bridgeId: entry.bridgeId,\n action: entry.action,\n label: entry.label,\n };\n}\n","import { textResult, errorResult } from \"../mcp/server\";\nimport type { ToolHost } from \"../mcp/tool-host\";\nimport type { JsonObject } from \"../mcp/types\";\nimport type { Bridge } from \"./types\";\nimport { wrapToolWithActivity } from \"../presence/wrap-tool-with-activity\";\nimport { ensureUndoToolsRegistered } from \"../undo/undo-tools\";\nimport type { AgentTarget } from \"../presence/types\";\n\n/**\n * Adapter wires a single fancy-echarts chart to the bridge. Charts are\n * already prop-driven, so the adapter just exposes the data + option\n * setters and a way to read what's currently rendered.\n */\nexport type ChartsBridgeAdapter = {\n /** Stable id for this chart instance. */\n id: string;\n title?: string;\n screenId?: string;\n /** Read the current ECharts option object the chart is rendering. */\n getOption: () => Record<string, unknown>;\n /** Replace the entire option. */\n setOption: (option: Record<string, unknown>) => void;\n /** Convenience: shallow-merge a partial option update. */\n updateOption?: (partial: Record<string, unknown>) => void;\n /** Read just the data series (subset of option for quick agent reads). */\n getData?: () => unknown;\n /** Update only the data, leaving axes/colors/etc. alone. */\n updateData?: (data: unknown) => void;\n};\n\nexport type ChartsBridgeOptions = {\n adapter: ChartsBridgeAdapter;\n agent?: { id: string; name?: string; color?: string };\n};\n\nconst DEFAULT_AGENT = { id: \"agent\", name: \"Agent\", color: \"#a855f7\" };\n\n/**\n * registerChartsBridge — schema-aware MCP access to a single chart.\n */\nexport function registerChartsBridge(\n host: ToolHost,\n options: ChartsBridgeOptions,\n): Bridge {\n const { adapter } = options;\n const agent = { ...DEFAULT_AGENT, ...(options.agent ?? {}) };\n const disposers: Array<() => void> = [];\n // The bridge id is also its registrant identity on the host: the same bridge\n // may re-register (a remount), a different one claiming a name is refused.\n const bridgeId = `chart:${adapter.id}`;\n\n // agent_undo / agent_redo / agent_history are registered whenever any bridge\n // mounts, so undo availability doesn't hinge on which bridges are co-present.\n ensureUndoToolsRegistered(host, { defaultAgentId: agent.id });\n\n const target: AgentTarget = {\n kind: \"chart\",\n screenId: adapter.screenId,\n elementId: adapter.id,\n label: adapter.title ?? adapter.id,\n };\n\n const reg = (\n name: string,\n description: string,\n properties: Record<string, unknown>,\n required: string[],\n handler: (args: JsonObject) => Promise<any> | any,\n isMutation: boolean,\n ) => {\n const wrapped = async (args: JsonObject) => {\n try { return await handler(args); }\n catch (e) { return errorResult(e instanceof Error ? e.message : String(e)); }\n };\n const final = isMutation\n ? wrapToolWithActivity(wrapped, {\n toolName: name, agent, kind: \"chart\", screenId: adapter.screenId,\n resolveTarget: () => target,\n })\n : wrapped;\n disposers.push(\n host.registerTool(\n { name, description, inputSchema: { type: \"object\", properties: properties as any, required, additionalProperties: false } },\n final as any,\n { owner: bridgeId },\n ),\n );\n };\n\n reg(\n \"chart_describe\",\n `Describe the chart \"${adapter.id}\" — series count, type guesses, axis info.`,\n {},\n [],\n () => {\n const opt = adapter.getOption();\n const series = Array.isArray(opt.series) ? opt.series : [];\n const summary = {\n id: adapter.id,\n title: adapter.title,\n seriesCount: series.length,\n seriesTypes: series.map((s: any) => s?.type ?? \"unknown\"),\n hasXAxis: !!opt.xAxis,\n hasYAxis: !!opt.yAxis,\n };\n return textResult(JSON.stringify(summary), summary);\n },\n false,\n );\n\n reg(\n \"chart_get_option\",\n \"Read the full ECharts option object the chart is rendering.\",\n {},\n [],\n () => {\n const opt = adapter.getOption();\n return textResult(JSON.stringify(opt, null, 2), opt);\n },\n false,\n );\n\n reg(\n \"chart_set_option\",\n \"Replace the entire ECharts option. Use chart_update_option for partial updates.\",\n { option: { type: \"object\" } },\n [\"option\"],\n (args) => {\n const opt = (args.option && typeof args.option === \"object\") ? args.option as Record<string, unknown> : {};\n adapter.setOption(opt);\n return textResult(\"Replaced chart option\", { });\n },\n true,\n );\n\n reg(\n \"chart_update_option\",\n \"Shallow-merge a partial option update — only the keys you provide change.\",\n { partial: { type: \"object\" } },\n [\"partial\"],\n (args) => {\n const partial = (args.partial && typeof args.partial === \"object\") ? args.partial as Record<string, unknown> : {};\n if (adapter.updateOption) {\n adapter.updateOption(partial);\n } else {\n adapter.setOption({ ...adapter.getOption(), ...partial });\n }\n return textResult(\"Merged chart option\", { keys: Object.keys(partial) });\n },\n true,\n );\n\n reg(\n \"chart_update_data\",\n \"Update only the data (typically the `series` field). Leaves layout / axes / colors alone.\",\n { data: { description: \"New series array (or whatever shape the host's adapter expects).\" } },\n [\"data\"],\n (args) => {\n if (!adapter.updateData) return errorResult(\"Host did not provide updateData.\");\n adapter.updateData(args.data);\n return textResult(\"Updated chart data\", { });\n },\n true,\n );\n\n return {\n id: bridgeId,\n title: adapter.title ?? adapter.id,\n dispose: () => { for (const d of disposers) d(); },\n };\n}\n"]}
|