@fitchmultz/pi-mcp-adapter 5.0.0 → 6.0.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 +25 -1
- package/OAUTH.md +3 -3
- package/README.md +153 -85
- package/app-bridge.bundle.js +75 -33
- package/commands.ts +9 -6
- package/direct-tools.ts +25 -358
- package/dist/app-bridge.bundle.js +75 -33
- package/dist/commands.js +9 -6
- package/dist/direct-tools.d.ts +2 -4
- package/dist/direct-tools.js +21 -319
- package/dist/gateway-arguments.d.ts +33 -0
- package/dist/gateway-arguments.js +63 -0
- package/dist/index.js +181 -276
- package/dist/init.js +6 -20
- package/dist/mcp-code.d.ts +2 -1
- package/dist/mcp-code.js +87 -41
- package/dist/mcp-output-guard.d.ts +57 -2
- package/dist/mcp-output-guard.js +129 -24
- package/dist/mcp-panel.d.ts +1 -1
- package/dist/mcp-panel.js +34 -97
- package/dist/mcp-script-worker.mjs +5 -2
- package/dist/mcp-status.js +2 -1
- package/dist/metadata-cache.d.ts +1 -1
- package/dist/metadata-cache.js +25 -88
- package/dist/prompts.d.ts +1 -1
- package/dist/prompts.js +1 -1
- package/dist/proxy-modes.d.ts +40 -6
- package/dist/proxy-modes.js +270 -485
- package/dist/resource-tools.d.ts +15 -0
- package/dist/resource-tools.js +26 -1
- package/dist/sampling-handler.js +4 -1
- package/dist/search-ranking.d.ts +0 -2
- package/dist/search-ranking.js +66 -137
- package/dist/state.d.ts +1 -1
- package/dist/tool-loader.d.ts +32 -0
- package/dist/tool-loader.js +152 -0
- package/dist/tool-metadata.d.ts +67 -0
- package/dist/tool-metadata.js +23 -17
- package/dist/tool-registrar.d.ts +4 -4
- package/dist/tool-registrar.js +18 -13
- package/dist/tool-result-renderer.d.ts +3 -0
- package/dist/tool-result-renderer.js +8 -3
- package/dist/types.d.ts +11 -36
- package/dist/utils.js +2 -4
- package/gateway-arguments.ts +73 -0
- package/index.ts +166 -299
- package/init.ts +6 -20
- package/mcp-code.ts +71 -45
- package/mcp-output-guard.ts +145 -27
- package/mcp-panel.ts +38 -109
- package/mcp-script-worker.mjs +5 -2
- package/mcp-status.ts +2 -1
- package/metadata-cache.ts +31 -93
- package/package.json +14 -9
- package/prompts.ts +1 -1
- package/proxy-modes.ts +265 -517
- package/resource-tools.ts +36 -1
- package/sampling-handler.ts +4 -1
- package/scripts/build-app-bridge.mjs +15 -0
- package/scripts/build.mjs +3 -2
- package/scripts/prepare.mjs +1 -0
- package/search-ranking.ts +71 -135
- package/skills/mcp-scripting/SKILL.md +67 -20
- package/state.ts +1 -1
- package/tool-loader.ts +153 -0
- package/tool-metadata.ts +22 -17
- package/tool-registrar.ts +18 -13
- package/tool-result-renderer.ts +10 -2
- package/types.ts +15 -40
- package/utils.ts +2 -4
- package/dist/ts-shape.d.ts +0 -2
- package/dist/ts-shape.js +0 -147
- package/ts-shape.ts +0 -145
package/dist/mcp-panel.js
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { matchesKey, truncateToWidth, visibleWidth } from "@earendil-works/pi-tui";
|
|
2
2
|
import { copyToClipboard } from "@earendil-works/pi-coding-agent";
|
|
3
3
|
import { createPanelKeys } from "./panel-keys.js";
|
|
4
|
-
import { isServerDisabled, isToolAllowed } from "./types.js";
|
|
5
|
-
import { resourceNameToToolName } from "./resource-tools.js";
|
|
6
4
|
import { sanitizeTerminalText, stripOscSequences } from "./utils.js";
|
|
5
|
+
import { reconstructToolMetadata } from "./metadata-cache.js";
|
|
7
6
|
const DEFAULT_THEME = {
|
|
8
7
|
border: "2",
|
|
9
8
|
title: "2",
|
|
@@ -138,57 +137,24 @@ class McpPanel {
|
|
|
138
137
|
else if (globalDirect) {
|
|
139
138
|
toolFilter = globalDirect;
|
|
140
139
|
}
|
|
141
|
-
const tools = [];
|
|
142
|
-
if (serverCache && !this.authOnly && !isServerDisabled(definition)) {
|
|
143
|
-
for (const tool of serverCache.tools ?? []) {
|
|
144
|
-
if (!isToolAllowed(tool.name, serverName, this.prefix, definition.includeTools, definition.excludeTools)) {
|
|
145
|
-
continue;
|
|
146
|
-
}
|
|
147
|
-
const isDirect = toolFilter === true || (Array.isArray(toolFilter) && toolFilter.includes(tool.name));
|
|
148
|
-
tools.push({
|
|
149
|
-
name: tool.name,
|
|
150
|
-
description: tool.description ?? "",
|
|
151
|
-
isDirect,
|
|
152
|
-
wasDirect: isDirect,
|
|
153
|
-
estimatedTokens: estimateTokens(tool),
|
|
154
|
-
});
|
|
155
|
-
}
|
|
156
|
-
if (definition.exposeResources !== false) {
|
|
157
|
-
for (const resource of serverCache.resources ?? []) {
|
|
158
|
-
const baseName = `read_${resourceNameToToolName(resource.name)}`;
|
|
159
|
-
if (!isToolAllowed(baseName, serverName, this.prefix, definition.includeTools, definition.excludeTools)) {
|
|
160
|
-
continue;
|
|
161
|
-
}
|
|
162
|
-
const isDirect = toolFilter === true || (Array.isArray(toolFilter) && toolFilter.includes(baseName));
|
|
163
|
-
const ct = {
|
|
164
|
-
name: baseName,
|
|
165
|
-
...(resource.description !== undefined ? { description: resource.description } : {}),
|
|
166
|
-
};
|
|
167
|
-
tools.push({
|
|
168
|
-
name: baseName,
|
|
169
|
-
description: resource.description ?? `Read resource: ${resource.uri}`,
|
|
170
|
-
isDirect,
|
|
171
|
-
wasDirect: isDirect,
|
|
172
|
-
estimatedTokens: estimateTokens(ct),
|
|
173
|
-
});
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
140
|
const status = callbacks.getConnectionStatus(serverName);
|
|
178
141
|
const failureMessage = callbacks.getFailureMessage?.(serverName) ?? null;
|
|
179
|
-
|
|
142
|
+
const server = {
|
|
180
143
|
name: serverName,
|
|
181
144
|
expanded: false,
|
|
182
145
|
source: prov?.kind ?? "user",
|
|
183
146
|
...(prov?.importKind !== undefined ? { importKind: prov.importKind } : {}),
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
147
|
+
definition,
|
|
148
|
+
toolFilter,
|
|
149
|
+
resourceCount: 0,
|
|
187
150
|
connectionStatus: status,
|
|
188
151
|
failureMessage,
|
|
189
|
-
tools,
|
|
152
|
+
tools: [],
|
|
190
153
|
hasCachedData: !!serverCache,
|
|
191
|
-
}
|
|
154
|
+
};
|
|
155
|
+
this.servers.push(server);
|
|
156
|
+
if (serverCache && !this.authOnly)
|
|
157
|
+
this.rebuildServerTools(server, serverCache);
|
|
192
158
|
}
|
|
193
159
|
this.rebuildVisibleItems();
|
|
194
160
|
this.resetInactivityTimeout();
|
|
@@ -503,7 +469,6 @@ class McpPanel {
|
|
|
503
469
|
if (entry) {
|
|
504
470
|
this.rebuildServerTools(server, entry);
|
|
505
471
|
}
|
|
506
|
-
server.hasCachedData = true;
|
|
507
472
|
}
|
|
508
473
|
if (options.afterAuth) {
|
|
509
474
|
this.authNotice = connected && server.connectionStatus === "connected"
|
|
@@ -578,46 +543,22 @@ class McpPanel {
|
|
|
578
543
|
this.cursorIndex = Math.max(0, Math.min(this.visibleItems.length - 1, this.cursorIndex + delta));
|
|
579
544
|
}
|
|
580
545
|
rebuildServerTools(server, entry) {
|
|
581
|
-
const existingState = new Map();
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
description: tool.description ?? "",
|
|
594
|
-
isDirect,
|
|
595
|
-
wasDirect: prev !== undefined ? server.tools.find((t) => t.name === tool.name)?.wasDirect ?? false : false,
|
|
546
|
+
const existingState = new Map(server.tools.map(tool => [tool.name, tool]));
|
|
547
|
+
const metadata = reconstructToolMetadata(server.name, entry, this.prefix, server.definition);
|
|
548
|
+
server.resourceCount = metadata.filter(tool => tool.resourceUri !== undefined).length;
|
|
549
|
+
server.tools = metadata.filter(tool => tool.resourceUri === undefined).map(tool => {
|
|
550
|
+
const previous = existingState.get(tool.originalName);
|
|
551
|
+
const pinned = server.toolFilter === true
|
|
552
|
+
|| (Array.isArray(server.toolFilter) && server.toolFilter.includes(tool.originalName));
|
|
553
|
+
return {
|
|
554
|
+
name: tool.originalName,
|
|
555
|
+
description: tool.description,
|
|
556
|
+
isDirect: previous?.isDirect ?? pinned,
|
|
557
|
+
wasDirect: previous?.wasDirect ?? pinned,
|
|
596
558
|
estimatedTokens: estimateTokens(tool),
|
|
597
|
-
}
|
|
598
|
-
}
|
|
599
|
-
|
|
600
|
-
for (const resource of entry.resources ?? []) {
|
|
601
|
-
const baseName = `read_${resourceNameToToolName(resource.name)}`;
|
|
602
|
-
if (!isToolAllowed(baseName, server.name, this.prefix, server.includeTools, server.excludeTools)) {
|
|
603
|
-
continue;
|
|
604
|
-
}
|
|
605
|
-
const prev = existingState.get(baseName);
|
|
606
|
-
const isDirect = prev !== undefined ? prev : false;
|
|
607
|
-
const ct = {
|
|
608
|
-
name: baseName,
|
|
609
|
-
...(resource.description !== undefined ? { description: resource.description } : {}),
|
|
610
|
-
};
|
|
611
|
-
newTools.push({
|
|
612
|
-
name: baseName,
|
|
613
|
-
description: resource.description ?? `Read resource: ${resource.uri}`,
|
|
614
|
-
isDirect,
|
|
615
|
-
wasDirect: prev !== undefined ? server.tools.find((t) => t.name === baseName)?.wasDirect ?? false : false,
|
|
616
|
-
estimatedTokens: estimateTokens(ct),
|
|
617
|
-
});
|
|
618
|
-
}
|
|
619
|
-
}
|
|
620
|
-
server.tools = newTools;
|
|
559
|
+
};
|
|
560
|
+
});
|
|
561
|
+
server.hasCachedData = true;
|
|
621
562
|
this.rebuildVisibleItems();
|
|
622
563
|
this.updateDirty();
|
|
623
564
|
}
|
|
@@ -677,6 +618,9 @@ class McpPanel {
|
|
|
677
618
|
continue;
|
|
678
619
|
if (item.type === "server") {
|
|
679
620
|
lines.push(row(this.renderServerRow(server, isCursor)));
|
|
621
|
+
if (isCursor && !this.authOnly && server.resourceCount > 0) {
|
|
622
|
+
lines.push(row(fg(t.hint, " Resources: mcp actions resources / read-resource")));
|
|
623
|
+
}
|
|
680
624
|
if (isCursor && server.connectionStatus === "failed" && server.failureMessage) {
|
|
681
625
|
for (const line of this.wrapText(sanitizeDisplayText(server.failureMessage), innerW - 6)) {
|
|
682
626
|
lines.push(row(` ${fg(t.cancel, line)}`));
|
|
@@ -722,8 +666,9 @@ class McpPanel {
|
|
|
722
666
|
else {
|
|
723
667
|
const directCount = this.servers.reduce((sum, s) => sum + s.tools.filter((t) => t.isDirect).length, 0);
|
|
724
668
|
const totalTokens = this.servers.reduce((sum, s) => sum + s.tools.filter((t) => t.isDirect).reduce((ts, t) => ts + t.estimatedTokens, 0), 0);
|
|
725
|
-
const stats = directCount > 0 ? `${directCount}
|
|
669
|
+
const stats = directCount > 0 ? `${directCount} pinned ~${totalTokens.toLocaleString()} tokens` : "no pinned tools";
|
|
726
670
|
lines.push(row(fg(t.description, stats + (this.dirty ? fg(t.needsAuth, " (unsaved)") : ""))));
|
|
671
|
+
lines.push(row(fg(t.hint, "Pins load at startup; discover more with mcp_search.")));
|
|
727
672
|
}
|
|
728
673
|
}
|
|
729
674
|
lines.push(emptyRow());
|
|
@@ -737,7 +682,7 @@ class McpPanel {
|
|
|
737
682
|
]
|
|
738
683
|
: [
|
|
739
684
|
italic("↑↓") + " navigate",
|
|
740
|
-
italic("space") + "
|
|
685
|
+
italic("space") + " pin/unpin",
|
|
741
686
|
italic("⏎") + " expand/auth",
|
|
742
687
|
italic("ctrl+a") + " auth",
|
|
743
688
|
italic("ctrl+r") + " reconnect",
|
|
@@ -781,7 +726,7 @@ class McpPanel {
|
|
|
781
726
|
const importLabel = server.source === "import" ? fg(t.description, ` (${importKind})`) : "";
|
|
782
727
|
const statusLabel = this.renderConnectionStatus(server);
|
|
783
728
|
if (!server.hasCachedData && !this.authOnly) {
|
|
784
|
-
return `${prefix} ${nameStr}${importLabel} ${fg(t.description, "(
|
|
729
|
+
return `${prefix} ${nameStr}${importLabel}${statusLabel} ${fg(t.description, "(undiscovered)")}`;
|
|
785
730
|
}
|
|
786
731
|
const directCount = server.tools.filter((t) => t.isDirect).length;
|
|
787
732
|
const totalCount = server.tools.length;
|
|
@@ -792,16 +737,8 @@ class McpPanel {
|
|
|
792
737
|
else if (directCount > 0) {
|
|
793
738
|
toggleIcon = fg(t.needsAuth, "◐");
|
|
794
739
|
}
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
toolInfo = `${directCount}/${totalCount}`;
|
|
798
|
-
if (directCount > 0) {
|
|
799
|
-
const tokens = server.tools.filter((t) => t.isDirect).reduce((s, t) => s + t.estimatedTokens, 0);
|
|
800
|
-
toolInfo += ` ~${tokens.toLocaleString()}`;
|
|
801
|
-
}
|
|
802
|
-
toolInfo = fg(t.description, toolInfo);
|
|
803
|
-
}
|
|
804
|
-
return `${prefix} ${toggleIcon} ${nameStr}${importLabel} ${toolInfo}${statusLabel}`;
|
|
740
|
+
const toolInfo = this.authOnly ? "" : fg(t.description, `${totalCount} tool${totalCount === 1 ? "" : "s"}, ${directCount} pinned${server.resourceCount > 0 ? `, ${server.resourceCount} resource${server.resourceCount === 1 ? "" : "s"}` : ""}`);
|
|
741
|
+
return `${prefix} ${toggleIcon} ${nameStr}${importLabel}${statusLabel} ${toolInfo}`;
|
|
805
742
|
}
|
|
806
743
|
selectedServerHasFailureMessage() {
|
|
807
744
|
const item = this.visibleItems[this.cursorIndex];
|
|
@@ -69,7 +69,7 @@ const tools = new Proxy(Object.create(null), {
|
|
|
69
69
|
return async (input) => request("search", { input });
|
|
70
70
|
}
|
|
71
71
|
if (property === "call") {
|
|
72
|
-
return async (path, args) => {
|
|
72
|
+
return async (path, args, server) => {
|
|
73
73
|
// Invalid paths never reach dispatch and therefore never appear in the call trace.
|
|
74
74
|
if (typeof path !== "string" || path.trim() === "") {
|
|
75
75
|
return {
|
|
@@ -80,9 +80,12 @@ const tools = new Proxy(Object.create(null), {
|
|
|
80
80
|
},
|
|
81
81
|
};
|
|
82
82
|
}
|
|
83
|
-
|
|
83
|
+
if (server !== undefined && (typeof server !== "string" || !server)) return { ok: false, error: { code: "invalid_arguments", message: "server must be a non-empty string" } };
|
|
84
|
+
return request("call", { path, args, server });
|
|
84
85
|
};
|
|
85
86
|
}
|
|
87
|
+
if (property === "resources" || property === "listResources") return async (input) => request("resources", { input });
|
|
88
|
+
if (property === "readResource" || property === "readResult") return async (input) => request(property, { input });
|
|
86
89
|
if (property === "describe") {
|
|
87
90
|
return async (input) => request("describe", { input });
|
|
88
91
|
}
|
package/dist/mcp-status.js
CHANGED
|
@@ -21,7 +21,7 @@ export function createMcpStatusSnapshot(state) {
|
|
|
21
21
|
const disabled = definition?.disabled === true;
|
|
22
22
|
const connection = disabled ? undefined : state.manager.getConnection(name);
|
|
23
23
|
const metadata = disabled ? undefined : state.toolMetadata.get(name);
|
|
24
|
-
const toolCount = metadata?.length ?? (connection?.status === "connected" ? connection.tools.length : 0);
|
|
24
|
+
const toolCount = metadata?.filter(tool => !tool.resourceUri).length ?? (connection?.status === "connected" ? connection.tools.length : 0);
|
|
25
25
|
const resourceCount = disabled
|
|
26
26
|
? undefined
|
|
27
27
|
: state.resourceCounts?.get(name) ?? (connection?.status === "connected" ? connection.resources.length : undefined);
|
|
@@ -51,6 +51,7 @@ export function createMcpStatusSnapshot(state) {
|
|
|
51
51
|
name,
|
|
52
52
|
status,
|
|
53
53
|
toolCount,
|
|
54
|
+
catalogKnown: metadata !== undefined || connection?.status === "connected",
|
|
54
55
|
...(resourceCount !== undefined ? { resourceCount } : {}),
|
|
55
56
|
...(status === "failed" && failedAgoSeconds !== undefined ? { failedAgoSeconds } : {}),
|
|
56
57
|
disabled,
|
package/dist/metadata-cache.d.ts
CHANGED
|
@@ -11,7 +11,7 @@ export declare function parseDirectToolSelectors(selectors: string[]): {
|
|
|
11
11
|
tools: Map<string, Set<string>>;
|
|
12
12
|
};
|
|
13
13
|
export declare function getMissingConfiguredDirectToolServers(config: McpConfig, cache: MetadataCache | null, envOverride?: string[]): string[];
|
|
14
|
-
export declare function reconstructToolMetadata(serverName: string, entry: ServerCacheEntry, prefix: ToolPrefix, definition: Pick<ServerEntry, "exposeResources" | "includeTools" | "excludeTools" | "toolPrefix">): ToolMetadata[];
|
|
14
|
+
export declare function reconstructToolMetadata(serverName: string, entry: ServerCacheEntry, prefix: ToolPrefix, definition: Pick<ServerEntry, "exposeResources" | "includeTools" | "excludeTools" | "toolPrefix" | "disabled">): ToolMetadata[];
|
|
15
15
|
export declare function serializeTools(tools: McpTool[]): CachedTool[];
|
|
16
16
|
export declare function serializeResources(resources: McpResource[]): CachedResource[];
|
|
17
17
|
export declare function serializePrompts(prompts: McpPrompt[]): CachedPrompt[];
|
package/dist/metadata-cache.js
CHANGED
|
@@ -3,12 +3,11 @@ import { existsSync, readFileSync, writeFileSync, renameSync, mkdirSync } from "
|
|
|
3
3
|
import { dirname } from "node:path";
|
|
4
4
|
import { getAdapterPath } from "./agent-dir.js";
|
|
5
5
|
import { createHash } from "node:crypto";
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
const CACHE_VERSION = 1;
|
|
6
|
+
import { formatPromptCommandName, isServerDisabled, resolveToolPrefix } from "./types.js";
|
|
7
|
+
import { buildToolMetadata } from "./tool-metadata.js";
|
|
8
|
+
import { interpolateEnvRecord, resolveBearerToken, resolveConfigPath, resolveServerUrl, } from "./utils.js";
|
|
9
|
+
// Version 2 stores raw descriptors; version 1 readers cannot enforce raw UI visibility.
|
|
10
|
+
const CACHE_VERSION = 2;
|
|
12
11
|
const CACHE_MAX_AGE_MS = 7 * 24 * 60 * 60 * 1000;
|
|
13
12
|
export function getMetadataCachePath() {
|
|
14
13
|
return getAdapterPath("mcp-cache.json");
|
|
@@ -23,7 +22,7 @@ export function loadMetadataCache(enabled = true) {
|
|
|
23
22
|
const raw = JSON.parse(readFileSync(cachePath, "utf-8"));
|
|
24
23
|
if (!raw || typeof raw !== "object")
|
|
25
24
|
return null;
|
|
26
|
-
if (raw.version !== CACHE_VERSION)
|
|
25
|
+
if (raw.version !== 1 && raw.version !== CACHE_VERSION)
|
|
27
26
|
return null;
|
|
28
27
|
if (!raw.servers || typeof raw.servers !== "object")
|
|
29
28
|
return null;
|
|
@@ -43,7 +42,7 @@ export function saveMetadataCache(cache, enabled = true) {
|
|
|
43
42
|
try {
|
|
44
43
|
if (existsSync(cachePath)) {
|
|
45
44
|
const existing = JSON.parse(readFileSync(cachePath, "utf-8"));
|
|
46
|
-
if (existing && existing.version === CACHE_VERSION && existing.servers) {
|
|
45
|
+
if (existing && (existing.version === 1 || existing.version === CACHE_VERSION) && existing.servers) {
|
|
47
46
|
merged.servers = { ...existing.servers };
|
|
48
47
|
}
|
|
49
48
|
}
|
|
@@ -139,83 +138,29 @@ export function getMissingConfiguredDirectToolServers(config, cache, envOverride
|
|
|
139
138
|
return missing;
|
|
140
139
|
}
|
|
141
140
|
export function reconstructToolMetadata(serverName, entry, prefix, definition) {
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
if (!isUiToolVisibleToModel(tool.uiVisibility)) {
|
|
149
|
-
continue;
|
|
150
|
-
}
|
|
151
|
-
if (!isToolAllowed(tool.name, serverName, effectivePrefix, definition.includeTools, definition.excludeTools)) {
|
|
152
|
-
continue;
|
|
153
|
-
}
|
|
154
|
-
const name = formatToolName(tool.name, serverName, effectivePrefix);
|
|
155
|
-
if (seenNames.has(name)) {
|
|
156
|
-
continue;
|
|
157
|
-
}
|
|
158
|
-
seenNames.add(name);
|
|
159
|
-
metadata.push({
|
|
160
|
-
name,
|
|
161
|
-
originalName: tool.name,
|
|
162
|
-
description: tool.description ?? "",
|
|
163
|
-
...(tool.inputSchema !== undefined ? { inputSchema: tool.inputSchema } : {}),
|
|
164
|
-
...(tool.annotations !== undefined ? { annotations: tool.annotations } : {}),
|
|
165
|
-
...(tool.uiResourceUri !== undefined ? { uiResourceUri: tool.uiResourceUri } : {}),
|
|
166
|
-
...(tool.uiVisibility !== undefined ? { uiVisibility: tool.uiVisibility } : {}),
|
|
167
|
-
...(tool.uiStreamMode !== undefined ? { uiStreamMode: tool.uiStreamMode } : {}),
|
|
168
|
-
});
|
|
169
|
-
}
|
|
170
|
-
if (definition.exposeResources !== false) {
|
|
171
|
-
for (const resource of entry.resources ?? []) {
|
|
172
|
-
if (!resource?.name || !resource?.uri)
|
|
173
|
-
continue;
|
|
174
|
-
const baseName = `read_${resourceNameToToolName(resource.name)}`;
|
|
175
|
-
if (!isToolAllowed(baseName, serverName, effectivePrefix, definition.includeTools, definition.excludeTools)) {
|
|
176
|
-
continue;
|
|
177
|
-
}
|
|
178
|
-
const name = formatToolName(baseName, serverName, effectivePrefix);
|
|
179
|
-
if (seenNames.has(name)) {
|
|
180
|
-
continue;
|
|
181
|
-
}
|
|
182
|
-
seenNames.add(name);
|
|
183
|
-
metadata.push({
|
|
184
|
-
name,
|
|
185
|
-
originalName: baseName,
|
|
186
|
-
description: resource.description ?? `Read resource: ${resource.uri}`,
|
|
187
|
-
resourceUri: resource.uri,
|
|
188
|
-
});
|
|
189
|
-
}
|
|
141
|
+
return buildToolMetadata((entry.tools ?? []).filter(tool => tool?.name).map(restoreCachedTool), entry.resources ?? [], definition, serverName, prefix).metadata;
|
|
142
|
+
}
|
|
143
|
+
function restoreCachedTool(tool) {
|
|
144
|
+
const { uiResourceUri, uiVisibility, uiStreamMode, ...descriptor } = tool;
|
|
145
|
+
if (descriptor._meta !== undefined || (uiResourceUri === undefined && uiVisibility === undefined && uiStreamMode === undefined)) {
|
|
146
|
+
return descriptor;
|
|
190
147
|
}
|
|
191
|
-
return
|
|
148
|
+
return {
|
|
149
|
+
...descriptor,
|
|
150
|
+
_meta: {
|
|
151
|
+
ui: {
|
|
152
|
+
...(uiResourceUri !== undefined ? { resourceUri: uiResourceUri } : {}),
|
|
153
|
+
...(uiVisibility !== undefined ? { visibility: uiVisibility } : {}),
|
|
154
|
+
...(uiStreamMode !== undefined ? { "pi-mcp-adapter.streamMode": uiStreamMode } : {}),
|
|
155
|
+
},
|
|
156
|
+
},
|
|
157
|
+
};
|
|
192
158
|
}
|
|
193
159
|
export function serializeTools(tools) {
|
|
194
|
-
return tools
|
|
195
|
-
.filter(t => t?.name)
|
|
196
|
-
.map(t => {
|
|
197
|
-
const uiResourceUri = tryGetToolUiResourceUri(t);
|
|
198
|
-
const uiVisibility = extractUiToolVisibility(t._meta);
|
|
199
|
-
const uiStreamMode = extractToolUiStreamMode(t._meta);
|
|
200
|
-
return {
|
|
201
|
-
name: t.name,
|
|
202
|
-
...(t.description !== undefined ? { description: t.description } : {}),
|
|
203
|
-
...(t.inputSchema !== undefined ? { inputSchema: t.inputSchema } : {}),
|
|
204
|
-
...(t.annotations !== undefined ? { annotations: t.annotations } : {}),
|
|
205
|
-
...(uiResourceUri !== undefined ? { uiResourceUri } : {}),
|
|
206
|
-
...(uiVisibility !== undefined ? { uiVisibility } : {}),
|
|
207
|
-
...(uiStreamMode !== undefined ? { uiStreamMode } : {}),
|
|
208
|
-
};
|
|
209
|
-
});
|
|
160
|
+
return tools.filter(tool => tool?.name);
|
|
210
161
|
}
|
|
211
162
|
export function serializeResources(resources) {
|
|
212
|
-
return resources
|
|
213
|
-
.filter(r => r?.name && r?.uri)
|
|
214
|
-
.map(r => ({
|
|
215
|
-
uri: r.uri,
|
|
216
|
-
name: r.name,
|
|
217
|
-
...(r.description !== undefined ? { description: r.description } : {}),
|
|
218
|
-
}));
|
|
163
|
+
return resources.filter(resource => resource?.name && resource?.uri);
|
|
219
164
|
}
|
|
220
165
|
export function serializePrompts(prompts) {
|
|
221
166
|
return (prompts ?? [])
|
|
@@ -267,11 +212,3 @@ function stableStringify(value) {
|
|
|
267
212
|
const keys = Object.keys(obj).sort();
|
|
268
213
|
return `{${keys.map(k => `${JSON.stringify(k)}:${stableStringify(obj[k])}`).join(",")}}`;
|
|
269
214
|
}
|
|
270
|
-
function tryGetToolUiResourceUri(tool) {
|
|
271
|
-
try {
|
|
272
|
-
return getToolUiResourceUri({ _meta: tool._meta });
|
|
273
|
-
}
|
|
274
|
-
catch {
|
|
275
|
-
return undefined;
|
|
276
|
-
}
|
|
277
|
-
}
|
package/dist/prompts.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ import type { McpExtensionState } from "./state.ts";
|
|
|
4
4
|
import { type McpConfig, type PromptMetadata } from "./types.ts";
|
|
5
5
|
/**
|
|
6
6
|
* Resolve prompt metadata for slash-command registration at extension load
|
|
7
|
-
* time.
|
|
7
|
+
* time. Like typed tool registration, reads the persistent metadata cache so
|
|
8
8
|
* commands are available before any server connects.
|
|
9
9
|
*/
|
|
10
10
|
export declare function resolveCachedPrompts(config: McpConfig, cacheEnabled?: boolean): PromptMetadata[];
|
package/dist/prompts.js
CHANGED
|
@@ -5,7 +5,7 @@ import { logger } from "./logger.js";
|
|
|
5
5
|
import { truncateAtWord } from "./utils.js";
|
|
6
6
|
/**
|
|
7
7
|
* Resolve prompt metadata for slash-command registration at extension load
|
|
8
|
-
* time.
|
|
8
|
+
* time. Like typed tool registration, reads the persistent metadata cache so
|
|
9
9
|
* commands are available before any server connects.
|
|
10
10
|
*/
|
|
11
11
|
export function resolveCachedPrompts(config, cacheEnabled = true) {
|
package/dist/proxy-modes.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { AgentToolResult, ToolInfo } from "@earendil-works/pi-coding-agent";
|
|
2
2
|
import type { McpExtensionState } from "./state.ts";
|
|
3
|
+
import type { ServerConnection } from "./server-manager.ts";
|
|
3
4
|
import type { ToolMetadata, McpOperationContext, McpToolCallIdentity } from "./types.ts";
|
|
4
5
|
import { type SessionRecoveryDeps } from "./session-recovery.ts";
|
|
5
6
|
type ProxyToolResult = AgentToolResult<Record<string, unknown>>;
|
|
@@ -7,7 +8,7 @@ export declare function executeUiMessages(state: McpExtensionState): ProxyToolRe
|
|
|
7
8
|
export declare function executeStatus(state: McpExtensionState): ProxyToolResult;
|
|
8
9
|
export declare function executeAuthStart(state: McpExtensionState, serverName: string, signal?: AbortSignal): Promise<ProxyToolResult>;
|
|
9
10
|
export declare function executeAuthComplete(state: McpExtensionState, serverName: string, input?: string, signal?: AbortSignal): Promise<ProxyToolResult>;
|
|
10
|
-
export declare function executeDescribe(state: McpExtensionState, toolName: string): ProxyToolResult;
|
|
11
|
+
export declare function executeDescribe(state: McpExtensionState, toolName: string, serverFilter?: string): ProxyToolResult;
|
|
11
12
|
export declare function executeSearch(state: McpExtensionState, query: string, server?: string, includeSchemas?: boolean, limit?: number, offset?: number): ProxyToolResult;
|
|
12
13
|
export declare function executeList(state: McpExtensionState, server: string, limit?: number, offset?: number): ProxyToolResult;
|
|
13
14
|
export declare function executeInstructions(state: McpExtensionState, server: string): ProxyToolResult;
|
|
@@ -24,15 +25,48 @@ interface ToolCallOptions extends McpToolCallIdentity {
|
|
|
24
25
|
recoverAuthConnection: NonNullable<SessionRecoveryDeps["onNeedsAuth"]>;
|
|
25
26
|
authRequiredMessage: () => string;
|
|
26
27
|
autoAuthAttempted: () => boolean;
|
|
27
|
-
|
|
28
|
+
raw?: boolean;
|
|
28
29
|
}
|
|
29
30
|
/**
|
|
30
31
|
* Executes an already-approved tool call against a connected server.
|
|
31
32
|
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
* auth strategy, approval) differs between them and stays with the caller.
|
|
33
|
+
* Direct, gateway, resource and script calls share executeCall preparation.
|
|
34
|
+
* Raw scripts skip content rendering but retain protocol results and artifacts.
|
|
35
35
|
*/
|
|
36
36
|
export declare function runToolCall(state: McpExtensionState, serverName: string, target: ToolCallTarget, args: Record<string, unknown> | undefined, options: ToolCallOptions): Promise<ProxyToolResult>;
|
|
37
|
-
export
|
|
37
|
+
export interface ExecuteCallOptions {
|
|
38
|
+
exactOriginalName?: boolean;
|
|
39
|
+
resourceUri?: string;
|
|
40
|
+
/** Scripts receive the raw protocol result without model-facing content transformation. */
|
|
41
|
+
raw?: boolean;
|
|
42
|
+
}
|
|
43
|
+
/** Connect/auth once for calls and resource discovery. Recovery stays bounded by withSessionRecovery. */
|
|
44
|
+
export declare function prepareMcpConnection(state: McpExtensionState, serverName: string, signal?: AbortSignal): Promise<{
|
|
45
|
+
error: {
|
|
46
|
+
content: {
|
|
47
|
+
type: "text";
|
|
48
|
+
text: string;
|
|
49
|
+
}[];
|
|
50
|
+
details: {
|
|
51
|
+
mode: string;
|
|
52
|
+
error: string;
|
|
53
|
+
server: string;
|
|
54
|
+
message: string;
|
|
55
|
+
};
|
|
56
|
+
};
|
|
57
|
+
connection?: never;
|
|
58
|
+
recoverAuthConnection?: never;
|
|
59
|
+
autoAuthAttempted?: never;
|
|
60
|
+
} | {
|
|
61
|
+
error: ProxyToolResult;
|
|
62
|
+
connection?: never;
|
|
63
|
+
recoverAuthConnection?: never;
|
|
64
|
+
autoAuthAttempted?: never;
|
|
65
|
+
} | {
|
|
66
|
+
connection: ServerConnection;
|
|
67
|
+
recoverAuthConnection: (serverName: string, signal?: AbortSignal, challenge?: import("./session-recovery.ts").AuthChallengeContext) => Promise<ServerConnection | undefined>;
|
|
68
|
+
autoAuthAttempted: () => boolean;
|
|
69
|
+
error?: never;
|
|
70
|
+
}>;
|
|
71
|
+
export declare function executeCall(state: McpExtensionState, toolName: string, args?: Record<string, unknown>, serverOverride?: string, getPiTools?: () => ToolInfo[], signal?: AbortSignal, identity?: McpToolCallIdentity, beforeDispatch?: (signal: AbortSignal | undefined, operation: McpOperationContext) => Promise<void>, options?: ExecuteCallOptions): Promise<ProxyToolResult>;
|
|
38
72
|
export {};
|