@geohar/pi-mcp-combiner 0.13.3 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. package/README.md +227 -126
  2. package/dist/client/config-ladder.d.ts +62 -0
  3. package/dist/client/config-ladder.d.ts.map +1 -0
  4. package/dist/client/config-ladder.js +162 -0
  5. package/dist/client/config-ladder.js.map +1 -0
  6. package/dist/client/connection.d.ts +113 -0
  7. package/dist/client/connection.d.ts.map +1 -0
  8. package/dist/client/connection.js +332 -0
  9. package/dist/client/connection.js.map +1 -0
  10. package/dist/client/control.d.ts +17 -0
  11. package/dist/client/control.d.ts.map +1 -0
  12. package/dist/client/control.js +80 -0
  13. package/dist/client/control.js.map +1 -0
  14. package/dist/client/direct-tools.d.ts +41 -0
  15. package/dist/client/direct-tools.d.ts.map +1 -0
  16. package/dist/client/direct-tools.js +122 -0
  17. package/dist/client/direct-tools.js.map +1 -0
  18. package/dist/client/elicitation.d.ts +22 -0
  19. package/dist/client/elicitation.d.ts.map +1 -0
  20. package/dist/client/elicitation.js +93 -0
  21. package/dist/client/elicitation.js.map +1 -0
  22. package/dist/client/footer.d.ts +17 -0
  23. package/dist/client/footer.d.ts.map +1 -0
  24. package/dist/client/footer.js +99 -0
  25. package/dist/client/footer.js.map +1 -0
  26. package/dist/client/panel.d.ts +16 -0
  27. package/dist/client/panel.d.ts.map +1 -0
  28. package/dist/client/panel.js +426 -0
  29. package/dist/client/panel.js.map +1 -0
  30. package/dist/client/prompts.d.ts +30 -0
  31. package/dist/client/prompts.d.ts.map +1 -0
  32. package/dist/client/prompts.js +230 -0
  33. package/dist/client/prompts.js.map +1 -0
  34. package/dist/client/proxy-tool.d.ts +22 -0
  35. package/dist/client/proxy-tool.d.ts.map +1 -0
  36. package/dist/client/proxy-tool.js +225 -0
  37. package/dist/client/proxy-tool.js.map +1 -0
  38. package/dist/client/ranking.d.ts +21 -0
  39. package/dist/client/ranking.d.ts.map +1 -0
  40. package/dist/client/ranking.js +113 -0
  41. package/dist/client/ranking.js.map +1 -0
  42. package/dist/client/render.d.ts +28 -0
  43. package/dist/client/render.d.ts.map +1 -0
  44. package/dist/client/render.js +166 -0
  45. package/dist/client/render.js.map +1 -0
  46. package/dist/client/renderers.d.ts +31 -0
  47. package/dist/client/renderers.d.ts.map +1 -0
  48. package/dist/client/renderers.js +191 -0
  49. package/dist/client/renderers.js.map +1 -0
  50. package/dist/client/resources.d.ts +20 -0
  51. package/dist/client/resources.d.ts.map +1 -0
  52. package/dist/client/resources.js +119 -0
  53. package/dist/client/resources.js.map +1 -0
  54. package/dist/client/schema-signature.d.ts +3 -0
  55. package/dist/client/schema-signature.d.ts.map +1 -0
  56. package/dist/client/schema-signature.js +183 -0
  57. package/dist/client/schema-signature.js.map +1 -0
  58. package/dist/client/script.d.ts +10 -0
  59. package/dist/client/script.d.ts.map +1 -0
  60. package/dist/client/script.js +130 -0
  61. package/dist/client/script.js.map +1 -0
  62. package/dist/client/settings.d.ts +46 -0
  63. package/dist/client/settings.d.ts.map +1 -0
  64. package/dist/client/settings.js +81 -0
  65. package/dist/client/settings.js.map +1 -0
  66. package/dist/index.d.ts.map +1 -1
  67. package/dist/index.js +333 -29
  68. package/dist/index.js.map +1 -1
  69. package/dist/pi.d.ts +82 -2
  70. package/dist/pi.d.ts.map +1 -1
  71. package/dist/pi.js +2 -1
  72. package/dist/pi.js.map +1 -1
  73. package/dist/sharedserver-resolve.d.ts.map +1 -1
  74. package/dist/sharedserver-resolve.js +2 -1
  75. package/dist/sharedserver-resolve.js.map +1 -1
  76. package/package.json +68 -57
  77. package/src/client/config-ladder.ts +221 -0
  78. package/src/client/connection.ts +373 -0
  79. package/src/client/control.ts +94 -0
  80. package/src/client/direct-tools.ts +146 -0
  81. package/src/client/elicitation.ts +115 -0
  82. package/src/client/footer.ts +108 -0
  83. package/src/client/panel.ts +478 -0
  84. package/src/client/prompts.ts +251 -0
  85. package/src/client/proxy-tool.ts +261 -0
  86. package/src/client/ranking.ts +130 -0
  87. package/src/client/render.ts +166 -0
  88. package/src/client/renderers.ts +211 -0
  89. package/src/client/resources.ts +137 -0
  90. package/src/client/schema-signature.ts +184 -0
  91. package/src/client/script.ts +150 -0
  92. package/src/client/settings.ts +109 -0
  93. package/src/index.ts +384 -32
  94. package/src/pi.ts +86 -6
  95. package/src/sharedserver-resolve.ts +10 -3
