@geohar/pi-mcp-combiner 0.14.2 → 0.16.0-dev.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. package/README.md +71 -48
  2. package/dist/client/config-ladder.d.ts +1 -1
  3. package/dist/client/config-ladder.d.ts.map +1 -1
  4. package/dist/client/control.d.ts +1 -1
  5. package/dist/client/control.d.ts.map +1 -1
  6. package/dist/client/elicitation.d.ts +4 -2
  7. package/dist/client/elicitation.d.ts.map +1 -1
  8. package/dist/client/elicitation.js +8 -2
  9. package/dist/client/elicitation.js.map +1 -1
  10. package/dist/client/footer.d.ts +1 -1
  11. package/dist/client/footer.d.ts.map +1 -1
  12. package/dist/client/panel.d.ts +1 -1
  13. package/dist/client/panel.d.ts.map +1 -1
  14. package/dist/client/panel.js +1 -1
  15. package/dist/client/panel.js.map +1 -1
  16. package/dist/client/prompts.d.ts +1 -1
  17. package/dist/client/prompts.d.ts.map +1 -1
  18. package/dist/client/proxy-tool.d.ts +1 -1
  19. package/dist/client/proxy-tool.d.ts.map +1 -1
  20. package/dist/client/resource-naming.d.ts +8 -0
  21. package/dist/client/resource-naming.d.ts.map +1 -0
  22. package/dist/client/resource-naming.js +33 -0
  23. package/dist/client/resource-naming.js.map +1 -0
  24. package/dist/client/settings.d.ts +5 -4
  25. package/dist/client/settings.d.ts.map +1 -1
  26. package/dist/client/settings.js +3 -3
  27. package/dist/client/settings.js.map +1 -1
  28. package/dist/client/tool-matching.d.ts +32 -0
  29. package/dist/client/tool-matching.d.ts.map +1 -0
  30. package/dist/client/tool-matching.js +43 -0
  31. package/dist/client/tool-matching.js.map +1 -0
  32. package/dist/client/types.d.ts +71 -0
  33. package/dist/client/types.d.ts.map +1 -0
  34. package/dist/client/types.js +16 -0
  35. package/dist/client/types.js.map +1 -0
  36. package/dist/client/widget-support.d.ts +17 -0
  37. package/dist/client/widget-support.d.ts.map +1 -0
  38. package/dist/client/widget-support.js +89 -0
  39. package/dist/client/widget-support.js.map +1 -0
  40. package/dist/index.d.ts.map +1 -1
  41. package/dist/index.js +109 -53
  42. package/dist/index.js.map +1 -1
  43. package/dist/{client/connection.d.ts → native/combiner-connection.d.ts} +46 -38
  44. package/dist/native/combiner-connection.d.ts.map +1 -0
  45. package/dist/native/combiner-connection.js +412 -0
  46. package/dist/native/combiner-connection.js.map +1 -0
  47. package/dist/native/index.d.ts +30 -0
  48. package/dist/native/index.d.ts.map +1 -0
  49. package/dist/native/index.js +61 -0
  50. package/dist/native/index.js.map +1 -0
  51. package/dist/native/resources.d.ts +18 -0
  52. package/dist/native/resources.d.ts.map +1 -0
  53. package/dist/native/resources.js +97 -0
  54. package/dist/native/resources.js.map +1 -0
  55. package/dist/native/tool-surface.d.ts +26 -0
  56. package/dist/native/tool-surface.d.ts.map +1 -0
  57. package/dist/native/tool-surface.js +113 -0
  58. package/dist/native/tool-surface.js.map +1 -0
  59. package/dist/pi.d.ts +19 -0
  60. package/dist/pi.d.ts.map +1 -1
  61. package/package.json +4 -6
  62. package/src/client/config-ladder.ts +1 -1
  63. package/src/client/control.ts +1 -1
  64. package/src/client/elicitation.ts +10 -2
  65. package/src/client/footer.ts +1 -1
  66. package/src/client/panel.ts +2 -2
  67. package/src/client/prompts.ts +1 -1
  68. package/src/client/proxy-tool.ts +1 -1
  69. package/src/client/resource-naming.ts +36 -0
  70. package/src/client/settings.ts +7 -6
  71. package/src/client/tool-matching.ts +69 -0
  72. package/src/client/types.ts +80 -0
  73. package/src/client/widget-support.ts +86 -0
  74. package/src/index.ts +109 -65
  75. package/src/native/combiner-connection.ts +483 -0
  76. package/src/native/index.ts +100 -0
  77. package/src/native/resources.ts +112 -0
  78. package/src/native/tool-surface.ts +147 -0
  79. package/src/pi.ts +16 -0
  80. package/dist/client/connection.d.ts.map +0 -1
  81. package/dist/client/connection.js +0 -332
  82. package/dist/client/connection.js.map +0 -1
  83. package/dist/client/direct-tools.d.ts +0 -41
  84. package/dist/client/direct-tools.d.ts.map +0 -1
  85. package/dist/client/direct-tools.js +0 -122
  86. package/dist/client/direct-tools.js.map +0 -1
  87. package/dist/client/resources.d.ts +0 -20
  88. package/dist/client/resources.d.ts.map +0 -1
  89. package/dist/client/resources.js +0 -119
  90. package/dist/client/resources.js.map +0 -1
  91. package/dist/client/script.d.ts +0 -10
  92. package/dist/client/script.d.ts.map +0 -1
  93. package/dist/client/script.js +0 -130
  94. package/dist/client/script.js.map +0 -1
  95. package/src/client/connection.ts +0 -373
  96. package/src/client/direct-tools.ts +0 -146
  97. package/src/client/resources.ts +0 -137
  98. package/src/client/script.ts +0 -150
