@fitchmultz/pi-mcp-adapter 6.0.0 → 7.1.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 +33 -0
- package/OAUTH.md +1 -1
- package/README.md +27 -18
- package/dist/app-bridge.bundle.js +14 -14
- package/dist/config.js +41 -16
- package/dist/direct-tools.js +1 -1
- package/dist/gateway-arguments.d.ts +1 -1
- package/dist/index.js +38 -59
- package/dist/lifecycle.d.ts +2 -2
- package/dist/lifecycle.js +2 -2
- package/dist/mcp-auth-flow.js +2 -2
- package/dist/mcp-auth.d.ts +1 -1
- package/dist/mcp-auth.js +3 -3
- package/dist/mcp-code.d.ts +6 -6
- package/dist/mcp-code.js +11 -10
- package/dist/mcp-oauth-provider.d.ts +5 -5
- package/dist/mcp-oauth-provider.js +5 -5
- package/dist/mcp-output-guard.d.ts +1 -1
- package/dist/mcp-output-guard.js +1 -1
- package/dist/mcp-panel.d.ts +2 -2
- package/dist/mcp-panel.js +2 -2
- package/dist/mcp-setup-panel.d.ts +5 -4
- package/dist/mcp-setup-panel.js +15 -7
- package/dist/mcp-trace.d.ts +1 -1
- package/dist/mcp-trace.js +1 -1
- package/dist/npx-resolver.js +8 -4
- package/dist/proxy-modes.d.ts +2 -2
- package/dist/proxy-modes.js +20 -19
- package/dist/sampling-handler.js +1 -0
- package/dist/search-ranking.js +6 -2
- package/dist/server-manager.d.ts +2 -2
- package/dist/server-manager.js +44 -27
- package/dist/session-recovery.d.ts +7 -4
- package/dist/session-recovery.js +76 -10
- package/dist/tool-loader.d.ts +7 -2
- package/dist/tool-loader.js +56 -5
- package/dist/tool-metadata.d.ts +43 -43
- package/dist/tool-result-renderer.d.ts +3 -3
- package/dist/tool-result-renderer.js +3 -3
- package/dist/ui-resource-handler.d.ts +2 -2
- package/dist/ui-resource-handler.js +2 -2
- package/dist/ui-server.js +5 -4
- package/dist/ui-stream-types.d.ts +8 -8
- package/dist/unix-socket-transport.d.ts +1 -1
- package/dist/unix-socket-transport.js +1 -1
- package/dist/utils.d.ts +1 -0
- package/dist/utils.js +14 -0
- package/package.json +34 -98
- package/skills/mcp-scripting/SKILL.md +2 -0
- package/abort.ts +0 -34
- package/agent-dir.ts +0 -24
- package/app-bridge.bundle.js +0 -109
- package/banner.png +0 -0
- package/checkpoint.ts +0 -55
- package/commands.ts +0 -622
- package/config.ts +0 -1204
- package/consent-manager.ts +0 -25
- package/direct-tools.ts +0 -75
- package/elicitation-handler.ts +0 -349
- package/error-signal.ts +0 -21
- package/gateway-arguments.ts +0 -73
- package/glimpse-ui.ts +0 -80
- package/host-html-template.ts +0 -456
- package/index.ts +0 -767
- package/init.ts +0 -613
- package/legacy-migration.ts +0 -47
- package/lifecycle.ts +0 -165
- package/logger.ts +0 -127
- package/mcp-auth-flow.ts +0 -975
- package/mcp-auth.ts +0 -793
- package/mcp-callback-server.ts +0 -450
- package/mcp-code.ts +0 -412
- package/mcp-keyring-helper.cjs +0 -89
- package/mcp-oauth-provider.ts +0 -774
- package/mcp-output-guard.ts +0 -530
- package/mcp-panel.ts +0 -907
- package/mcp-script-worker.mjs +0 -131
- package/mcp-setup-panel.ts +0 -666
- package/mcp-status.ts +0 -110
- package/mcp-trace.ts +0 -295
- package/metadata-cache.ts +0 -271
- package/npx-resolver.ts +0 -488
- package/onboarding-state.ts +0 -58
- package/panel-keys.ts +0 -37
- package/prompts.ts +0 -337
- package/proxy-modes.ts +0 -1109
- package/resource-tools.ts +0 -52
- package/runtime-owner.ts +0 -123
- package/sampling-handler.ts +0 -276
- package/scripts/build-app-bridge.mjs +0 -15
- package/scripts/build.mjs +0 -132
- package/scripts/prepare.mjs +0 -103
- package/search-ranking.ts +0 -132
- package/server-manager.ts +0 -1320
- package/session-recovery.ts +0 -316
- package/state.ts +0 -64
- package/tool-approval.ts +0 -78
- package/tool-loader.ts +0 -153
- package/tool-metadata.ts +0 -240
- package/tool-registrar.ts +0 -74
- package/tool-result-renderer.ts +0 -294
- package/tsconfig.build.json +0 -13
- package/tsconfig.json +0 -16
- package/types.ts +0 -785
- package/ui-resource-handler.ts +0 -249
- package/ui-server.ts +0 -808
- package/ui-session.ts +0 -568
- package/ui-stream-types.ts +0 -89
- package/ui-tool-visibility.ts +0 -25
- package/unix-socket-transport.ts +0 -85
- package/utils.ts +0 -307
package/dist/config.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
// config.ts - Config loading with import support
|
|
2
|
-
import { existsSync, readFileSync, writeFileSync, mkdirSync, realpathSync, renameSync } from "node:fs";
|
|
2
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync, realpathSync, renameSync, statSync, chmodSync } from "node:fs";
|
|
3
|
+
import { randomUUID } from "node:crypto";
|
|
3
4
|
import { homedir } from "node:os";
|
|
4
5
|
import { dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
6
|
+
import { isDeepStrictEqual } from "node:util";
|
|
5
7
|
import { parse as parseToml } from "smol-toml";
|
|
6
8
|
import stripJsonComments from "strip-json-comments";
|
|
7
9
|
import { getAdapterPath } from "./agent-dir.js";
|
|
@@ -367,6 +369,14 @@ function mergeServerMaps(base, next) {
|
|
|
367
369
|
delete baseEntry.oauth;
|
|
368
370
|
}
|
|
369
371
|
}
|
|
372
|
+
// Stdio env belongs to the program that received it, not just the server name.
|
|
373
|
+
if (existing?.command && ((definition.command !== undefined && definition.command !== existing.command)
|
|
374
|
+
|| (definition.args !== undefined && !isDeepStrictEqual(definition.args, existing.args ?? []))
|
|
375
|
+
|| (definition.cwd !== undefined && definition.cwd !== existing.cwd))) {
|
|
376
|
+
if (baseEntry === existing)
|
|
377
|
+
baseEntry = { ...existing };
|
|
378
|
+
delete baseEntry.env;
|
|
379
|
+
}
|
|
370
380
|
merged[name] = { ...baseEntry, ...definition };
|
|
371
381
|
}
|
|
372
382
|
return merged;
|
|
@@ -533,8 +543,10 @@ function mergeOpenCodeConfigs(base, next) {
|
|
|
533
543
|
delete safeBase.cwd;
|
|
534
544
|
}
|
|
535
545
|
}
|
|
546
|
+
if (Object.hasOwn(override, "cwd") && override.cwd !== safeBase.cwd)
|
|
547
|
+
delete safeBase.environment;
|
|
536
548
|
const mergedEntry = { ...safeBase, ...override };
|
|
537
|
-
for (const field of ["
|
|
549
|
+
for (const field of ["headers", "oauth"]) {
|
|
538
550
|
const baseField = safeBase[field];
|
|
539
551
|
const nextField = override[field];
|
|
540
552
|
if (baseField && typeof baseField === "object" && !Array.isArray(baseField)
|
|
@@ -714,24 +726,37 @@ function buildConfigWritePreview(filePath, nextRaw) {
|
|
|
714
726
|
function readRawConfigObject(filePath) {
|
|
715
727
|
if (!existsSync(filePath))
|
|
716
728
|
return {};
|
|
729
|
+
let raw;
|
|
717
730
|
try {
|
|
718
|
-
|
|
719
|
-
return raw && typeof raw === "object" && !Array.isArray(raw) ? raw : {};
|
|
731
|
+
raw = parseJsonConfig(readFileSync(filePath, "utf-8"));
|
|
720
732
|
}
|
|
721
|
-
catch {
|
|
722
|
-
|
|
733
|
+
catch (error) {
|
|
734
|
+
throw new Error(`Cannot read MCP config at ${filePath}: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
|
|
735
|
+
}
|
|
736
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
|
|
737
|
+
throw new Error(`Invalid MCP config at ${filePath}: expected an object`);
|
|
723
738
|
}
|
|
739
|
+
return raw;
|
|
724
740
|
}
|
|
725
741
|
function writeRawConfigObject(filePath, raw) {
|
|
726
742
|
mkdirSync(dirname(filePath), { recursive: true });
|
|
727
|
-
const
|
|
728
|
-
|
|
743
|
+
const existingMode = existsSync(filePath) ? statSync(filePath).mode & 0o7777 : undefined;
|
|
744
|
+
const tmpPath = `${filePath}.${randomUUID()}.tmp`;
|
|
745
|
+
writeFileSync(tmpPath, `${JSON.stringify(raw, null, 2)}\n`, {
|
|
746
|
+
encoding: "utf-8",
|
|
747
|
+
mode: existingMode ?? 0o666,
|
|
748
|
+
flag: "wx",
|
|
749
|
+
});
|
|
750
|
+
if (existingMode !== undefined)
|
|
751
|
+
chmodSync(tmpPath, existingMode);
|
|
729
752
|
renameSync(tmpPath, filePath);
|
|
730
753
|
}
|
|
731
|
-
function getServersObject(raw) {
|
|
732
|
-
const existing = raw.mcpServers
|
|
754
|
+
function getServersObject(raw, filePath) {
|
|
755
|
+
const existing = raw.mcpServers !== undefined ? raw.mcpServers
|
|
756
|
+
: raw["mcp-servers"] !== undefined ? raw["mcp-servers"]
|
|
757
|
+
: {};
|
|
733
758
|
if (!existing || typeof existing !== "object" || Array.isArray(existing)) {
|
|
734
|
-
|
|
759
|
+
throw new Error(`Invalid MCP config at ${filePath}: mcpServers must be an object`);
|
|
735
760
|
}
|
|
736
761
|
return existing;
|
|
737
762
|
}
|
|
@@ -886,7 +911,7 @@ export function previewCompatibilityImports(importKinds, overridePath) {
|
|
|
886
911
|
const currentImports = Array.isArray(raw.imports) ? raw.imports.filter((value) => typeof value === "string") : [];
|
|
887
912
|
const merged = [...new Set([...currentImports, ...importKinds])];
|
|
888
913
|
const nextRaw = { ...raw, imports: merged };
|
|
889
|
-
setServersObject(nextRaw, getServersObject(nextRaw));
|
|
914
|
+
setServersObject(nextRaw, getServersObject(nextRaw, targetPath));
|
|
890
915
|
return buildConfigWritePreview(targetPath, nextRaw);
|
|
891
916
|
}
|
|
892
917
|
export function ensureCompatibilityImports(importKinds, overridePath) {
|
|
@@ -899,7 +924,7 @@ export function ensureCompatibilityImports(importKinds, overridePath) {
|
|
|
899
924
|
return { path: targetPath, added: [] };
|
|
900
925
|
}
|
|
901
926
|
raw.imports = merged;
|
|
902
|
-
const servers = getServersObject(raw);
|
|
927
|
+
const servers = getServersObject(raw, targetPath);
|
|
903
928
|
setServersObject(raw, servers);
|
|
904
929
|
writeRawConfigObject(targetPath, raw);
|
|
905
930
|
return { path: targetPath, added };
|
|
@@ -923,14 +948,14 @@ export function writeStarterProjectConfig(cwd = process.cwd()) {
|
|
|
923
948
|
export function previewSharedServerEntry(filePath, serverName, entry) {
|
|
924
949
|
const raw = readRawConfigObject(filePath);
|
|
925
950
|
const nextRaw = { ...raw };
|
|
926
|
-
const servers = getServersObject(nextRaw);
|
|
951
|
+
const servers = getServersObject(nextRaw, filePath);
|
|
927
952
|
servers[serverName] = entry;
|
|
928
953
|
setServersObject(nextRaw, servers);
|
|
929
954
|
return buildConfigWritePreview(filePath, nextRaw);
|
|
930
955
|
}
|
|
931
956
|
export function writeSharedServerEntry(filePath, serverName, entry) {
|
|
932
957
|
const raw = readRawConfigObject(filePath);
|
|
933
|
-
const servers = getServersObject(raw);
|
|
958
|
+
const servers = getServersObject(raw, filePath);
|
|
934
959
|
servers[serverName] = entry;
|
|
935
960
|
setServersObject(raw, servers);
|
|
936
961
|
writeRawConfigObject(filePath, raw);
|
|
@@ -991,7 +1016,7 @@ export function writeDirectToolsConfig(changes, provenance) {
|
|
|
991
1016
|
}
|
|
992
1017
|
for (const [filePath, entries] of byPath) {
|
|
993
1018
|
const raw = readRawConfigObject(filePath);
|
|
994
|
-
const servers = getServersObject(raw);
|
|
1019
|
+
const servers = getServersObject(raw, filePath);
|
|
995
1020
|
for (const { name, value } of entries) {
|
|
996
1021
|
// Keep inherited connection details in their source file.
|
|
997
1022
|
servers[name] = { ...servers[name], directTools: value };
|
package/dist/direct-tools.js
CHANGED
|
@@ -15,7 +15,7 @@ export function directToolSelection(config, serverName, envOverride) {
|
|
|
15
15
|
export function buildProxyDescription(config) {
|
|
16
16
|
const servers = Object.entries(config.mcpServers).filter(([, definition]) => !isServerDisabled(definition)).map(([name]) => name).sort();
|
|
17
17
|
return [
|
|
18
|
-
|
|
18
|
+
'MCP gateway. Use mcp_search to discover typed tools; enable mcp_script with mcp_search({ enable: ["script"] }) for multi-call composition. Native Pi tools are called directly.',
|
|
19
19
|
`Configured servers: ${servers.join(", ") || "none"}. Catalog discovery is lazy.`,
|
|
20
20
|
"Actions: status; list/search/describe; call (tool,args,server?); connect (server); instructions (server); resources (server); read-resource (server,uri); read-result (ref,path?,fields?,offset?,limit?); auth-start/auth-complete (server,args?); ui-messages.",
|
|
21
21
|
"Use call when a discovered direct tool is unavailable in this host. read-result reads a retained response without repeating the remote operation.",
|
|
@@ -15,7 +15,7 @@ export type GatewayArguments = {
|
|
|
15
15
|
fields?: string[];
|
|
16
16
|
};
|
|
17
17
|
export declare const gatewayParameters: Type.TObject<{
|
|
18
|
-
action: Type.TUnsafe<"
|
|
18
|
+
action: Type.TUnsafe<"auth-complete" | "auth-start" | "call" | "connect" | "describe" | "instructions" | "list" | "read-resource" | "read-result" | "resources" | "search" | "status" | "ui-messages">;
|
|
19
19
|
server: Type.TOptional<Type.TString>;
|
|
20
20
|
tool: Type.TOptional<Type.TString>;
|
|
21
21
|
args: Type.TOptional<Type.TObject<{}>>;
|
package/dist/index.js
CHANGED
|
@@ -19,7 +19,7 @@ import { createToolLoader, supportsNativeAsync } from "./tool-loader.js";
|
|
|
19
19
|
import { gatewayParameters, prepareGatewayArguments } from "./gateway-arguments.js";
|
|
20
20
|
import { executeResourceList, executeResourceRead } from "./resource-tools.js";
|
|
21
21
|
import { guardMcpOutput, guardedMcpDetails, readMcpResult, resolveMcpOutputGuardOptions } from "./mcp-output-guard.js";
|
|
22
|
-
import { abortable } from "./abort.js";
|
|
22
|
+
import { abortable, throwIfAborted } from "./abort.js";
|
|
23
23
|
import { onSessionCheckpoint, prepareMcpCheckpoint } from "./checkpoint.js";
|
|
24
24
|
export { MCP_STATUS_EVENT, MCP_STATUS_SNAPSHOT_VERSION, } from "./types.js";
|
|
25
25
|
const INIT_WAIT_TIMEOUT_MS = 30_000;
|
|
@@ -90,29 +90,15 @@ function installMcpAdapter(pi, options) {
|
|
|
90
90
|
? cloneMcpConfig(sessionConfig)
|
|
91
91
|
: { mcpServers: {} };
|
|
92
92
|
const earlyCache = null;
|
|
93
|
+
let currentConfig = earlyConfig;
|
|
93
94
|
const envRaw = process.env.MCP_DIRECT_TOOLS;
|
|
94
95
|
const envDirectToolOverride = envRaw?.split(",").map(s => s.trim()).filter(Boolean);
|
|
95
96
|
const toolLoader = createToolLoader(pi, () => state, () => initPromise, beforeExecute);
|
|
96
|
-
const deactivatedTools = new Set();
|
|
97
97
|
let runtimeCwd;
|
|
98
98
|
let nativeAsyncSupported = false;
|
|
99
99
|
let proxyToolRegistered = false;
|
|
100
100
|
let proxyToolDescription = null;
|
|
101
101
|
let directToolsFrozen = false;
|
|
102
|
-
function deactivateTools(toolNames) {
|
|
103
|
-
if (toolNames.length === 0)
|
|
104
|
-
return;
|
|
105
|
-
const remove = new Set(toolNames);
|
|
106
|
-
const activeTools = pi.getActiveTools();
|
|
107
|
-
for (const toolName of toolNames) {
|
|
108
|
-
if (activeTools.includes(toolName))
|
|
109
|
-
deactivatedTools.add(toolName);
|
|
110
|
-
}
|
|
111
|
-
const nextActiveTools = activeTools.filter((name) => !remove.has(name));
|
|
112
|
-
if (nextActiveTools.length !== activeTools.length) {
|
|
113
|
-
pi.setActiveTools(nextActiveTools);
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
102
|
function applyDirectToolConfigChanges(changes) {
|
|
117
103
|
if (!state)
|
|
118
104
|
return;
|
|
@@ -124,12 +110,9 @@ function installMcpAdapter(pi, options) {
|
|
|
124
110
|
}
|
|
125
111
|
}
|
|
126
112
|
function syncToolSurface(ctx) {
|
|
127
|
-
const config = state?.config ??
|
|
113
|
+
const config = state?.config ?? currentConfig;
|
|
128
114
|
const cache = loadMetadataCache(state?.metadataCacheEnabled ?? false);
|
|
129
|
-
toolLoader.sync(config, cache, envRaw === "__none__" ? null : envDirectToolOverride, nativeAsyncSupported, specs =>
|
|
130
|
-
syncProxyTool(config, cache, specs);
|
|
131
|
-
syncScriptTool(config);
|
|
132
|
-
});
|
|
115
|
+
toolLoader.sync(config, cache, envRaw === "__none__" ? null : envDirectToolOverride, nativeAsyncSupported, specs => syncGateways(config, cache, specs));
|
|
133
116
|
}
|
|
134
117
|
const registeredPromptCommands = new Set();
|
|
135
118
|
function registerPromptCommands(specs) {
|
|
@@ -260,15 +243,13 @@ function installMcpAdapter(pi, options) {
|
|
|
260
243
|
if (options.transformConfig) {
|
|
261
244
|
runtimeConfig = cloneMcpConfig(options.transformConfig(cloneMcpConfig(runtimeConfig), ctx));
|
|
262
245
|
}
|
|
246
|
+
currentConfig = runtimeConfig;
|
|
263
247
|
const metadataCacheEnabled = ctx.isProjectTrusted()
|
|
264
248
|
|| !isPathInsideProject(getMetadataCachePath(), ctx.cwd);
|
|
265
249
|
toolLoader.restore(ctx);
|
|
266
250
|
registerPromptCommands(resolveCachedPrompts(runtimeConfig, metadataCacheEnabled));
|
|
267
251
|
const runtimeCache = loadMetadataCache(metadataCacheEnabled);
|
|
268
|
-
toolLoader.sync(runtimeConfig, runtimeCache, envRaw === "__none__" ? null : envDirectToolOverride, nativeAsyncSupported, specs =>
|
|
269
|
-
syncProxyTool(runtimeConfig, runtimeCache, specs);
|
|
270
|
-
syncScriptTool(runtimeConfig);
|
|
271
|
-
});
|
|
252
|
+
toolLoader.sync(runtimeConfig, runtimeCache, envRaw === "__none__" ? null : envDirectToolOverride, nativeAsyncSupported, specs => syncGateways(runtimeConfig, runtimeCache, specs));
|
|
272
253
|
const initialization = startInitialization(ctx, owner, oauthRuntime, runtimeConfig, generation);
|
|
273
254
|
if (envRaw !== undefined && envRaw !== "__none__") {
|
|
274
255
|
const missingEnvDirectTools = getMissingConfiguredDirectToolServers(runtimeConfig, runtimeCache, envDirectToolOverride);
|
|
@@ -538,7 +519,17 @@ function installMcpAdapter(pi, options) {
|
|
|
538
519
|
owner?.throwIfInactive();
|
|
539
520
|
return state ?? { content: [{ type: "text", text: "MCP not initialized" }], details: { error: "not_initialized" } };
|
|
540
521
|
}
|
|
522
|
+
const unavailableFeatures = (enable = [], tools) => enable.filter(feature => !tools.some(tool => tool.name === (feature === "gateway" ? "mcp" : "mcp_script") && !tool.namespace));
|
|
541
523
|
async function searchAndLoad(params, signal, ctx) {
|
|
524
|
+
throwIfAborted(signal);
|
|
525
|
+
if (params.query === undefined && !params.enable?.length)
|
|
526
|
+
throw new Error("Provide query or enable.");
|
|
527
|
+
// Loading front doors does not require initialization or connect to a server.
|
|
528
|
+
if (params.query === undefined) {
|
|
529
|
+
const tools = toolLoader.activate([], params.enable);
|
|
530
|
+
const unavailable = unavailableFeatures(params.enable, tools);
|
|
531
|
+
return { content: [{ type: "text", text: `Loaded for the next request: ${JSON.stringify(tools)}${unavailable.length ? `. Unavailable under configuration or host policy: ${unavailable.join(", ")}` : ""}` }], details: { loaded: tools, unavailable }, tools };
|
|
532
|
+
}
|
|
542
533
|
const ready = await getToolState(signal);
|
|
543
534
|
if ("content" in ready)
|
|
544
535
|
return { ...ready, tools: [] };
|
|
@@ -551,23 +542,27 @@ function installMcpAdapter(pi, options) {
|
|
|
551
542
|
const matches = params.query.trim() ? rankToolMatches(ready, params.query, params.server)
|
|
552
543
|
: params.server ? (ready.toolMetadata.get(params.server) ?? []).filter(tool => !tool.resourceUri).map(tool => ({ server: params.server, tool })).sort((a, b) => a.tool.name.localeCompare(b.tool.name)) : [];
|
|
553
544
|
const page = paginate(matches, params.offset ?? 0, params.limit ?? 5);
|
|
554
|
-
const tools = toolLoader.activate(page.items);
|
|
555
|
-
const
|
|
545
|
+
const tools = toolLoader.activate(page.items, params.enable);
|
|
546
|
+
const unavailable = unavailableFeatures(params.enable, tools);
|
|
547
|
+
const typedCount = tools.filter(tool => tool.namespace || (tool.name !== "mcp" && tool.name !== "mcp_script")).length;
|
|
548
|
+
const result = executeSearch(ready, params.query, params.server, typedCount < page.items.length, params.limit ?? 5, params.offset, "mcp_search");
|
|
556
549
|
const guarded = await guardMcpOutput([
|
|
557
550
|
...result.content,
|
|
558
|
-
{ type: "text", text: tools.length ? `Loaded for the next request: ${JSON.stringify(tools)}` :
|
|
551
|
+
{ type: "text", text: tools.length ? `Loaded for the next request: ${JSON.stringify(tools)}` : 'No direct tools loaded. Enable gateway or script with mcp_search({ enable: ["gateway"] }) or mcp_search({ enable: ["script"] }), then use mcp action call or tools.call with the returned exact names.' },
|
|
552
|
+
...(unavailable.length ? [{ type: "text", text: `Unavailable under configuration or host policy: ${unavailable.join(", ")}` }] : []),
|
|
559
553
|
], resolveMcpOutputGuardOptions(ready.config.settings, ready.outputDirectory));
|
|
560
|
-
return { content: guarded.content, details: { ...result.details, ...guardedMcpDetails(guarded), loaded: tools }, tools };
|
|
554
|
+
return { content: guarded.content, details: { ...result.details, ...guardedMcpDetails(guarded), loaded: tools, ...(unavailable.length ? { unavailable } : {}) }, tools };
|
|
561
555
|
}
|
|
562
556
|
const searchDefinition = {
|
|
563
557
|
name: "mcp_search", label: "MCP Search",
|
|
564
|
-
description: "Discover
|
|
558
|
+
description: "Discover and load typed MCP tools for the next request. Use query; server discovers an uncached server (empty query browses it). Results report incomplete coverage. Or enable gateway for mcp status/list/search/describe/call/connect/instructions, resources/read-resource, read-result, auth-start/auth-complete and ui-messages; enable script for JavaScript composition, resources and saved-result readback. Enable alone performs no integration action. Loaded schemas stay available in this session/branch.",
|
|
565
559
|
parameters: Type.Object({
|
|
566
|
-
query: Type.String(),
|
|
560
|
+
query: Type.Optional(Type.String()),
|
|
561
|
+
enable: Type.Optional(Type.Array(Type.Union([Type.Literal("gateway"), Type.Literal("script")]), { minItems: 1, uniqueItems: true })),
|
|
567
562
|
server: Type.Optional(Type.String()),
|
|
568
563
|
limit: Type.Optional(Type.Integer({ minimum: 1, maximum: MAX_PAGE_SIZE, description: "Tools to load (default 5)." })),
|
|
569
564
|
offset: Type.Optional(Type.Integer({ minimum: 0 })),
|
|
570
|
-
}),
|
|
565
|
+
}, { anyOf: [{ required: ["query"] }, { required: ["enable"] }] }),
|
|
571
566
|
renderResult: renderMcpToolResult,
|
|
572
567
|
async execute(toolCallId, params, signal, _onUpdate, ctx) {
|
|
573
568
|
if (beforeExecute) {
|
|
@@ -587,7 +582,7 @@ function installMcpAdapter(pi, options) {
|
|
|
587
582
|
function registerScriptTool() {
|
|
588
583
|
if (scriptToolRegistered)
|
|
589
584
|
return;
|
|
590
|
-
|
|
585
|
+
toolLoader.registerFeature("script", {
|
|
591
586
|
...(beforeExecute ? { executionMode: "sequential" } : {}),
|
|
592
587
|
name: "mcp_script",
|
|
593
588
|
label: "MCP Script",
|
|
@@ -609,21 +604,8 @@ function installMcpAdapter(pi, options) {
|
|
|
609
604
|
});
|
|
610
605
|
scriptToolRegistered = true;
|
|
611
606
|
}
|
|
612
|
-
function syncScriptTool(config) {
|
|
613
|
-
if (config.settings?.scriptMode === false) {
|
|
614
|
-
if (scriptToolRegistered)
|
|
615
|
-
deactivateTools(["mcp_script"]);
|
|
616
|
-
return;
|
|
617
|
-
}
|
|
618
|
-
registerScriptTool();
|
|
619
|
-
if (deactivatedTools.delete("mcp_script")) {
|
|
620
|
-
const activeTools = pi.getActiveTools();
|
|
621
|
-
if (!activeTools.includes("mcp_script"))
|
|
622
|
-
pi.setActiveTools([...activeTools, "mcp_script"]);
|
|
623
|
-
}
|
|
624
|
-
}
|
|
625
607
|
function registerProxyTool(description) {
|
|
626
|
-
|
|
608
|
+
toolLoader.registerFeature("gateway", {
|
|
627
609
|
...(beforeExecute ? { executionMode: "sequential" } : {}),
|
|
628
610
|
name: "mcp", label: "MCP", description,
|
|
629
611
|
promptSnippet: "MCP server operations, resources, saved result readback, and fallback tool calls",
|
|
@@ -684,7 +666,10 @@ function installMcpAdapter(pi, options) {
|
|
|
684
666
|
proxyToolRegistered = true;
|
|
685
667
|
proxyToolDescription = description;
|
|
686
668
|
}
|
|
687
|
-
function
|
|
669
|
+
function syncGateways(config, cache, directSpecs) {
|
|
670
|
+
const policy = {};
|
|
671
|
+
if (config.settings?.scriptMode !== false)
|
|
672
|
+
policy.script = {};
|
|
688
673
|
const missingConfiguredDirectToolServers = getMissingConfiguredDirectToolServers(config, cache, envRaw === undefined || envRaw === "__none__" ? undefined : envDirectToolOverride);
|
|
689
674
|
const hasPinnedResources = envRaw !== "__none__" && Object.entries(config.mcpServers).some(([server, definition]) => {
|
|
690
675
|
if (definition.disabled === true)
|
|
@@ -706,21 +691,15 @@ function installMcpAdapter(pi, options) {
|
|
|
706
691
|
if (!proxyToolRegistered || proxyToolDescription !== description) {
|
|
707
692
|
registerProxyTool(description);
|
|
708
693
|
}
|
|
709
|
-
|
|
710
|
-
const activeTools = pi.getActiveTools();
|
|
711
|
-
if (!activeTools.includes("mcp")) {
|
|
712
|
-
pi.setActiveTools([...activeTools, "mcp"]);
|
|
713
|
-
}
|
|
714
|
-
}
|
|
715
|
-
return;
|
|
694
|
+
policy.gateway = { eager: hasPinnedResources };
|
|
716
695
|
}
|
|
717
|
-
if (
|
|
718
|
-
|
|
696
|
+
if (policy.script)
|
|
697
|
+
registerScriptTool();
|
|
698
|
+
return policy;
|
|
719
699
|
}
|
|
720
700
|
// A transform needs the session context before any configured tool surface is registered.
|
|
721
701
|
if (!options.transformConfig) {
|
|
722
|
-
|
|
723
|
-
syncScriptTool(earlyConfig);
|
|
702
|
+
syncGateways(earlyConfig, earlyCache, []);
|
|
724
703
|
}
|
|
725
704
|
}
|
|
726
705
|
export function createMcpAdapter(options = {}) {
|
package/dist/lifecycle.d.ts
CHANGED
|
@@ -4,8 +4,6 @@ import { hasPendingAuth } from "./mcp-auth-flow.ts";
|
|
|
4
4
|
export type ReconnectCallback = (serverName: string) => void;
|
|
5
5
|
export type ReconnectFailureCallback = (serverName: string, error: unknown) => void;
|
|
6
6
|
export declare class McpLifecycleManager {
|
|
7
|
-
private readonly manager;
|
|
8
|
-
private readonly hasPendingAuthForServer;
|
|
9
7
|
private keepAliveServers;
|
|
10
8
|
private allServers;
|
|
11
9
|
private serverSettings;
|
|
@@ -23,6 +21,8 @@ export declare class McpLifecycleManager {
|
|
|
23
21
|
pauseForCheckpoint(): () => void;
|
|
24
22
|
private healthSignal;
|
|
25
23
|
private removeHealthAbortListener;
|
|
24
|
+
private readonly manager;
|
|
25
|
+
private readonly hasPendingAuthForServer;
|
|
26
26
|
constructor(manager: McpServerManager, hasPendingAuthForServer?: typeof hasPendingAuth);
|
|
27
27
|
setReconnectCallback(callback: ReconnectCallback): void;
|
|
28
28
|
setReconnectFailureCallback(callback: ReconnectFailureCallback): void;
|
package/dist/lifecycle.js
CHANGED
|
@@ -3,8 +3,6 @@ import { hasPendingAuth } from "./mcp-auth-flow.js";
|
|
|
3
3
|
import { logger } from "./logger.js";
|
|
4
4
|
import { formatTerminalError, sanitizeTerminalText } from "./utils.js";
|
|
5
5
|
export class McpLifecycleManager {
|
|
6
|
-
manager;
|
|
7
|
-
hasPendingAuthForServer;
|
|
8
6
|
keepAliveServers = new Map();
|
|
9
7
|
allServers = new Map();
|
|
10
8
|
serverSettings = new Map();
|
|
@@ -31,6 +29,8 @@ export class McpLifecycleManager {
|
|
|
31
29
|
}
|
|
32
30
|
healthSignal;
|
|
33
31
|
removeHealthAbortListener;
|
|
32
|
+
manager;
|
|
33
|
+
hasPendingAuthForServer;
|
|
34
34
|
constructor(manager, hasPendingAuthForServer = hasPendingAuth) {
|
|
35
35
|
this.manager = manager;
|
|
36
36
|
this.hasPendingAuthForServer = hasPendingAuthForServer;
|
package/dist/mcp-auth-flow.js
CHANGED
|
@@ -9,7 +9,7 @@ import { McpOAuthProvider, issuersMatch, loopbackRedirectsMatch, validateOAuthCl
|
|
|
9
9
|
import { ensureCallbackServer, waitForCallback, cancelPendingCallback, stopCallbackServer, releaseCallbackServer, takeCallbackResult, } from "./mcp-callback-server.js";
|
|
10
10
|
import { getAuthForUrl, clearAllCredentials, clearClientInfo, clearTokens, clearCodeVerifier, getOAuthState, clearOAuthState, getAuthBaseDir, } from "./mcp-auth.js";
|
|
11
11
|
import { isServerDisabled, isNonInteractiveOAuth, validateServerProtocolConfig } from "./types.js";
|
|
12
|
-
import { formatTerminalError, interpolateEnvRecord, interpolateEnvVars, normalizeRequestTimeoutMs } from "./utils.js";
|
|
12
|
+
import { ADAPTER_VERSION, formatTerminalError, interpolateEnvRecord, interpolateEnvVars, normalizeRequestTimeoutMs } from "./utils.js";
|
|
13
13
|
import { abortable, throwIfAborted } from "./abort.js";
|
|
14
14
|
import { combineAbortSignals, isAbortError } from "./runtime-owner.js";
|
|
15
15
|
function applyConfiguredScope(discovery, config) {
|
|
@@ -255,7 +255,7 @@ async function probeAuthDiscovery(serverUrl, definition, signal) {
|
|
|
255
255
|
const timeout = normalizeRequestTimeoutMs(definition?.requestTimeoutMs) ?? 5000;
|
|
256
256
|
const discoverySignal = combineAbortSignals(signal, AbortSignal.timeout(Math.ceil(timeout)));
|
|
257
257
|
let discovery = {};
|
|
258
|
-
const client = new Client({ name: "pi-mcp-auth-discovery", version:
|
|
258
|
+
const client = new Client({ name: "pi-mcp-auth-discovery", version: ADAPTER_VERSION }, {
|
|
259
259
|
versionNegotiation: { mode: definition?.protocolVersion ?? "auto" },
|
|
260
260
|
...(isNonInteractiveOAuth(definition?.oauth)
|
|
261
261
|
? { capabilities: { extensions: { [definition?.oauth && definition.oauth.crossAppAccess
|
package/dist/mcp-auth.d.ts
CHANGED
|
@@ -51,8 +51,8 @@ export interface AuthStorageOptions {
|
|
|
51
51
|
baseDir?: string;
|
|
52
52
|
}
|
|
53
53
|
export declare class OAuthCredentialStoreError extends Error {
|
|
54
|
-
readonly operation: 'read' | 'write' | 'remove';
|
|
55
54
|
readonly code = "OAUTH_CREDENTIAL_STORE_UNAVAILABLE";
|
|
55
|
+
readonly operation: 'read' | 'write' | 'remove';
|
|
56
56
|
constructor(message: string, operation: 'read' | 'write' | 'remove', cause: unknown);
|
|
57
57
|
}
|
|
58
58
|
export type OAuthCredentialStatus = {
|
package/dist/mcp-auth.js
CHANGED
|
@@ -15,8 +15,8 @@ import { createRequire } from 'module';
|
|
|
15
15
|
import { readFileSync, existsSync, rmSync } from 'fs';
|
|
16
16
|
import { dirname, join } from 'path';
|
|
17
17
|
import { fileURLToPath } from 'url';
|
|
18
|
-
import { getAdapterPath, getAgentPath } from
|
|
19
|
-
import { resolveConfiguredOAuthDir } from
|
|
18
|
+
import { getAdapterPath, getAgentPath } from './agent-dir.js';
|
|
19
|
+
import { resolveConfiguredOAuthDir } from './config.js';
|
|
20
20
|
const require = createRequire(import.meta.url);
|
|
21
21
|
const AUTH_SECRET_SERVICE = 'fitch-mcp-adapter.oauth';
|
|
22
22
|
const LEGACY_AUTH_SECRET_SERVICE = 'pi-mcp-adapter.oauth';
|
|
@@ -30,8 +30,8 @@ const TEST_LINUX_KEYRING_RECOVERY_ENV = 'PI_MCP_ADAPTER_TEST_LINUX_KEYRING_RECOV
|
|
|
30
30
|
const KEYRING_RECOVERY_TIMEOUT_MS = 10_000;
|
|
31
31
|
const AUTH_CHUNK_MANIFEST_KEY = '__piMcpAdapterOAuthChunked';
|
|
32
32
|
export class OAuthCredentialStoreError extends Error {
|
|
33
|
-
operation;
|
|
34
33
|
code = 'OAUTH_CREDENTIAL_STORE_UNAVAILABLE';
|
|
34
|
+
operation;
|
|
35
35
|
constructor(message, operation, cause) {
|
|
36
36
|
super(isAndroidKeyringLoadFailure(cause)
|
|
37
37
|
? `${message}. Android/Termux: @napi-rs/keyring could not load a native binding. Persistent OAuth requires a supported platform with an OS credential store; no plaintext fallback is used.`
|
package/dist/mcp-code.d.ts
CHANGED
|
@@ -6,6 +6,12 @@ export declare const runMcpScript: typeof runMcpScriptOperation;
|
|
|
6
6
|
declare function runMcpScriptOperation(state: McpExtensionState, code: string, timeoutMs?: number | null, getPiTools?: () => ToolInfo[], signal?: AbortSignal, toolCallId?: string, beforeDispatch?: (signal: AbortSignal | undefined, operation: McpOperationContext) => Promise<void>): Promise<{
|
|
7
7
|
content: ContentBlock[];
|
|
8
8
|
details: {
|
|
9
|
+
mode: string;
|
|
10
|
+
resultRefs?: string[];
|
|
11
|
+
error?: "aborted" | "call_capture_failed" | "script_error" | "timeout";
|
|
12
|
+
message?: string | undefined;
|
|
13
|
+
timeoutMs: number | null;
|
|
14
|
+
recovery?: {} | null;
|
|
9
15
|
calls?: ({
|
|
10
16
|
operation: "call";
|
|
11
17
|
path: string;
|
|
@@ -41,12 +47,6 @@ declare function runMcpScriptOperation(state: McpExtensionState, code: string, t
|
|
|
41
47
|
error: string;
|
|
42
48
|
durationMs: number;
|
|
43
49
|
})[];
|
|
44
|
-
recovery?: {} | null;
|
|
45
|
-
timeoutMs: number | null;
|
|
46
|
-
error?: "aborted" | "timeout" | "call_capture_failed" | "script_error";
|
|
47
|
-
message?: string | undefined;
|
|
48
|
-
resultRefs?: string[];
|
|
49
|
-
mode: string;
|
|
50
50
|
};
|
|
51
51
|
}>;
|
|
52
52
|
export {};
|
package/dist/mcp-code.js
CHANGED
|
@@ -122,7 +122,7 @@ async function runMcpScriptOperation(state, code, timeoutMs = DEFAULT_MCP_SCRIPT
|
|
|
122
122
|
? Math.max(0, Date.now() - startedAt)
|
|
123
123
|
: operation.durationMs,
|
|
124
124
|
}));
|
|
125
|
-
|
|
125
|
+
const pendingOperations = new Set();
|
|
126
126
|
const resultRefs = new Set();
|
|
127
127
|
const payloadNotices = new Set();
|
|
128
128
|
const recordCall = async (path, dispatch) => {
|
|
@@ -149,11 +149,11 @@ async function runMcpScriptOperation(state, code, timeoutMs = DEFAULT_MCP_SCRIPT
|
|
|
149
149
|
: textFromContent(result.content);
|
|
150
150
|
calls[index] = {
|
|
151
151
|
operation: "call", path, ok: false, error: errorCode, durationMs: Date.now() - startedAt, startedAt,
|
|
152
|
-
...(
|
|
152
|
+
...(details.recovery !== undefined ? { recovery: details.recovery } : {}),
|
|
153
153
|
};
|
|
154
154
|
if (errorCode === "call_capture_failed")
|
|
155
155
|
throw new McpScriptCaptureError(details.recovery, message);
|
|
156
|
-
if (
|
|
156
|
+
if (details.recovery !== undefined)
|
|
157
157
|
output.push({ type: "text", text: message });
|
|
158
158
|
return {
|
|
159
159
|
ok: false,
|
|
@@ -301,7 +301,7 @@ async function runMcpScriptOperation(state, code, timeoutMs = DEFAULT_MCP_SCRIPT
|
|
|
301
301
|
reject(new Error(message.message));
|
|
302
302
|
return;
|
|
303
303
|
}
|
|
304
|
-
|
|
304
|
+
const operation = (async () => {
|
|
305
305
|
let envelope;
|
|
306
306
|
if (message.type === "call") {
|
|
307
307
|
envelope = await callTool(message.id, message.path, message.args, message.server);
|
|
@@ -332,7 +332,9 @@ async function runMcpScriptOperation(state, code, timeoutMs = DEFAULT_MCP_SCRIPT
|
|
|
332
332
|
}
|
|
333
333
|
const response = { type: "result", id: message.id, envelope };
|
|
334
334
|
activeWorker.postMessage(response);
|
|
335
|
-
})()
|
|
335
|
+
})();
|
|
336
|
+
pendingOperations.add(operation);
|
|
337
|
+
void operation.catch(reject).finally(() => pendingOperations.delete(operation));
|
|
336
338
|
});
|
|
337
339
|
activeWorker.once("error", reject);
|
|
338
340
|
activeWorker.once("exit", (code) => {
|
|
@@ -345,7 +347,6 @@ async function runMcpScriptOperation(state, code, timeoutMs = DEFAULT_MCP_SCRIPT
|
|
|
345
347
|
return;
|
|
346
348
|
const timeoutError = new McpScriptTimeoutError(resolvedTimeoutMs);
|
|
347
349
|
timer = setTimeout(() => {
|
|
348
|
-
callsSnapshot = snapshotCalls();
|
|
349
350
|
timeoutController.abort(timeoutError);
|
|
350
351
|
void activeWorker.terminate();
|
|
351
352
|
reject(timeoutError);
|
|
@@ -354,7 +355,6 @@ async function runMcpScriptOperation(state, code, timeoutMs = DEFAULT_MCP_SCRIPT
|
|
|
354
355
|
const aborted = externalSignal
|
|
355
356
|
? new Promise((_resolve, reject) => {
|
|
356
357
|
const onAbort = () => {
|
|
357
|
-
callsSnapshot = snapshotCalls();
|
|
358
358
|
void activeWorker.terminate();
|
|
359
359
|
reject(abortReasonError(externalSignal.reason));
|
|
360
360
|
};
|
|
@@ -387,14 +387,15 @@ async function runMcpScriptOperation(state, code, timeoutMs = DEFAULT_MCP_SCRIPT
|
|
|
387
387
|
finally {
|
|
388
388
|
clearTimeout(timer);
|
|
389
389
|
removeAbortListener();
|
|
390
|
-
|
|
391
|
-
// (deadline, abort, or early return). Snapshot before aborting stragglers.
|
|
392
|
-
callsSnapshot ??= snapshotCalls();
|
|
390
|
+
worker?.removeAllListeners("message");
|
|
393
391
|
// A script may finish without awaiting every call; abort leftovers so
|
|
394
392
|
// parent-side dispatches do not outlive the script.
|
|
395
393
|
timeoutController.abort(new Error("mcp_script finished"));
|
|
394
|
+
// Let cancelled dispatches report whether an outcome is known before taking the trace.
|
|
395
|
+
await Promise.allSettled(pendingOperations);
|
|
396
396
|
await worker?.terminate();
|
|
397
397
|
}
|
|
398
|
+
const callsSnapshot = snapshotCalls();
|
|
398
399
|
// Snapshot before the asynchronous output guard; the terminated worker can no longer emit.
|
|
399
400
|
const guarded = await guardMcpOutput([...(output.length > 0 ? output : [{ type: "text", text: "(no output)" }]), ...[...payloadNotices].map(text => ({ type: "text", text })), ...[...resultRefs].map(ref => ({ type: "text", text: formatMcpResultReference(ref) }))], resolveMcpOutputGuardOptions(state.config.settings, state.outputDirectory));
|
|
400
401
|
return {
|
|
@@ -49,11 +49,6 @@ export interface McpOAuthCallbacks {
|
|
|
49
49
|
* Implements the OAuthClientProvider interface from the MCP SDK.
|
|
50
50
|
*/
|
|
51
51
|
export declare class McpOAuthProvider implements OAuthClientProvider {
|
|
52
|
-
private serverName;
|
|
53
|
-
private serverUrl;
|
|
54
|
-
private config;
|
|
55
|
-
private callbacks;
|
|
56
|
-
private storageOptions;
|
|
57
52
|
private readonly redirectUrlSnapshot;
|
|
58
53
|
readonly clientMetadataUrl?: string;
|
|
59
54
|
private readonly controller;
|
|
@@ -66,6 +61,11 @@ export declare class McpOAuthProvider implements OAuthClientProvider {
|
|
|
66
61
|
private flowDiscoveryState;
|
|
67
62
|
private flowIssuerMismatch;
|
|
68
63
|
private flowState;
|
|
64
|
+
private serverName;
|
|
65
|
+
private serverUrl;
|
|
66
|
+
private config;
|
|
67
|
+
private callbacks;
|
|
68
|
+
private storageOptions;
|
|
69
69
|
constructor(serverName: string, serverUrl: string, config: McpOAuthConfig, callbacks: McpOAuthCallbacks, storageOptions?: AuthStorageOptions, runtimeSignal?: AbortSignal, initialState?: string);
|
|
70
70
|
private get isNonInteractive();
|
|
71
71
|
private get discoveredIssuer();
|
|
@@ -152,11 +152,6 @@ function addAuthorizationParams(authorizationUrl, params) {
|
|
|
152
152
|
* Implements the OAuthClientProvider interface from the MCP SDK.
|
|
153
153
|
*/
|
|
154
154
|
export class McpOAuthProvider {
|
|
155
|
-
serverName;
|
|
156
|
-
serverUrl;
|
|
157
|
-
config;
|
|
158
|
-
callbacks;
|
|
159
|
-
storageOptions;
|
|
160
155
|
redirectUrlSnapshot;
|
|
161
156
|
clientMetadataUrl;
|
|
162
157
|
controller = new AbortController();
|
|
@@ -169,6 +164,11 @@ export class McpOAuthProvider {
|
|
|
169
164
|
flowDiscoveryState;
|
|
170
165
|
flowIssuerMismatch = false;
|
|
171
166
|
flowState;
|
|
167
|
+
serverName;
|
|
168
|
+
serverUrl;
|
|
169
|
+
config;
|
|
170
|
+
callbacks;
|
|
171
|
+
storageOptions;
|
|
172
172
|
constructor(serverName, serverUrl, config, callbacks, storageOptions = {}, runtimeSignal, initialState) {
|
|
173
173
|
this.serverName = serverName;
|
|
174
174
|
this.serverUrl = serverUrl;
|
|
@@ -94,11 +94,11 @@ export declare function readMcpResult(input: ReadMcpResultInput, options?: McpOu
|
|
|
94
94
|
text: string;
|
|
95
95
|
}[];
|
|
96
96
|
details: {
|
|
97
|
-
path?: string;
|
|
98
97
|
ref: string;
|
|
99
98
|
offset: number;
|
|
100
99
|
nextOffset: number | null;
|
|
101
100
|
totalCharacters: number;
|
|
101
|
+
path?: string;
|
|
102
102
|
error?: never;
|
|
103
103
|
message?: never;
|
|
104
104
|
};
|
package/dist/mcp-output-guard.js
CHANGED
|
@@ -223,7 +223,7 @@ export function formatMcpPayloadFile(file) {
|
|
|
223
223
|
return `[MCP ${file.kind === "audio" ? "audio" : "binary resource"}${file.uri ? ` (${file.uri})` : ""}: ${file.mimeType ?? "unknown MIME type"}; not rendered. ${file.path ? `Saved file: ${file.path}` : `Could not save: ${file.error}`}]`;
|
|
224
224
|
}
|
|
225
225
|
export function formatMcpResultReference(ref) {
|
|
226
|
-
return `[MCP result saved: ${JSON.stringify(ref)}. Inspect without repeating the call using mcp action "read-result" or tools.readResult with this ref. Optionally select a JSON Pointer with path.]`;
|
|
226
|
+
return `[MCP result saved: ${JSON.stringify(ref)}. Inspect without repeating the call using mcp action "read-result" or tools.readResult with this ref. If inactive, first mcp_search({ enable: ["gateway"] }) or mcp_search({ enable: ["script"] }). Optionally select a JSON Pointer with path.]`;
|
|
227
227
|
}
|
|
228
228
|
function summarizeMcpResult(result, rawBytes, artifact) {
|
|
229
229
|
const { path: fullResultPath, error: resultWriteError } = artifact;
|
package/dist/mcp-panel.d.ts
CHANGED
|
@@ -2,8 +2,6 @@ import { type PanelKeybindings } from "./panel-keys.ts";
|
|
|
2
2
|
import type { McpConfig, McpPanelCallbacks, McpPanelResult, ServerProvenance } from "./types.ts";
|
|
3
3
|
import { type MetadataCache } from "./metadata-cache.ts";
|
|
4
4
|
declare class McpPanel {
|
|
5
|
-
private callbacks;
|
|
6
|
-
private done;
|
|
7
5
|
private noticeLines;
|
|
8
6
|
private prefix;
|
|
9
7
|
private servers;
|
|
@@ -25,6 +23,8 @@ declare class McpPanel {
|
|
|
25
23
|
private keys;
|
|
26
24
|
private static readonly MAX_VISIBLE;
|
|
27
25
|
private static readonly INACTIVITY_MS;
|
|
26
|
+
private callbacks;
|
|
27
|
+
private done;
|
|
28
28
|
constructor(config: McpConfig, cache: MetadataCache | null, provenance: Map<string, ServerProvenance>, callbacks: McpPanelCallbacks, tui: {
|
|
29
29
|
requestRender(): void;
|
|
30
30
|
}, done: (result: McpPanelResult) => void, options?: {
|