@@ -0,0 +1,119 @@
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
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resources.js","sourceRoot":"","sources":["../../src/client/resources.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ /** Renders the useful JSON Schema subset as TypeScript, or null for unsupported schemas. */
2
+ export declare function renderSchemaSignature(inputSchema: unknown): string | null;
3
+ //# sourceMappingURL=schema-signature.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema-signature.d.ts","sourceRoot":"","sources":["../../src/client/schema-signature.ts"],"names":[],"mappings":"AAUA,4FAA4F;AAC5F,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CA2HzE"}
@@ -0,0 +1,183 @@
1
+ // TypeScript-shape rendering of JSON Schemas for tool `describe` output.
2
+ //
3
+ // Adapted (near-verbatim) from pi-mcp-adapter's ts-shape.ts — MIT, © 2026 Nico Bailon
4
+ // (https://github.com/nicobailon/pi-mcp-adapter). Self-contained by design: no
5
+ // dependencies on the rest of that package. Conformance cases: test/schema-signature.test.ts.
6
+ const UNSUPPORTED_KEYWORDS = ["if", "then", "else", "allOf", "not", "patternProperties", "additionalProperties"];
7
+ /** Renders the useful JSON Schema subset as TypeScript, or null for unsupported schemas. */
8
+ export function renderSchemaSignature(inputSchema) {
9
+ try {
10
+ if (!isSchema(inputSchema))
11
+ return null;
12
+ const definitions = new Map();
13
+ for (const key of ["$defs", "definitions"]) {
14
+ const rawDefinitions = inputSchema[key];
15
+ if (rawDefinitions === undefined)
16
+ continue;
17
+ if (!isSchema(rawDefinitions))
18
+ return null;
19
+ for (const [name, definition] of Object.entries(rawDefinitions)) {
20
+ if (!isSchema(definition))
21
+ return null;
22
+ definitions.set(`${key}/${decodePointerToken(name)}`, definition);
23
+ }
24
+ }
25
+ const aliases = new Map();
26
+ const usedAliases = new Set();
27
+ let aliasIndex = 0;
28
+ const aliasFor = (definitionKey) => {
29
+ let alias = aliases.get(definitionKey);
30
+ if (alias)
31
+ return alias;
32
+ const name = definitionKey.slice(definitionKey.indexOf("/") + 1);
33
+ alias = /^[A-Za-z_$][\w$]*$/.test(name) && !usedAliases.has(name) ? name : `Definition${++aliasIndex}`;
34
+ while (usedAliases.has(alias))
35
+ alias = `Definition${++aliasIndex}`;
36
+ aliases.set(definitionKey, alias);
37
+ usedAliases.add(alias);
38
+ return alias;
39
+ };
40
+ const render = (schema) => {
41
+ if (!isSchema(schema) || hasUnsupportedKeyword(schema))
42
+ return null;
43
+ if ("$ref" in schema) {
44
+ if (typeof schema.$ref !== "string")
45
+ return null;
46
+ const match = schema.$ref.match(/^#\/(\$defs|definitions)\/([^/]+)$/);
47
+ if (!match)
48
+ return null;
49
+ const definitionGroup = match[1];
50
+ const definitionName = match[2];
51
+ if (definitionGroup === undefined || definitionName === undefined)
52
+ return null;
53
+ const definitionKey = `${definitionGroup}/${decodePointerToken(definitionName)}`;
54
+ if (!definitions.has(definitionKey))
55
+ return null;
56
+ return aliasFor(definitionKey);
57
+ }
58
+ if (Array.isArray(schema.enum)) {
59
+ const values = schema.enum.map(renderLiteral);
60
+ return values.every((value) => value !== null) ? values.join(" | ") : null;
61
+ }
62
+ if (Object.hasOwn(schema, "const"))
63
+ return renderLiteral(schema.const);
64
+ if (Array.isArray(schema.anyOf) || Array.isArray(schema.oneOf)) {
65
+ const variants = (schema.anyOf ?? schema.oneOf);
66
+ if (variants.length === 0)
67
+ return null;
68
+ const rendered = variants.map(render);
69
+ return rendered.every((value) => value !== null) ? rendered.join(" | ") : null;
70
+ }
71
+ if (schema.type === "object" || schema.properties !== undefined) {
72
+ if (schema.properties === undefined)
73
+ return "{}";
74
+ if (!isSchema(schema.properties))
75
+ return null;
76
+ const required = new Set(Array.isArray(schema.required)
77
+ ? schema.required.filter((name) => typeof name === "string")
78
+ : []);
79
+ const properties = [];
80
+ for (const [name, property] of Object.entries(schema.properties)) {
81
+ const rendered = render(property);
82
+ if (rendered === null)
83
+ return null;
84
+ // Field descriptions are the model's primary guidance at
85
+ // describe-time (it never sees the raw schema on the proxy
86
+ // path) — thread them as comments; defaults inline too.
87
+ const prop = isSchema(property) ? property : {};
88
+ const notes = [];
89
+ if (!required.has(name) && prop.default !== undefined) {
90
+ notes.push(`default ${JSON.stringify(prop.default)}`);
91
+ }
92
+ if (typeof prop.description === "string" && prop.description) {
93
+ const oneLine = prop.description.replace(/\s+/g, " ").trim();
94
+ notes.push(oneLine.length > 90 ? `${oneLine.slice(0, 87)}…` : oneLine);
95
+ }
96
+ const comment = notes.length > 0 ? ` // ${notes.join(" — ")}` : "";
97
+ properties.push(`${formatPropertyName(name)}${required.has(name) ? "" : "?"}: ${rendered};${comment}`);
98
+ }
99
+ // Multi-line when annotations are present (readability beats the
100
+ // single-line compactness once comments exist).
101
+ if (properties.some((p) => p.includes("//"))) {
102
+ return properties.length === 0 ? "{}" : `{\n${properties.map((p) => ` ${p}`).join("\n")}\n}`;
103
+ }
104
+ return properties.length === 0 ? "{}" : `{ ${properties.join(" ")} }`;
105
+ }
106
+ if (schema.type === "array") {
107
+ if (schema.items === undefined)
108
+ return "unknown[]";
109
+ const item = render(schema.items);
110
+ return item === null ? null : `${needsParentheses(item) ? `(${item})` : item}[]`;
111
+ }
112
+ if (Array.isArray(schema.type)) {
113
+ const types = schema.type.map(renderType);
114
+ return types.every((type) => type !== null) ? types.join(" | ") : null;
115
+ }
116
+ if (typeof schema.type === "string")
117
+ return renderType(schema.type);
118
+ return "unknown";
119
+ };
120
+ const root = render(inputSchema);
121
+ if (root === null)
122
+ return null;
123
+ const definitionsText = [];
124
+ for (const [key, alias] of aliases) {
125
+ const definition = definitions.get(key);
126
+ if (!definition)
127
+ return null;
128
+ const rendered = render(definition);
129
+ if (rendered === null)
130
+ return null;
131
+ definitionsText.push(`type ${alias} = ${rendered};`);
132
+ }
133
+ return definitionsText.length > 0 ? `${definitionsText.join("\n")}\n\n${root}` : root;
134
+ }
135
+ catch {
136
+ return null;
137
+ }
138
+ }
139
+ function isSchema(value) {
140
+ return typeof value === "object" && value !== null && !Array.isArray(value);
141
+ }
142
+ function hasUnsupportedKeyword(schema) {
143
+ return UNSUPPORTED_KEYWORDS.some((keyword) => {
144
+ if (!Object.hasOwn(schema, keyword))
145
+ return false;
146
+ // `additionalProperties: false` is a closed-object constraint, not a shape that this renderer needs to understand.
147
+ return keyword !== "additionalProperties" || schema.additionalProperties !== false;
148
+ });
149
+ }
150
+ function decodePointerToken(token) {
151
+ return token.replace(/~1/g, "/").replace(/~0/g, "~");
152
+ }
153
+ function renderType(type) {
154
+ switch (type) {
155
+ case "string":
156
+ return "string";
157
+ case "number":
158
+ case "integer":
159
+ return "number";
160
+ case "boolean":
161
+ return "boolean";
162
+ case "null":
163
+ return "null";
164
+ case "object":
165
+ return "{}";
166
+ case "array":
167
+ return "unknown[]";
168
+ default:
169
+ return null;
170
+ }
171
+ }
172
+ function renderLiteral(value) {
173
+ if (value === null || typeof value === "string" || typeof value === "boolean")
174
+ return JSON.stringify(value);
175
+ return typeof value === "number" && Number.isFinite(value) ? String(value) : null;
176
+ }
177
+ function formatPropertyName(name) {
178
+ return /^[A-Za-z_$][\w$]*$/.test(name) ? name : JSON.stringify(name);
179
+ }
180
+ function needsParentheses(type) {
181
+ return type.includes(" | ");
182
+ }
183
+ //# sourceMappingURL=schema-signature.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema-signature.js","sourceRoot":"","sources":["../../src/client/schema-signature.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
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
@@ -0,0 +1 @@
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"}
@@ -0,0 +1,130 @@
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
@@ -0,0 +1 @@
1
+ {"version":3,"file":"script.js","sourceRoot":"","sources":["../../src/client/script.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,46 @@
1
+ export type AdapterMode = boolean | "auto";
2
+ export type FooterStatus = "full" | "compact" | "off";
3
+ export type CombinerSettings = {
4
+ /** Tool name registered with Pi. Default "mcp" (parity with pi-mcp-adapter);
5
+ * rename (e.g. "combiner") to coexist while both are installed. */
6
+ toolName: string;
7
+ /** "lazy" (default): connect on first mcp() call. "eager": connect at session_start. */
8
+ lazy: "lazy" | "eager";
9
+ /** Client-half gate. `true`: we are the MCP tool. `false`: legacy mode — the
10
+ * process + instructions halves only, pi-mcp-adapter (if installed) owns MCP.
11
+ * `"auto"` (default): OFF when pi-mcp-adapter is detected installed, ON otherwise —
12
+ * so existing adapter users upgrade with zero behaviour change, while fresh
13
+ * installs get the one-package experience. Env PI_MCP_COMBINER_ADAPTER wins. */
14
+ adapter: AdapterMode;
15
+ /** Expose combiner resources as read_* tools. */
16
+ exposeResources: boolean;
17
+ /** Register combiner prompts as slash commands (adapter naming:
18
+ * mcp__<server>__<name>; prefixed with our toolName when renamed). */
19
+ prompts: boolean;
20
+ /** Footer status line: "full" = "N servers enabled (M ready) · T tools", "compact" = "MCP M/N",
21
+ * "off" = none. Same values as pi-mcp-adapter's mcpFooterStatus. */
22
+ mcpFooterStatus: FooterStatus;
23
+ /** The ctx.ui.setStatus key the footer publishes under. Default "mcp" — the
24
+ * slot pi-mcp-adapter wrote and footers (oh-my-posh's PI_STATUS aggregate)
25
+ * already surface; rename only if something else claims it. */
26
+ mcpFooterKey: string;
27
+ /** Register the trusted batching tool (<toolName>Script). Default true. */
28
+ scriptMode: boolean;
29
+ /** Auto-open interactive widget URLs (Stage 2 holds + resource reads).
30
+ * Default true. */
31
+ uiAutoOpen: boolean;
32
+ /** Explicit combiner base URL (e.g. "http://127.0.0.1:9741/mcp"). Env wins. */
33
+ url?: string;
34
+ /** Notify (vs stderr-only) for connection lifecycle messages. */
35
+ notify: boolean;
36
+ };
37
+ export declare const DEFAULT_SETTINGS: CombinerSettings;
38
+ /** Pi's agent dir: `$PI_CODING_AGENT_DIR` when set, else the first existing of the
39
+ * known defaults (~/.config/pi/agent on newer layouts, ~/.pi/agent on older). */
40
+ export declare function agentDir(): string;
41
+ /** The settings file path this extension reads. */
42
+ export declare function settingsPath(): string;
43
+ /** Load + validate the settings file; missing file or bad shape → defaults.
44
+ * Unknown keys are ignored (forward compat). */
45
+ export declare function loadSettings(path?: string): CombinerSettings;
46
+ //# sourceMappingURL=settings.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../../src/client/settings.ts"],"names":[],"mappings":"AAaA,MAAM,MAAM,WAAW,GAAG,OAAO,GAAG,MAAM,CAAA;AAE1C,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,SAAS,GAAG,KAAK,CAAA;AAErD,MAAM,MAAM,gBAAgB,GAAG;IAC3B;wEACoE;IACpE,QAAQ,EAAE,MAAM,CAAA;IAChB,wFAAwF;IACxF,IAAI,EAAE,MAAM,GAAG,OAAO,CAAA;IACtB;;;;qFAIiF;IACjF,OAAO,EAAE,WAAW,CAAA;IACpB,iDAAiD;IACjD,eAAe,EAAE,OAAO,CAAA;IACxB;2EACuE;IACvE,OAAO,EAAE,OAAO,CAAA;IAChB;yEACqE;IACrE,eAAe,EAAE,YAAY,CAAA;IAC7B;;oEAEgE;IAChE,YAAY,EAAE,MAAM,CAAA;IACpB,2EAA2E;IAC3E,UAAU,EAAE,OAAO,CAAA;IACnB;wBACoB;IACpB,UAAU,EAAE,OAAO,CAAA;IACnB,+EAA+E;IAC/E,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,iEAAiE;IACjE,MAAM,EAAE,OAAO,CAAA;CAClB,CAAA;AAED,eAAO,MAAM,gBAAgB,EAAE,gBAW9B,CAAA;AAED;kFACkF;AAClF,wBAAgB,QAAQ,IAAI,MAAM,CAMjC;AAED,mDAAmD;AACnD,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAED;iDACiD;AACjD,wBAAgB,YAAY,CAAC,IAAI,SAAiB,GAAG,gBAAgB,CA0BpE"}
@@ -0,0 +1,81 @@
1
+ // Pi-specific settings for the mcp-combiner extension's client half.
2
+ //
3
+ // Standard file: `$PI_CODING_AGENT_DIR/extensions/mcp-combiner.json` — one place for
4
+ // the knobs that are about THIS extension in Pi, deliberately separate from the shared
5
+ // MCP config ladder (`.pi/mcp.json` & co. hold connection + per-project exposure; see
6
+ // config-ladder.ts). Read-only at extension load; changes take effect on /reload.
7
+ //
8
+ // Precedence: PI_MCP_COMBINER_* env > this file > built-in defaults.
9
+ import { existsSync, readFileSync } from "node:fs";
10
+ import { homedir } from "node:os";
11
+ import { join } from "node:path";
12
+ export const DEFAULT_SETTINGS = {
13
+ toolName: "mcp",
14
+ lazy: "lazy",
15
+ adapter: "auto",
16
+ exposeResources: true,
17
+ prompts: true,
18
+ mcpFooterStatus: "full",
19
+ mcpFooterKey: "mcp",
20
+ scriptMode: true,
21
+ uiAutoOpen: true,
22
+ notify: true,
23
+ };
24
+ /** Pi's agent dir: `$PI_CODING_AGENT_DIR` when set, else the first existing of the
25
+ * known defaults (~/.config/pi/agent on newer layouts, ~/.pi/agent on older). */
26
+ export function agentDir() {
27
+ const env = process.env.PI_CODING_AGENT_DIR;
28
+ if (env && env.trim())
29
+ return env;
30
+ const candidates = [join(homedir(), ".config", "pi", "agent"), join(homedir(), ".pi", "agent")];
31
+ for (const c of candidates)
32
+ if (existsSync(c))
33
+ return c;
34
+ return candidates[0];
35
+ }
36
+ /** The settings file path this extension reads. */
37
+ export function settingsPath() {
38
+ return join(agentDir(), "extensions", "mcp-combiner.json");
39
+ }
40
+ /** Load + validate the settings file; missing file or bad shape → defaults.
41
+ * Unknown keys are ignored (forward compat). */
42
+ export function loadSettings(path = settingsPath()) {
43
+ const out = { ...DEFAULT_SETTINGS };
44
+ if (!existsSync(path))
45
+ return out;
46
+ let doc;
47
+ try {
48
+ doc = JSON.parse(readFileSync(path, "utf8"));
49
+ }
50
+ catch {
51
+ return out; // malformed JSON → defaults; noisy parse errors help nobody at load time
52
+ }
53
+ if (typeof doc !== "object" || doc === null || Array.isArray(doc))
54
+ return out;
55
+ const d = doc;
56
+ if (typeof d.toolName === "string" && /^[a-zA-Z][a-zA-Z0-9_-]*$/.test(d.toolName))
57
+ out.toolName = d.toolName;
58
+ if (d.lazy === "lazy" || d.lazy === "eager")
59
+ out.lazy = d.lazy;
60
+ if (d.adapter === "auto" || typeof d.adapter === "boolean")
61
+ out.adapter = d.adapter;
62
+ if (typeof d.exposeResources === "boolean")
63
+ out.exposeResources = d.exposeResources;
64
+ if (typeof d.prompts === "boolean")
65
+ out.prompts = d.prompts;
66
+ if (d.mcpFooterStatus === "full" || d.mcpFooterStatus === "compact" || d.mcpFooterStatus === "off") {
67
+ out.mcpFooterStatus = d.mcpFooterStatus;
68
+ }
69
+ if (typeof d.mcpFooterKey === "string" && d.mcpFooterKey.trim())
70
+ out.mcpFooterKey = d.mcpFooterKey.trim();
71
+ if (typeof d.uiAutoOpen === "boolean")
72
+ out.uiAutoOpen = d.uiAutoOpen;
73
+ if (typeof d.scriptMode === "boolean")
74
+ out.scriptMode = d.scriptMode;
75
+ if (typeof d.url === "string" && d.url.trim())
76
+ out.url = d.url.trim();
77
+ if (typeof d.notify === "boolean")
78
+ out.notify = d.notify;
79
+ return out;
80
+ }
81
+ //# sourceMappingURL=settings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"settings.js","sourceRoot":"","sources":["../../src/client/settings.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAiCA,OAAO,KAAK,EAER,YAAY,EAIf,MAAM,SAAS,CAAA;AA6NhB,MAAM,CAAC,OAAO,UAAU,WAAW,CAAC,EAAE,EAAE,YAAY,GAAG,IAAI,CAyJ1D"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAiCA,OAAO,KAAK,EAER,YAAY,EAKf,MAAM,SAAS,CAAA;AA4PhB,MAAM,CAAC,OAAO,UAAU,WAAW,CAAC,EAAE,EAAE,YAAY,GAAG,IAAI,CA8b1D"}