@@ -1,41 +0,0 @@
1
- import type { ToolDefinition } from "../pi.js";
2
- import type { CombinerConnection, ToolSummary } from "./connection.js";
3
- export type DirectToolsSpec = string[] | "search";
4
- /** Names that must never be shadowed by a promoted tool (pi builtins). Callers add
5
- * their own tool names on top. */
6
- export declare const RESERVED_TOOL_NAMES: readonly ["read", "bash", "edit", "write", "grep", "find", "ls", "mcp", "glob"];
7
- /** Apply a server allow/deny filter to a combined tool list. Server names may
8
- * contain underscores (gws_georgeharker), so matching is by PREFIX — a tool
9
- * belongs to entry E iff its name starts `E_` (subsumes first-segment equality). */
10
- export declare function toolServerMatches(toolName: string, serverEntry: string): boolean;
11
- /** Apply a server allow/deny filter to a combined tool list (`<server>_` prefix,
12
- * underscore-safe via toolServerMatches). */
13
- export declare function applyServerFilter(tools: ToolSummary[], filter: {
14
- allow?: string[];
15
- deny?: string[];
16
- } | undefined): ToolSummary[];
17
- /** fnmatch-lite: `*` → any run, `?` → one char, everything else literal. */
18
- export declare function globToRegExp(pattern: string): RegExp;
19
- export declare function matchesGlob(name: string, pattern: string): boolean;
20
- /** Resolve the allowlist spec against the combined tool list (server filter applied
21
- * by the caller). Returns matching tools in list order. */
22
- export declare function resolveAllowlist(tools: ToolSummary[], patterns: string[]): ToolSummary[];
23
- export type DirectToolDeps = {
24
- connection: CombinerConnection;
25
- /** Names already registered (shared across syncs + search activation). */
26
- registered: Set<string>;
27
- /** Reserved names to refuse (builtins + this extension's own tool names). */
28
- reserved: Set<string>;
29
- register: (tool: ToolDefinition) => void;
30
- log: (level: "info" | "warn" | "error", message: string) => void;
31
- };
32
- /** Build the Pi tool definition for one promoted combiner tool. */
33
- export declare function buildDirectTool(tool: ToolSummary, deps: DirectToolDeps): ToolDefinition;
34
- /** Register one tool if new and not reserved. Returns the name, or undefined when skipped. */
35
- export declare function registerDirectTool(tool: ToolSummary, deps: DirectToolDeps): string | undefined;
36
- /** Allowlist sync: register every matching, not-yet-registered tool. */
37
- export declare function syncAllowlistTools(tools: ToolSummary[], patterns: string[], deps: DirectToolDeps): number;
38
- /** Search-mode activation: register matched tools (bounded per activation). Returns
39
- * the newly activated names — empty when everything matched was already live. */
40
- export declare function activateFromSearch(matches: ToolSummary[], deps: DirectToolDeps, max?: number): string[];
41
- //# sourceMappingURL=direct-tools.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"direct-tools.d.ts","sourceRoot":"","sources":["../../src/client/direct-tools.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AAC9C,OAAO,KAAK,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAItE,MAAM,MAAM,eAAe,GAAG,MAAM,EAAE,GAAG,QAAQ,CAAA;AAEjD;mCACmC;AACnC,eAAO,MAAM,mBAAmB,iFAAkF,CAAA;AAElH;;qFAEqF;AACrF,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAEhF;AAED;8CAC8C;AAC9C,wBAAgB,iBAAiB,CAC7B,KAAK,EAAE,WAAW,EAAE,EACpB,MAAM,EAAE;IAAE,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;CAAE,GAAG,SAAS,GAC1D,WAAW,EAAE,CASf;AAED,4EAA4E;AAC5E,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAMpD;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAElE;AAED;4DAC4D;AAC5D,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,WAAW,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,WAAW,EAAE,CAGxF;AAWD,MAAM,MAAM,cAAc,GAAG;IACzB,UAAU,EAAE,kBAAkB,CAAA;IAC9B,0EAA0E;IAC1E,UAAU,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;IACvB,6EAA6E;IAC7E,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;IACrB,QAAQ,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,IAAI,CAAA;IACxC,GAAG,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAA;CACnE,CAAA;AAED,mEAAmE;AACnE,wBAAgB,eAAe,CAAC,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,cAAc,GAAG,cAAc,CAcvF;AAED,8FAA8F;AAC9F,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,cAAc,GAAG,MAAM,GAAG,SAAS,CAU9F;AAED,wEAAwE;AACxE,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,WAAW,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,cAAc,GAAG,MAAM,CAczG;AAED;kFACkF;AAClF,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,WAAW,EAAE,EAAE,IAAI,EAAE,cAAc,EAAE,GAAG,SAAK,GAAG,MAAM,EAAE,CAQnG"}
@@ -1,122 +0,0 @@
1
- // Direct tool promotion: allowlist + search-mode, per the agreed design
2
- // (docs/adapter-design.md §Now/Later). Behavior follows pi-mcp-adapter's
3
- // directTools modes (MIT, © 2026 Nico Bailon).
4
- //
5
- // `combiner.directTools` on the shared-file entry is either a glob allowlist over
6
- // combined tool names — registered once at session start, cache-stable — or
7
- // "search": nothing registered upfront; the first mcp({search}) match activates
8
- // those tools as first-class Pi tools for the rest of the session (the adapter's
9
- // directTools:"search" semantics, on our own mid-session registerTool path).
10
- //
11
- // `directTools: true` is deliberately NOT offered: at combiner scale (hundreds of
12
- // tools) it burns the context window the proxy exists to save. Allowlists larger
13
- // than ~50 tools draw a loud warning and still register — an explicit list is the
14
- // user's call.
15
- import { renderToolResult, textResult } from "./render.js";
16
- import { directToolRenderers } from "./renderers.js";
17
- /** Names that must never be shadowed by a promoted tool (pi builtins). Callers add
18
- * their own tool names on top. */
19
- export const RESERVED_TOOL_NAMES = ["read", "bash", "edit", "write", "grep", "find", "ls", "mcp", "glob"];
20
- /** Apply a server allow/deny filter to a combined tool list. Server names may
21
- * contain underscores (gws_georgeharker), so matching is by PREFIX — a tool
22
- * belongs to entry E iff its name starts `E_` (subsumes first-segment equality). */
23
- export function toolServerMatches(toolName, serverEntry) {
24
- return toolName.startsWith(`${serverEntry}_`);
25
- }
26
- /** Apply a server allow/deny filter to a combined tool list (`<server>_` prefix,
27
- * underscore-safe via toolServerMatches). */
28
- export function applyServerFilter(tools, filter) {
29
- if (!filter)
30
- return tools;
31
- if (filter.allow?.length) {
32
- return tools.filter((t) => filter.allow.some((e) => toolServerMatches(t.name, e)));
33
- }
34
- if (filter.deny?.length) {
35
- return tools.filter((t) => !filter.deny.some((e) => toolServerMatches(t.name, e)));
36
- }
37
- return tools;
38
- }
39
- /** fnmatch-lite: `*` → any run, `?` → one char, everything else literal. */
40
- export function globToRegExp(pattern) {
41
- const escaped = pattern
42
- .replace(/[.+^${}()|[\]\\]/g, "\\$&")
43
- .replace(/\*/g, ".*")
44
- .replace(/\?/g, ".");
45
- return new RegExp(`^${escaped}$`, "i");
46
- }
47
- export function matchesGlob(name, pattern) {
48
- return globToRegExp(pattern).test(name);
49
- }
50
- /** Resolve the allowlist spec against the combined tool list (server filter applied
51
- * by the caller). Returns matching tools in list order. */
52
- export function resolveAllowlist(tools, patterns) {
53
- const regexes = patterns.map(globToRegExp);
54
- return tools.filter((t) => regexes.some((re) => re.test(t.name)));
55
- }
56
- /** Ensure a usable parameters object: pass the advertised JSON schema through when it
57
- * is an object; repair anything else to an empty object schema. */
58
- function normalizeInputSchema(schema) {
59
- if (typeof schema === "object" && schema !== null && !Array.isArray(schema)) {
60
- return schema;
61
- }
62
- return { type: "object", properties: {} };
63
- }
64
- /** Build the Pi tool definition for one promoted combiner tool. */
65
- export function buildDirectTool(tool, deps) {
66
- return {
67
- name: tool.name,
68
- label: `MCP: ${tool.name}`,
69
- description: tool.description ?? `Combiner tool ${tool.name}`,
70
- parameters: normalizeInputSchema(tool.inputSchema),
71
- ...directToolRenderers(tool.name),
72
- execute: async () => {
73
- const result = await deps.connection.callTool(tool.name, undefined);
74
- const text = renderToolResult(result);
75
- if (result?.isError)
76
- throw new Error(text);
77
- return textResult(text);
78
- },
79
- };
80
- }
81
- /** Register one tool if new and not reserved. Returns the name, or undefined when skipped. */
82
- export function registerDirectTool(tool, deps) {
83
- if (deps.registered.has(tool.name))
84
- return undefined;
85
- if (deps.reserved.has(tool.name)) {
86
- deps.log("warn", `directTools: refusing to register "${tool.name}" — reserved name`);
87
- deps.registered.add(tool.name); // don't re-warn on every sync
88
- return undefined;
89
- }
90
- deps.registered.add(tool.name);
91
- deps.register(buildDirectTool(tool, deps));
92
- return tool.name;
93
- }
94
- /** Allowlist sync: register every matching, not-yet-registered tool. */
95
- export function syncAllowlistTools(tools, patterns, deps) {
96
- const matches = resolveAllowlist(tools, patterns);
97
- if (matches.length > 50) {
98
- deps.log("warn", `directTools: allowlist promotes ${matches.length} tools — every schema rides in every ` +
99
- "request. Consider trimming (the mcp() proxy covers the rest).");
100
- }
101
- let added = 0;
102
- for (const tool of matches) {
103
- if (registerDirectTool(tool, deps))
104
- added++;
105
- }
106
- return added;
107
- }
108
- /** Search-mode activation: register matched tools (bounded per activation). Returns
109
- * the newly activated names — empty when everything matched was already live. */
110
- export function activateFromSearch(matches, deps, max = 10) {
111
- const activated = [];
112
- for (const tool of matches) {
113
- if (activated.length >= max)
114
- break;
115
- if (deps.registered.has(tool.name))
116
- continue;
117
- if (registerDirectTool(tool, deps))
118
- activated.push(tool.name);
119
- }
120
- return activated;
121
- }
122
- //# sourceMappingURL=direct-tools.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"direct-tools.js","sourceRoot":"","sources":["../../src/client/direct-tools.ts"],"names":[],"mappings":"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"}
@@ -1,20 +0,0 @@
1
- import type { ToolDefinition } from "../pi.js";
2
- import type { CombinerConnection, ResourceSummary } from "./connection.js";
3
- import type { ServerFilter } from "./config-ladder.js";
4
- /** Ported verbatim from pi-mcp-adapter's resource-tools.ts (MIT, © 2026 Nico Bailon). */
5
- export declare function resourceNameToToolName(name: string): string;
6
- export declare const MCP_APP_MIME = "text/html;profile=mcp-app";
7
- /** True for interactive ext-apps resources: read_* returns their markup AND
8
- * surfaces the combiner UI-host URL (which serves the live widget). */
9
- export declare function isInteractiveResource(r: ResourceSummary): boolean;
10
- /** Attribute a resource to an upstream server for filtering: ui:// URIs carry the
11
- * server as the host component (ui://todoist/…); otherwise fall back to the name's
12
- * leading word before a dash/underscore. */
13
- export declare function resourceServer(r: ResourceSummary): string | undefined;
14
- /** Apply the project server filter to a resource list (mirrors tool filtering;
15
- * attribution by uri host, with `_`/`-` name-prefix fallback for underscore-named
16
- * servers whose resources carry the full prefixed name). */
17
- export declare function filterResources(resources: ResourceSummary[], filter: ServerFilter | undefined): ResourceSummary[];
18
- /** Discover resources and register one read_* tool each. Idempotent; returns count. */
19
- export declare function syncResourceTools(register: (tool: ToolDefinition) => void, connection: CombinerConnection, registered: Set<string>, filter: ServerFilter | undefined, notify: (message: string, level: "info" | "warn" | "error") => void): Promise<number>;
20
- //# sourceMappingURL=resources.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"resources.d.ts","sourceRoot":"","sources":["../../src/client/resources.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AAC9C,OAAO,KAAK,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAC1E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAKtD,yFAAyF;AACzF,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAc3D;AAED,eAAO,MAAM,YAAY,8BAA8B,CAAA;AAEvD;wEACwE;AACxE,wBAAgB,qBAAqB,CAAC,CAAC,EAAE,eAAe,GAAG,OAAO,CAEjE;AAED;;6CAE6C;AAC7C,wBAAgB,cAAc,CAAC,CAAC,EAAE,eAAe,GAAG,MAAM,GAAG,SAAS,CAMrE;AAED;;6DAE6D;AAC7D,wBAAgB,eAAe,CAAC,SAAS,EAAE,eAAe,EAAE,EAAE,MAAM,EAAE,YAAY,GAAG,SAAS,GAAG,eAAe,EAAE,CAWjH;AAED,uFAAuF;AACvF,wBAAsB,iBAAiB,CACnC,QAAQ,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,IAAI,EACxC,UAAU,EAAE,kBAAkB,EAC9B,UAAU,EAAE,GAAG,CAAC,MAAM,CAAC,EACvB,MAAM,EAAE,YAAY,GAAG,SAAS,EAChC,MAAM,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,KAAK,IAAI,GACpE,OAAO,CAAC,MAAM,CAAC,CA2DjB"}
@@ -1,119 +0,0 @@
1
- // MCP resources → read_* Pi tools, compatible with pi-mcp-adapter's conventions.
2
- //
3
- // A resource is server-exposed content addressed by URI (the GET to tools' POST);
4
- // each becomes a zero-parameter tool the model can call directly, named
5
- // `read_<sanitized>` (resourceNameToToolName ported verbatim). Reads go through the
6
- // combiner's proxied resources/read; text is guarded, binaries noted by size.
7
- //
8
- // Interactive mcp-app resources (mimeType `text/html;profile=mcp-app`, `ui://` URIs)
9
- // are flagged in the tool description — read_* returns their markup as text; the
10
- // interactive browser experience is the ext-apps host (later, see adapter-design.md).
11
- import { renderResourceResult, textResult } from "./render.js";
12
- import { openInBrowser } from "./proxy-tool.js";
13
- import { callRenderer, resultRenderer } from "./renderers.js";
14
- /** Ported verbatim from pi-mcp-adapter's resource-tools.ts (MIT, © 2026 Nico Bailon). */
15
- export function resourceNameToToolName(name) {
16
- let result = name
17
- .replace(/[^a-zA-Z0-9]/g, "_")
18
- .replace(/_+/g, "_")
19
- .replace(/^_+/, "") // Remove leading underscores
20
- .replace(/_+$/, "") // Remove trailing underscores
21
- .toLowerCase();
22
- // Ensure we have a valid name
23
- if (!result || /^\d/.test(result)) {
24
- result = "resource" + (result ? "_" + result : "");
25
- }
26
- return result;
27
- }
28
- export const MCP_APP_MIME = "text/html;profile=mcp-app";
29
- /** True for interactive ext-apps resources: read_* returns their markup AND
30
- * surfaces the combiner UI-host URL (which serves the live widget). */
31
- export function isInteractiveResource(r) {
32
- return r.mimeType === MCP_APP_MIME || r.uri.startsWith("ui://");
33
- }
34
- /** Attribute a resource to an upstream server for filtering: ui:// URIs carry the
35
- * server as the host component (ui://todoist/…); otherwise fall back to the name's
36
- * leading word before a dash/underscore. */
37
- export function resourceServer(r) {
38
- const m = r.uri.match(/^[a-z][a-z0-9+.-]*:\/\/([^/?#]+)/i);
39
- if (m?.[1])
40
- return m[1].split(".")[0]?.toLowerCase();
41
- const name = r.name ?? r.uri;
42
- const head = name.split(/[-_]/, 1)[0];
43
- return head ? head.toLowerCase() : undefined;
44
- }
45
- /** Apply the project server filter to a resource list (mirrors tool filtering;
46
- * attribution by uri host, with `_`/`-` name-prefix fallback for underscore-named
47
- * servers whose resources carry the full prefixed name). */
48
- export function filterResources(resources, filter) {
49
- if (!filter)
50
- return resources;
51
- const matches = (r, entry) => resourceServer(r) === entry || (r.name ?? "").startsWith(`${entry}_`) || (r.name ?? "").startsWith(`${entry}-`);
52
- if (filter.allow?.length) {
53
- return resources.filter((r) => filter.allow.some((e) => matches(r, e)));
54
- }
55
- if (filter.deny?.length) {
56
- return resources.filter((r) => !filter.deny.some((e) => matches(r, e)));
57
- }
58
- return resources;
59
- }
60
- /** Discover resources and register one read_* tool each. Idempotent; returns count. */
61
- export async function syncResourceTools(register, connection, registered, filter, notify) {
62
- let resources = [];
63
- try {
64
- resources = filterResources(await connection.listResources(), filter);
65
- }
66
- catch (e) {
67
- notify(`resource discovery failed (${e instanceof Error ? e.message : String(e)})`, "warn");
68
- return 0;
69
- }
70
- for (const resource of resources) {
71
- const label = resource.name ?? resource.uri;
72
- const toolName = `read_${resourceNameToToolName(label)}`;
73
- if (registered.has(toolName))
74
- continue;
75
- registered.add(toolName);
76
- const interactive = isInteractiveResource(resource);
77
- const description = [
78
- resource.description ?? `Read MCP resource ${resource.uri}`,
79
- `uri: ${resource.uri}`,
80
- resource.mimeType ? `type: ${resource.mimeType}` : undefined,
81
- interactive
82
- ? "interactive app resource — markup as text; the interactive widget opens from the URL appended to results"
83
- : undefined,
84
- ]
85
- .filter(Boolean)
86
- .join(" | ");
87
- register({
88
- name: toolName,
89
- label: `MCP resource: ${label}`,
90
- description,
91
- promptSnippet: `Read MCP resource ${label}.`,
92
- parameters: { type: "object", properties: {} },
93
- renderCall: callRenderer(toolName, () => resource.uri),
94
- renderResult: resultRenderer(() => toolName, toolName),
95
- execute: async (_toolCallId, _params, _signal, _onUpdate, ctx) => {
96
- try {
97
- const result = await connection.readResource(resource.uri);
98
- let text = renderResourceResult(result);
99
- // Interactive resources: the combiner's UI host serves the
100
- // widget for this session's token — surface + auto-open.
101
- if (interactive) {
102
- const url = connection.uiUrlFor(resource.uri);
103
- if (url) {
104
- text = `${text}\n\ninteractive: ${url}`;
105
- if (ctx?.hasUI)
106
- openInBrowser(url);
107
- }
108
- }
109
- return textResult(text, { mode: "resource", uri: resource.uri });
110
- }
111
- catch (e) {
112
- throw new Error(`${toolName}: resource read failed (${e instanceof Error ? e.message : String(e)})`);
113
- }
114
- },
115
- });
116
- }
117
- return resources.length;
118
- }
119
- //# sourceMappingURL=resources.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"resources.js","sourceRoot":"","sources":["../../src/client/resources.ts"],"names":[],"mappings":"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"}
@@ -1,10 +0,0 @@
1
- import type { ToolDefinition } from "../pi.js";
2
- import type { CombinerConnection } from "./connection.js";
3
- export declare const DEFAULT_SCRIPT_TIMEOUT_MS = 30000;
4
- export type ScriptToolDeps = {
5
- connection: CombinerConnection;
6
- /** Tool name for the batching tool — `${toolName}Script` ("mcpScript" in parity). */
7
- name: string;
8
- };
9
- export declare function createScriptTool(deps: ScriptToolDeps): ToolDefinition;
10
- //# sourceMappingURL=script.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"script.d.ts","sourceRoot":"","sources":["../../src/client/script.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AAC9C,OAAO,KAAK,EAAE,kBAAkB,EAAe,MAAM,iBAAiB,CAAA;AAKtE,eAAO,MAAM,yBAAyB,QAAS,CAAA;AAK/C,MAAM,MAAM,cAAc,GAAG;IACzB,UAAU,EAAE,kBAAkB,CAAA;IAC9B,qFAAqF;IACrF,IAAI,EAAE,MAAM,CAAA;CACf,CAAA;AAyBD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,cAAc,GAAG,cAAc,CAkGrE"}
@@ -1,130 +0,0 @@
1
- // The <toolName>Script batching tool — API parity with pi-mcp-adapter's
2
- // mcpScript (MIT, © 2026 Nico Bailon; mcp-code.ts), reimplemented lean:
3
- // scriptMode: `{code, timeoutMs?}` executing trusted JavaScript with
4
- // `await tools.search/describe/call()` and `emit(value)` for user-visible output.
5
- //
6
- // Lean port: pi-mcp-adapter runs the code in a worker thread (mcp-code.ts) for hard
7
- // timeout termination; we evaluate in-process with an AsyncFunction and race a timer.
8
- // The trade-off is deliberate — trusted code, one loopback server — an abandoned
9
- // call finishes harmlessly combiner-side, and the API surface (what agents write)
10
- // is identical. Default timeout 30s, matching the adapter.
11
- import { rankTools, regexMatches, compileSafeRegex } from "./ranking.js";
12
- import { renderDescribe, renderSearchHit, renderToolResult, textResult } from "./render.js";
13
- import { callRenderer, resultRenderer } from "./renderers.js";
14
- export const DEFAULT_SCRIPT_TIMEOUT_MS = 30_000;
15
- const MAX_SCRIPT_TIMEOUT_MS = 120_000;
16
- const MAX_EMITTED_BLOCKS = 200;
17
- const MAX_EMIT_CHARS = 16 * 1024;
18
- const AsyncFunction = Object.getPrototypeOf(async () => {
19
- /* capture */
20
- }).constructor;
21
- function serverOf(name) {
22
- return name.split("_", 1)[0] ?? "";
23
- }
24
- function formatValue(value) {
25
- if (typeof value === "string")
26
- return value;
27
- try {
28
- return JSON.stringify(value, null, 2) ?? String(value);
29
- }
30
- catch {
31
- return "[unserializable value]";
32
- }
33
- }
34
- export function createScriptTool(deps) {
35
- const { connection, name } = deps;
36
- return {
37
- name,
38
- label: "MCP script (combiner)",
39
- description: [
40
- "Run trusted JavaScript that makes multiple MCP calls in one request.",
41
- "API: const r = await tools.search('query', {limit}); await tools.describe('name');",
42
- "await tools.call('name', {args}); emit(value) for user-visible output.",
43
- "The final return value (or the last emitted value) becomes the tool result.",
44
- ].join(" "),
45
- promptSnippet: "Batch multiple MCP calls with trusted JavaScript (tools.search/describe/call + emit).",
46
- parameters: {
47
- type: "object",
48
- properties: {
49
- code: { type: "string", description: "JavaScript to run (await allowed)" },
50
- timeoutMs: { type: "number", description: `Timeout in ms (default ${DEFAULT_SCRIPT_TIMEOUT_MS})` },
51
- },
52
- required: ["code"],
53
- },
54
- renderCall: callRenderer(name, (args) => {
55
- const code = typeof args.code === "string" ? (args.code.trim().split("\n", 1)[0] ?? "") : "";
56
- return code.length > 60 ? `${code.slice(0, 59)}…` : code;
57
- }),
58
- renderResult: resultRenderer(() => name, name),
59
- execute: async (_toolCallId, params) => {
60
- const p = params;
61
- if (typeof p.code !== "string" || !p.code.trim()) {
62
- throw new Error(`${name}: code must be a non-empty string`);
63
- }
64
- const timeoutMs = typeof p.timeoutMs === "number" && p.timeoutMs > 0
65
- ? Math.min(MAX_SCRIPT_TIMEOUT_MS, p.timeoutMs)
66
- : DEFAULT_SCRIPT_TIMEOUT_MS;
67
- const emitted = [];
68
- let emittedChars = 0;
69
- const emit = (value) => {
70
- if (emitted.length >= MAX_EMITTED_BLOCKS)
71
- return;
72
- const text = formatValue(value).slice(0, MAX_EMIT_CHARS);
73
- emittedChars += text.length;
74
- emitted.push(text);
75
- };
76
- const tools = {
77
- search: (query, opts) => {
78
- const q = typeof query === "string" ? query : "";
79
- const server = opts?.server;
80
- return connection
81
- .listTools()
82
- .then((all) => {
83
- const pool = server ? all.filter((t) => serverOf(t.name) === server) : all;
84
- if (opts?.regex) {
85
- const { re, error } = compileSafeRegex(q);
86
- if (!re)
87
- throw new Error(`bad regex: ${error}`);
88
- return regexMatches(pool, re, opts?.limit ?? 12, opts?.offset ?? 0).map((m) => m.tool);
89
- }
90
- return rankTools(pool, q, opts?.limit ?? 12, opts?.offset ?? 0).map((m) => m.tool);
91
- })
92
- .then((tools) => tools.map((t) => renderSearchHit(t)))
93
- .then((lines) => lines.join("\n"));
94
- },
95
- describe: (toolName) => connection
96
- .listTools()
97
- .then((all) => all.find((t) => t.name === toolName))
98
- .then((t) => {
99
- if (!t)
100
- throw new Error(`no tool "${toolName}" — use tools.search first`);
101
- return renderDescribe(t, serverOf(t.name));
102
- }),
103
- call: (toolName, args) => connection.callTool(toolName, args).then((r) => renderToolResult(r)),
104
- };
105
- try {
106
- const fn = new AsyncFunction("tools", "emit", p.code);
107
- const timer = new Promise((_, reject) => setTimeout(() => reject(new Error(`${name} timed out after ${timeoutMs}ms`)), timeoutMs));
108
- let result;
109
- try {
110
- result = await Promise.race([fn(tools, emit), timer]);
111
- }
112
- finally {
113
- // nothing to clean — the timer's reject is inert once the race settled
114
- }
115
- const resultText = result === undefined ? "" : formatValue(result);
116
- const text = [...emitted, resultText].filter((s) => s.length > 0).join("\n\n");
117
- return textResult(text || "(no output — emit(value) or return a value)", {
118
- mode: "script",
119
- emitted: emitted.length,
120
- });
121
- }
122
- catch (e) {
123
- const msg = e instanceof Error ? e.message : String(e);
124
- const text = emitted.length ? `${emitted.join("\n\n")}\n\n${name}: ${msg}` : `${name}: ${msg}`;
125
- throw new Error(text);
126
- }
127
- },
128
- };
129
- }
130
- //# sourceMappingURL=script.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"script.js","sourceRoot":"","sources":["../../src/client/script.ts"],"names":[],"mappings":"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"}