@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/mcp-panel.js
CHANGED
|
@@ -93,8 +93,6 @@ function estimateTokens(tool) {
|
|
|
93
93
|
return Math.ceil((tool.name.length + descLen + schemaLen) / 4) + 10;
|
|
94
94
|
}
|
|
95
95
|
class McpPanel {
|
|
96
|
-
callbacks;
|
|
97
|
-
done;
|
|
98
96
|
noticeLines;
|
|
99
97
|
prefix;
|
|
100
98
|
servers = [];
|
|
@@ -116,6 +114,8 @@ class McpPanel {
|
|
|
116
114
|
keys;
|
|
117
115
|
static MAX_VISIBLE = 12;
|
|
118
116
|
static INACTIVITY_MS = 60_000;
|
|
117
|
+
callbacks;
|
|
118
|
+
done;
|
|
119
119
|
constructor(config, cache, provenance, callbacks, tui, done, options = {}) {
|
|
120
120
|
this.callbacks = callbacks;
|
|
121
121
|
this.done = done;
|
|
@@ -31,10 +31,6 @@ export interface SetupPanelOptions {
|
|
|
31
31
|
keybindings?: PanelKeybindings;
|
|
32
32
|
}
|
|
33
33
|
export declare class McpSetupPanel {
|
|
34
|
-
private discovery;
|
|
35
|
-
private callbacks;
|
|
36
|
-
private options;
|
|
37
|
-
private done;
|
|
38
34
|
private screen;
|
|
39
35
|
private actionCursor;
|
|
40
36
|
private importCursor;
|
|
@@ -47,6 +43,10 @@ export declare class McpSetupPanel {
|
|
|
47
43
|
private keys;
|
|
48
44
|
private inactivityTimeout;
|
|
49
45
|
private static readonly INACTIVITY_MS;
|
|
46
|
+
private discovery;
|
|
47
|
+
private callbacks;
|
|
48
|
+
private options;
|
|
49
|
+
private done;
|
|
50
50
|
constructor(discovery: McpDiscoverySummary, callbacks: SetupPanelCallbacks, options: SetupPanelOptions, tui: {
|
|
51
51
|
requestRender(): void;
|
|
52
52
|
}, done: () => void);
|
|
@@ -72,6 +72,7 @@ export declare class McpSetupPanel {
|
|
|
72
72
|
private previewWidth;
|
|
73
73
|
private getActionPreview;
|
|
74
74
|
private formatPreview;
|
|
75
|
+
private previewOrError;
|
|
75
76
|
private formatWritePreview;
|
|
76
77
|
private padLine;
|
|
77
78
|
invalidate(): void;
|
package/dist/mcp-setup-panel.js
CHANGED
|
@@ -38,10 +38,6 @@ function wrapText(text, width) {
|
|
|
38
38
|
return lines.length > 0 ? lines : [""];
|
|
39
39
|
}
|
|
40
40
|
export class McpSetupPanel {
|
|
41
|
-
discovery;
|
|
42
|
-
callbacks;
|
|
43
|
-
options;
|
|
44
|
-
done;
|
|
45
41
|
screen;
|
|
46
42
|
actionCursor = 0;
|
|
47
43
|
importCursor = 0;
|
|
@@ -54,6 +50,10 @@ export class McpSetupPanel {
|
|
|
54
50
|
keys;
|
|
55
51
|
inactivityTimeout = null;
|
|
56
52
|
static INACTIVITY_MS = 60_000;
|
|
53
|
+
discovery;
|
|
54
|
+
callbacks;
|
|
55
|
+
options;
|
|
56
|
+
done;
|
|
57
57
|
constructor(discovery, callbacks, options, tui, done) {
|
|
58
58
|
this.discovery = discovery;
|
|
59
59
|
this.callbacks = callbacks;
|
|
@@ -361,7 +361,7 @@ export class McpSetupPanel {
|
|
|
361
361
|
lines.push(this.padLine(fg(this.t.muted, `… ${actions.length - end} more below`), innerW));
|
|
362
362
|
}
|
|
363
363
|
lines.push(this.padLine("", innerW));
|
|
364
|
-
const preview = this.getActionPreview(this.getSelectedAction(),
|
|
364
|
+
const preview = this.previewOrError(width => this.getActionPreview(this.getSelectedAction(), width), innerW);
|
|
365
365
|
for (const line of preview) {
|
|
366
366
|
lines.push(this.padLine(line, innerW));
|
|
367
367
|
}
|
|
@@ -384,8 +384,7 @@ export class McpSetupPanel {
|
|
|
384
384
|
}
|
|
385
385
|
lines.push(this.padLine("", innerW));
|
|
386
386
|
const selected = this.discovery.imports.filter((entry) => this.selectedImports.has(entry.kind)).map((entry) => entry.kind);
|
|
387
|
-
const
|
|
388
|
-
for (const line of this.formatWritePreview("Compatibility import write preview", preview, [], this.previewWidth(innerW))) {
|
|
387
|
+
for (const line of this.previewOrError(width => this.formatWritePreview("Compatibility import write preview", this.callbacks.previewImports(selected), [], width), innerW)) {
|
|
389
388
|
lines.push(this.padLine(line, innerW));
|
|
390
389
|
}
|
|
391
390
|
return lines;
|
|
@@ -522,6 +521,15 @@ export class McpSetupPanel {
|
|
|
522
521
|
}
|
|
523
522
|
return preview;
|
|
524
523
|
}
|
|
524
|
+
previewOrError(preview, innerW) {
|
|
525
|
+
const width = this.previewWidth(innerW);
|
|
526
|
+
try {
|
|
527
|
+
return preview(width);
|
|
528
|
+
}
|
|
529
|
+
catch (error) {
|
|
530
|
+
return this.formatPreview([`Cannot preview write: ${error instanceof Error ? error.message : String(error)}`], width);
|
|
531
|
+
}
|
|
532
|
+
}
|
|
525
533
|
formatWritePreview(title, preview, intro = [], width = DESKTOP_PREVIEW_WIDTH) {
|
|
526
534
|
const lines = [];
|
|
527
535
|
for (const line of intro) {
|
package/dist/mcp-trace.d.ts
CHANGED
|
@@ -52,7 +52,6 @@ export declare function createMcpTraceEvent(direction: McpTraceDirection, server
|
|
|
52
52
|
durationMs?: number;
|
|
53
53
|
}): McpTraceEvent;
|
|
54
54
|
export declare class McpTraceWriter {
|
|
55
|
-
private readonly options;
|
|
56
55
|
private readonly maxBytes;
|
|
57
56
|
private readonly maxEvents;
|
|
58
57
|
private readonly append;
|
|
@@ -65,6 +64,7 @@ export declare class McpTraceWriter {
|
|
|
65
64
|
private initializationFailed;
|
|
66
65
|
private persistenceError;
|
|
67
66
|
private readonly fileReady;
|
|
67
|
+
private readonly options;
|
|
68
68
|
constructor(options: McpTraceWriterOptions);
|
|
69
69
|
get filePath(): string;
|
|
70
70
|
get isDisabled(): boolean;
|
package/dist/mcp-trace.js
CHANGED
|
@@ -73,7 +73,6 @@ export function createMcpTraceEvent(direction, server, transport, message, statu
|
|
|
73
73
|
return event;
|
|
74
74
|
}
|
|
75
75
|
export class McpTraceWriter {
|
|
76
|
-
options;
|
|
77
76
|
maxBytes;
|
|
78
77
|
maxEvents;
|
|
79
78
|
append;
|
|
@@ -86,6 +85,7 @@ export class McpTraceWriter {
|
|
|
86
85
|
initializationFailed = false;
|
|
87
86
|
persistenceError;
|
|
88
87
|
fileReady;
|
|
88
|
+
options;
|
|
89
89
|
constructor(options) {
|
|
90
90
|
this.options = options;
|
|
91
91
|
this.maxBytes = boundedPositiveInteger(options.maxBytes, DEFAULT_MCP_TRACE_MAX_BYTES);
|
package/dist/npx-resolver.js
CHANGED
|
@@ -17,13 +17,15 @@ export async function resolveNpxBinary(command, args, signal) {
|
|
|
17
17
|
if (!parsed)
|
|
18
18
|
return null;
|
|
19
19
|
const packageSpec = parsePackageSpec(parsed.packageSpec);
|
|
20
|
+
if (!packageSpec)
|
|
21
|
+
return null;
|
|
20
22
|
const cacheKey = JSON.stringify([command, ...args]);
|
|
21
23
|
const cache = loadCache();
|
|
22
24
|
const cached = cache?.entries?.[cacheKey];
|
|
23
25
|
if (cached
|
|
24
26
|
&& Date.now() - cached.resolvedAt < CACHE_TTL_MS
|
|
25
27
|
&& existsSync(cached.resolvedBin)
|
|
26
|
-
&& (!packageSpec
|
|
28
|
+
&& (!packageSpec.exactVersion || cached.packageVersion === packageSpec.exactVersion)) {
|
|
27
29
|
return { binPath: cached.resolvedBin, extraArgs: parsed.extraArgs, isJs: cached.isJs };
|
|
28
30
|
}
|
|
29
31
|
const resolved = resolveFromNpmCache(parsed.packageSpec, parsed.binName);
|
|
@@ -289,11 +291,13 @@ function parsePackageSpec(spec) {
|
|
|
289
291
|
if (!packageName)
|
|
290
292
|
return null;
|
|
291
293
|
const normalizedVersion = requestedVersion?.replace(/^=/, "").replace(/^v/i, "");
|
|
294
|
+
// Let npm resolve ranges and tags rather than choosing an arbitrary cached version.
|
|
295
|
+
if (requestedVersion !== undefined && (!normalizedVersion || !EXACT_PACKAGE_VERSION_RE.test(normalizedVersion))) {
|
|
296
|
+
return null;
|
|
297
|
+
}
|
|
292
298
|
return {
|
|
293
299
|
packageName,
|
|
294
|
-
...(normalizedVersion
|
|
295
|
-
? { exactVersion: normalizedVersion }
|
|
296
|
-
: {}),
|
|
300
|
+
...(normalizedVersion ? { exactVersion: normalizedVersion } : {}),
|
|
297
301
|
};
|
|
298
302
|
}
|
|
299
303
|
function defaultBinName(packageName) {
|
package/dist/proxy-modes.d.ts
CHANGED
|
@@ -9,7 +9,7 @@ export declare function executeStatus(state: McpExtensionState): ProxyToolResult
|
|
|
9
9
|
export declare function executeAuthStart(state: McpExtensionState, serverName: string, signal?: AbortSignal): Promise<ProxyToolResult>;
|
|
10
10
|
export declare function executeAuthComplete(state: McpExtensionState, serverName: string, input?: string, signal?: AbortSignal): Promise<ProxyToolResult>;
|
|
11
11
|
export declare function executeDescribe(state: McpExtensionState, toolName: string, serverFilter?: string): ProxyToolResult;
|
|
12
|
-
export declare function executeSearch(state: McpExtensionState, query: string, server?: string, includeSchemas?: boolean, limit?: number, offset?: number): ProxyToolResult;
|
|
12
|
+
export declare function executeSearch(state: McpExtensionState, query: string, server?: string, includeSchemas?: boolean, limit?: number, offset?: number, caller?: "mcp" | "mcp_search"): ProxyToolResult;
|
|
13
13
|
export declare function executeList(state: McpExtensionState, server: string, limit?: number, offset?: number): ProxyToolResult;
|
|
14
14
|
export declare function executeInstructions(state: McpExtensionState, server: string): ProxyToolResult;
|
|
15
15
|
export declare function executeConnect(state: McpExtensionState, serverName: string, signal?: AbortSignal, limit?: number, offset?: number): Promise<ProxyToolResult>;
|
|
@@ -63,10 +63,10 @@ export declare function prepareMcpConnection(state: McpExtensionState, serverNam
|
|
|
63
63
|
recoverAuthConnection?: never;
|
|
64
64
|
autoAuthAttempted?: never;
|
|
65
65
|
} | {
|
|
66
|
+
error?: never;
|
|
66
67
|
connection: ServerConnection;
|
|
67
68
|
recoverAuthConnection: (serverName: string, signal?: AbortSignal, challenge?: import("./session-recovery.ts").AuthChallengeContext) => Promise<ServerConnection | undefined>;
|
|
68
69
|
autoAuthAttempted: () => boolean;
|
|
69
|
-
error?: never;
|
|
70
70
|
}>;
|
|
71
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>;
|
|
72
72
|
export {};
|
package/dist/proxy-modes.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { DEFAULT_REQUEST_TIMEOUT_MSEC, UrlElicitationRequiredError } from "@modelcontextprotocol/client";
|
|
2
2
|
import { getServerPrefix, isServerDisabled, isNonInteractiveOAuth, parseUiPromptHandoff, resolveToolPrefix } from "./types.js";
|
|
3
|
-
import { lazyConnect, markKeepAliveAfterConnect, notifyToolMetadataUpdated, updateMetadataCache, getFailureAgeSeconds, updateStatusBar, clearFailure, recordFailure } from "./init.js";
|
|
3
|
+
import { lazyConnect, markKeepAliveAfterConnect, notifyToolMetadataUpdated, updateServerMetadata, updateMetadataCache, getFailureAgeSeconds, updateStatusBar, clearFailure, recordFailure } from "./init.js";
|
|
4
4
|
import { abortable, throwIfAborted } from "./abort.js";
|
|
5
5
|
import { combineAbortSignals, isAbortError } from "./runtime-owner.js";
|
|
6
6
|
import { buildToolMetadata, catalogCoverage, findToolByName, formatSchema, toToolDescriptor } from "./tool-metadata.js";
|
|
@@ -10,7 +10,7 @@ import { guardMcpOutput, guardedMcpDetails, retainMcpResult, resolveMcpOutputGua
|
|
|
10
10
|
import { maybeStartUiSession, summarizeUiSessionResult } from "./ui-session.js";
|
|
11
11
|
import { formatAuthRequiredMessage, formatMcpStatus, resolveServerUrl, truncateAtWord } from "./utils.js";
|
|
12
12
|
import { authenticate, completeAuthFromInput, startAuth, supportsOAuth } from "./mcp-auth-flow.js";
|
|
13
|
-
import { isToolTransportFailure, SessionRecoveryAuthRequiredError, withSessionRecovery } from "./session-recovery.js";
|
|
13
|
+
import { isInterruptedToolCall, isToolTransportFailure, trackToolCallOutcome, SessionRecoveryAuthRequiredError, withSessionRecovery } from "./session-recovery.js";
|
|
14
14
|
import { paginate, rankSuggestions, rankToolMatches } from "./search-ranking.js";
|
|
15
15
|
import { ensureToolCallApproved, isToolCallApprovalRequired } from "./tool-approval.js";
|
|
16
16
|
const INSTRUCTIONS_PREVIEW_LENGTH = 300;
|
|
@@ -21,7 +21,7 @@ function disabledResult(mode, serverName) {
|
|
|
21
21
|
details: { mode, error: "server_disabled", server: serverName, message },
|
|
22
22
|
};
|
|
23
23
|
}
|
|
24
|
-
function getAuthRequiredMessage(state, serverName, defaultMessage = `Server "${serverName}" requires OAuth authentication. Run mcp({ action: "auth-start", server: "${serverName}" }) to get a browser URL, or /mcp-auth ${serverName} in an interactive local session.`) {
|
|
24
|
+
function getAuthRequiredMessage(state, serverName, defaultMessage = `Server "${serverName}" requires OAuth authentication. If mcp is inactive, first mcp_search({ enable: ["gateway"] }). Run mcp({ action: "auth-start", server: "${serverName}" }) to get a browser URL, or /mcp-auth ${serverName} in an interactive local session.`) {
|
|
25
25
|
const oauth = state.config.mcpServers[serverName]?.oauth;
|
|
26
26
|
if (oauth && oauth.crossAppAccess)
|
|
27
27
|
defaultMessage = `Server "${serverName}" requires enterprise authorization. Check oauth.crossAppAccess IdP configuration and ID-token source, then retry.`;
|
|
@@ -33,7 +33,7 @@ function getAuthFailedMessage(state, serverName, message) {
|
|
|
33
33
|
if (customGuidance || (oauth && oauth.crossAppAccess)) {
|
|
34
34
|
return `OAuth authentication failed for "${serverName}": ${message}. ${getAuthRequiredMessage(state, serverName)}`;
|
|
35
35
|
}
|
|
36
|
-
return `OAuth authentication failed for "${serverName}": ${message}. Run mcp({ action: "auth-start", server: "${serverName}" }) to get a browser URL, or /mcp-auth ${serverName} in an interactive local session.`;
|
|
36
|
+
return `OAuth authentication failed for "${serverName}": ${message}. If mcp is inactive, first mcp_search({ enable: ["gateway"] }). Run mcp({ action: "auth-start", server: "${serverName}" }) to get a browser URL, or /mcp-auth ${serverName} in an interactive local session.`;
|
|
37
37
|
}
|
|
38
38
|
function getRedirectPort(authorizationUrl) {
|
|
39
39
|
try {
|
|
@@ -91,7 +91,7 @@ async function attemptAutoAuth(state, serverName, signal) {
|
|
|
91
91
|
if (!state.ui && !isNonInteractiveOAuth(definition.oauth)) {
|
|
92
92
|
return {
|
|
93
93
|
status: "failed",
|
|
94
|
-
message: getAuthRequiredMessage(state, serverName, `Server "${serverName}" requires OAuth authentication. Run mcp({ action: "auth-start", server: "${serverName}" }) to get a browser URL, or /mcp-auth ${serverName} in an interactive local session.`),
|
|
94
|
+
message: getAuthRequiredMessage(state, serverName, `Server "${serverName}" requires OAuth authentication. If mcp is inactive, first mcp_search({ enable: ["gateway"] }). Run mcp({ action: "auth-start", server: "${serverName}" }) to get a browser URL, or /mcp-auth ${serverName} in an interactive local session.`),
|
|
95
95
|
};
|
|
96
96
|
}
|
|
97
97
|
try {
|
|
@@ -268,7 +268,7 @@ export async function executeAuthStart(state, serverName, signal) {
|
|
|
268
268
|
const definition = state.config.mcpServers[serverName];
|
|
269
269
|
if (!definition) {
|
|
270
270
|
return {
|
|
271
|
-
content: [{ type: "text", text: `Server "${serverName}" not found. Use mcp({ action: "status" }) to see available servers.` }],
|
|
271
|
+
content: [{ type: "text", text: `Server "${serverName}" not found. Use mcp({ action: "status" }) to see available servers (load it first with mcp_search({ enable: ["gateway"] }) if inactive).` }],
|
|
272
272
|
details: { mode: "auth-start", error: "not_found", server: serverName },
|
|
273
273
|
};
|
|
274
274
|
}
|
|
@@ -314,7 +314,7 @@ export async function executeAuthComplete(state, serverName, input, signal) {
|
|
|
314
314
|
const definition = state.config.mcpServers[serverName];
|
|
315
315
|
if (!definition) {
|
|
316
316
|
return {
|
|
317
|
-
content: [{ type: "text", text: `Server "${serverName}" not found. Use mcp({ action: "status" }) to see available servers.` }],
|
|
317
|
+
content: [{ type: "text", text: `Server "${serverName}" not found. Use mcp({ action: "status" }) to see available servers (load it first with mcp_search({ enable: ["gateway"] }) if inactive).` }],
|
|
318
318
|
details: { mode: "auth-complete", error: "not_found", server: serverName },
|
|
319
319
|
};
|
|
320
320
|
}
|
|
@@ -372,7 +372,7 @@ export function executeDescribe(state, toolName, serverFilter) {
|
|
|
372
372
|
return disabledResult("describe", disabled[0]);
|
|
373
373
|
const suggestions = rankSuggestions(state, toolName, 5, serverFilter);
|
|
374
374
|
const hint = suggestions.length > 0
|
|
375
|
-
? `Did you mean: ${suggestions.join(", ")}. Inspect with mcp({ action: "describe", tool: "${suggestions[0]}" }).`
|
|
375
|
+
? `Did you mean: ${suggestions.join(", ")}. Inspect with mcp({ action: "describe", tool: "${suggestions[0]}" }). Load if inactive: mcp_search({ enable: ["gateway"] }).`
|
|
376
376
|
: `Use mcp_search({ query: "..." }) to search.`;
|
|
377
377
|
return {
|
|
378
378
|
content: [{ type: "text", text: `Tool "${toolName}" not found. ${hint}` }],
|
|
@@ -387,9 +387,9 @@ export function executeDescribe(state, toolName, serverFilter) {
|
|
|
387
387
|
details: { mode: "describe", tool: toolMeta, server: serverName },
|
|
388
388
|
};
|
|
389
389
|
}
|
|
390
|
-
export function executeSearch(state, query, server, includeSchemas, limit = 12, offset = 0) {
|
|
390
|
+
export function executeSearch(state, query, server, includeSchemas, limit = 12, offset = 0, caller = "mcp") {
|
|
391
391
|
const showSchemas = includeSchemas !== false;
|
|
392
|
-
const searchCall = (nextOffset) =>
|
|
392
|
+
const searchCall = (nextOffset) => `${caller}({ ${caller === "mcp" ? 'action: "search", ' : ""}query: ${JSON.stringify(query)}${server ? `, server: ${JSON.stringify(server)}` : ""}${caller === "mcp" && !showSchemas ? ", includeSchemas: false" : ""}, limit: ${limit}, offset: ${nextOffset} })`;
|
|
393
393
|
if (server && isServerDisabled(state.config.mcpServers[server]))
|
|
394
394
|
return disabledResult("search", server);
|
|
395
395
|
let matches;
|
|
@@ -461,7 +461,7 @@ export function executeList(state, server, limit = 12, offset = 0) {
|
|
|
461
461
|
const definition = state.config.mcpServers[server];
|
|
462
462
|
if (!definition) {
|
|
463
463
|
return {
|
|
464
|
-
content: [{ type: "text", text: `Server "${server}" not found. Use mcp({ action: "status" }) to see available servers.` }],
|
|
464
|
+
content: [{ type: "text", text: `Server "${server}" not found. Use mcp({ action: "status" }) to see available servers (load it first with mcp_search({ enable: ["gateway"] }) if inactive).` }],
|
|
465
465
|
details: { mode: "list", server, tools: [], count: 0, error: "not_found" },
|
|
466
466
|
};
|
|
467
467
|
}
|
|
@@ -534,7 +534,7 @@ export function executeInstructions(state, server) {
|
|
|
534
534
|
const definition = state.config.mcpServers[server];
|
|
535
535
|
if (!definition) {
|
|
536
536
|
return {
|
|
537
|
-
content: [{ type: "text", text: `Server "${server}" not found. Use mcp({ action: "status" }) to see available servers.` }],
|
|
537
|
+
content: [{ type: "text", text: `Server "${server}" not found. Use mcp({ action: "status" }) to see available servers (load it first with mcp_search({ enable: ["gateway"] }) if inactive).` }],
|
|
538
538
|
details: { mode: "instructions", server, error: "not_found" },
|
|
539
539
|
};
|
|
540
540
|
}
|
|
@@ -565,7 +565,7 @@ export async function executeConnect(state, serverName, signal, limit, offset) {
|
|
|
565
565
|
const definition = state.config.mcpServers[serverName];
|
|
566
566
|
if (!definition) {
|
|
567
567
|
return {
|
|
568
|
-
content: [{ type: "text", text: `Server "${serverName}" not found. Use mcp({ action: "status" }) to see available servers.` }],
|
|
568
|
+
content: [{ type: "text", text: `Server "${serverName}" not found. Use mcp({ action: "status" }) to see available servers (load it first with mcp_search({ enable: ["gateway"] }) if inactive).` }],
|
|
569
569
|
details: { mode: "connect", error: "not_found", server: serverName },
|
|
570
570
|
};
|
|
571
571
|
}
|
|
@@ -670,7 +670,7 @@ export async function runToolCall(state, serverName, target, args, options) {
|
|
|
670
670
|
state.manager.touch(serverName);
|
|
671
671
|
state.manager.incrementInFlight(serverName);
|
|
672
672
|
uiSession = !target.resourceUri && target.uiResourceUri
|
|
673
|
-
? await maybeStartUiSession(state, {
|
|
673
|
+
? await abortable(maybeStartUiSession(state, {
|
|
674
674
|
serverName,
|
|
675
675
|
toolName: target.originalName,
|
|
676
676
|
toolArgs: args ?? {},
|
|
@@ -678,7 +678,7 @@ export async function runToolCall(state, serverName, target, args, options) {
|
|
|
678
678
|
...(target.uiStreamMode !== undefined ? { streamMode: target.uiStreamMode } : {}),
|
|
679
679
|
...(signal ? { signal } : {}),
|
|
680
680
|
onNeedsAuth: recoverAuthConnection,
|
|
681
|
-
})
|
|
681
|
+
}), callerSignal)
|
|
682
682
|
: null;
|
|
683
683
|
// UI preparation can replace the connection; use its current annotations.
|
|
684
684
|
const liveTools = state.manager.getConnection(serverName)?.tools;
|
|
@@ -720,7 +720,7 @@ export async function runToolCall(state, serverName, target, args, options) {
|
|
|
720
720
|
};
|
|
721
721
|
const result = target.resourceUri
|
|
722
722
|
? await dispatch(() => withSessionRecovery(recovery, serverName, conn => abortable(conn.client.readResource({ uri: target.resourceUri }, requestOptions), ownedSignal)))
|
|
723
|
-
: await dispatch(() => withSessionRecovery({ ...recovery, retryOnTransportFailure: annotations?.readOnlyHint === true || annotations?.idempotentHint === true }, serverName, conn => abortable(conn.client.callTool({ name: target.originalName, arguments: args ?? {}, _meta: uiSession?.requestMeta }, requestOptions), ownedSignal)));
|
|
723
|
+
: await dispatch(() => trackToolCallOutcome(() => withSessionRecovery({ ...recovery, retryOnTransportFailure: annotations?.readOnlyHint === true || annotations?.idempotentHint === true }, serverName, conn => abortable(conn.client.callTool({ name: target.originalName, arguments: args ?? {}, _meta: uiSession?.requestMeta }, requestOptions), ownedSignal)), ownedSignal));
|
|
724
724
|
if (!target.resourceUri)
|
|
725
725
|
uiSession?.sendToolResult(result);
|
|
726
726
|
const record = result;
|
|
@@ -762,8 +762,8 @@ export async function runToolCall(state, serverName, target, args, options) {
|
|
|
762
762
|
details: { ...detailsBase, ...retained, error: isAbortError(error, callerSignal) ? "aborted" : "call_capture_failed", message, recovery: context },
|
|
763
763
|
};
|
|
764
764
|
}
|
|
765
|
-
if (isToolTransportFailure(error)) {
|
|
766
|
-
const message = `The outcome of MCP tool "${target.originalName}" on "${serverName}" is unknown after
|
|
765
|
+
if (isToolTransportFailure(error) || isInterruptedToolCall(error)) {
|
|
766
|
+
const message = `The outcome of MCP tool "${target.originalName}" on "${serverName}" is unknown after the call was interrupted. Read back the original operation using its saved arguments and provider identity before continuing. Do not blindly repeat the call or rerun its script.`;
|
|
767
767
|
uiSession?.sendToolCancelled(message);
|
|
768
768
|
return {
|
|
769
769
|
content: [{ type: "text", text: message }],
|
|
@@ -962,6 +962,7 @@ export async function executeCall(state, toolName, args, serverOverride, getPiTo
|
|
|
962
962
|
let hint = suggestions.length
|
|
963
963
|
? ` Did you mean: ${suggestions.join(", ")}. Inspect with mcp({ action: "describe", tool: ${JSON.stringify(suggestions[0])} }).`
|
|
964
964
|
: serverName ? ` Search with mcp({ action: "search", query: ${JSON.stringify(toolName)}, server: ${JSON.stringify(serverName)} }).` : ' Use mcp({ action: "search", query: "..." }) to search.';
|
|
965
|
+
hint += ' If mcp is inactive, load it with mcp_search({ enable: ["gateway"] }).';
|
|
965
966
|
if (serverName && state.toolMetadata.has(serverName) && state.manager.getConnection(serverName)?.status !== "connected")
|
|
966
967
|
hint += ` Refresh a stale catalog with mcp({ action: "connect", server: ${JSON.stringify(serverName)} }).`;
|
|
967
968
|
return {
|
|
@@ -973,7 +974,7 @@ export async function executeCall(state, toolName, args, serverOverride, getPiTo
|
|
|
973
974
|
return missing();
|
|
974
975
|
const definition = state.config.mcpServers[serverName];
|
|
975
976
|
if (!definition)
|
|
976
|
-
return { content: [{ type: "text", text: `Server "${serverName}" not found. Use mcp({ action: "status" }) to see available servers.` }], details: { mode: "call", error: "server_not_found", server: serverName, requestedTool: toolName } };
|
|
977
|
+
return { content: [{ type: "text", text: `Server "${serverName}" not found. Use mcp({ action: "status" }) to see available servers (load it first with mcp_search({ enable: ["gateway"] }) if inactive).` }], details: { mode: "call", error: "server_not_found", server: serverName, requestedTool: toolName } };
|
|
977
978
|
if (isServerDisabled(definition))
|
|
978
979
|
return disabledResult("call", serverName);
|
|
979
980
|
const cached = state.toolMetadata.get(serverName);
|
package/dist/sampling-handler.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { truncateAtWord } from "./utils.js";
|
|
2
2
|
import { throwIfAborted } from "./abort.js";
|
|
3
|
+
import {} from "@modelcontextprotocol/client";
|
|
3
4
|
export function registerSamplingHandler(client, options, own = run => run()) {
|
|
4
5
|
// Own the handler's real promise, not the SDK caller's cancellable response facade.
|
|
5
6
|
client.setRequestHandler("sampling/createMessage", request => own(() => handleSamplingRequest(options, request)));
|
package/dist/search-ranking.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import MiniSearch from "minisearch";
|
|
1
|
+
import MiniSearch, {} from "minisearch";
|
|
2
2
|
import { getServerPrefix, isServerDisabled, isToolAllowed, resolveToolPrefix } from "./types.js";
|
|
3
3
|
export const MAX_PAGE_SIZE = 100;
|
|
4
4
|
export const MAX_TOOL_NAME_LENGTH = 512;
|
|
@@ -69,7 +69,11 @@ function searchCatalog(state, query, server, options) {
|
|
|
69
69
|
.sort((a, b) => b.score - a.score || a.tool.name.localeCompare(b.tool.name));
|
|
70
70
|
}
|
|
71
71
|
export function rankToolMatches(state, query, server) {
|
|
72
|
-
|
|
72
|
+
const matches = searchCatalog(state, query, server);
|
|
73
|
+
const identity = query.trim();
|
|
74
|
+
const exact = ({ tool }) => tool.name === identity || (Boolean(server) && tool.originalName === identity);
|
|
75
|
+
// Stable partition retains MiniSearch order and scores within both groups.
|
|
76
|
+
return [...matches.filter(exact), ...matches.filter(match => !exact(match))];
|
|
73
77
|
}
|
|
74
78
|
export function paginate(items, offset, limit) {
|
|
75
79
|
const safeOffset = Number.isFinite(offset) ? Math.max(0, Math.trunc(offset)) : 0;
|
package/dist/server-manager.d.ts
CHANGED
|
@@ -24,7 +24,6 @@ export interface ServerConnection {
|
|
|
24
24
|
type UiStreamListener = (serverName: string, notification: ServerStreamResultPatchNotification["params"]) => void;
|
|
25
25
|
type MetadataListChangedListener = (serverName: string, reason: string) => void;
|
|
26
26
|
export declare class McpServerManager {
|
|
27
|
-
private readonly defaultCwd?;
|
|
28
27
|
private ownedClients;
|
|
29
28
|
private connections;
|
|
30
29
|
private connectPromises;
|
|
@@ -56,7 +55,8 @@ export declare class McpServerManager {
|
|
|
56
55
|
* Preserve existing property setters (including tracing) rather than replacing their behavior. */
|
|
57
56
|
private fenceTransport;
|
|
58
57
|
/** Default cwd for stdio servers without an explicit config `cwd`. */
|
|
59
|
-
|
|
58
|
+
private readonly defaultCwd;
|
|
59
|
+
constructor(defaultCwd?: string);
|
|
60
60
|
setSamplingConfig(config: ServerSamplingConfig | undefined): void;
|
|
61
61
|
setMetadataListChangedListener(listener: MetadataListChangedListener | undefined): void;
|
|
62
62
|
setElicitationConfig(config: ServerElicitationConfig | undefined): void;
|
package/dist/server-manager.js
CHANGED
|
@@ -2,7 +2,7 @@ import { AsyncLocalStorage } from "node:async_hooks";
|
|
|
2
2
|
import { Client, StreamableHTTPClientTransport, SSEClientTransport, SdkHttpError, auth, extractWWWAuthenticateParams, UnauthorizedError, } from "@modelcontextprotocol/client";
|
|
3
3
|
import { StdioClientTransport } from "@modelcontextprotocol/client/stdio";
|
|
4
4
|
import { UnixSocketClientTransport } from "./unix-socket-transport.js";
|
|
5
|
-
import {
|
|
5
|
+
import { trackToolTransport, trackToolTransportFailure } from "./session-recovery.js";
|
|
6
6
|
import { isServerDisabled, isNonInteractiveOAuth, validateServerProtocolConfig, serverStreamResultPatchNotificationSchema, } from "./types.js";
|
|
7
7
|
import { resolveNpxBinary } from "./npx-resolver.js";
|
|
8
8
|
import { logger } from "./logger.js";
|
|
@@ -11,10 +11,10 @@ import { extractOAuthConfig, supportsOAuth, isOAuthChallenge, recordOAuthChallen
|
|
|
11
11
|
import { getAuthBaseDir } from "./mcp-auth.js";
|
|
12
12
|
import { registerSamplingHandler } from "./sampling-handler.js";
|
|
13
13
|
import { handleUrlElicitation, registerElicitationHandler, } from "./elicitation-handler.js";
|
|
14
|
-
import { normalizeRequestTimeoutMs, resolveBearerToken, resolveCommandSecret, resolveCommandSecretsRecord, resolveConfigPath, resolveServerUrl, } from "./utils.js";
|
|
14
|
+
import { ADAPTER_VERSION, normalizeRequestTimeoutMs, resolveBearerToken, resolveCommandSecret, resolveCommandSecretsRecord, resolveConfigPath, resolveServerUrl, } from "./utils.js";
|
|
15
15
|
import { abortable, throwIfAborted } from "./abort.js";
|
|
16
16
|
import { combineAbortSignals } from "./runtime-owner.js";
|
|
17
|
-
import { createMcpTraceWriter, isMcpTraceEnabled, traceTransportKind, wrapTransportWithMcpTrace, } from "./mcp-trace.js";
|
|
17
|
+
import { createMcpTraceWriter, isMcpTraceEnabled, McpTraceWriter, traceTransportKind, wrapTransportWithMcpTrace, } from "./mcp-trace.js";
|
|
18
18
|
const MAX_CAPTURED_STDERR_BYTES = 8 * 1024;
|
|
19
19
|
const MAX_CAPTURED_STDERR_LINES = 3;
|
|
20
20
|
const abortCleanupPromises = new WeakMap();
|
|
@@ -161,7 +161,6 @@ function appendStderrTail(tail, chunk) {
|
|
|
161
161
|
: combined;
|
|
162
162
|
}
|
|
163
163
|
export class McpServerManager {
|
|
164
|
-
defaultCwd;
|
|
165
164
|
// Includes native clients whose public connect/close facade ended before their send/auth tail.
|
|
166
165
|
// Their operation promises remain in the same clientOperations authority until settlement.
|
|
167
166
|
ownedClients = new Set();
|
|
@@ -267,6 +266,7 @@ export class McpServerManager {
|
|
|
267
266
|
}
|
|
268
267
|
}
|
|
269
268
|
/** Default cwd for stdio servers without an explicit config `cwd`. */
|
|
269
|
+
defaultCwd;
|
|
270
270
|
constructor(defaultCwd) {
|
|
271
271
|
this.defaultCwd = defaultCwd;
|
|
272
272
|
}
|
|
@@ -329,9 +329,30 @@ export class McpServerManager {
|
|
|
329
329
|
throwIfAborted(ownedSignal);
|
|
330
330
|
if (this.stopped)
|
|
331
331
|
throw new Error("MCP server manager is closed");
|
|
332
|
+
const wait = (promise, attempt) => {
|
|
333
|
+
attempt.waiters++;
|
|
334
|
+
return abortable(promise, ownedSignal).finally(() => {
|
|
335
|
+
if (--attempt.waiters === 0 && ownedSignal?.aborted)
|
|
336
|
+
attempt.controller.abort(ownedSignal.reason);
|
|
337
|
+
});
|
|
338
|
+
};
|
|
332
339
|
// Dedupe concurrent connection attempts.
|
|
333
|
-
|
|
334
|
-
|
|
340
|
+
const pending = this.connectPromises.get(name);
|
|
341
|
+
if (pending) {
|
|
342
|
+
const attempt = this.connectAttempts.get(name);
|
|
343
|
+
if (attempt.controller.signal.aborted) {
|
|
344
|
+
// Finish the canceled attempt's cleanup before starting a fresh one.
|
|
345
|
+
try {
|
|
346
|
+
await abortable(pending, ownedSignal);
|
|
347
|
+
}
|
|
348
|
+
catch (error) {
|
|
349
|
+
throwIfAborted(ownedSignal);
|
|
350
|
+
if (this.containsCleanupFailure(error))
|
|
351
|
+
throw error;
|
|
352
|
+
}
|
|
353
|
+
return this.connect(name, definition, signal);
|
|
354
|
+
}
|
|
355
|
+
return wait(pending, attempt);
|
|
335
356
|
}
|
|
336
357
|
const existing = this.connections.get(name);
|
|
337
358
|
if (existing?.status === "connected") {
|
|
@@ -339,10 +360,10 @@ export class McpServerManager {
|
|
|
339
360
|
return existing;
|
|
340
361
|
}
|
|
341
362
|
const generation = this.closeGenerations.get(name) ?? 0;
|
|
342
|
-
const
|
|
343
|
-
const attemptSignal = combineAbortSignals(
|
|
344
|
-
const promise = this.createConnection(name, definition, attemptSignal, ownedSignal).then(async (connection) => {
|
|
345
|
-
if (
|
|
363
|
+
const attempt = { controller: new AbortController(), waiters: 0 };
|
|
364
|
+
const attemptSignal = combineAbortSignals(this.runtimeSignal, attempt.controller.signal);
|
|
365
|
+
const promise = this.createConnection(name, definition, attemptSignal, ownedSignal ? attemptSignal : undefined).then(async (connection) => {
|
|
366
|
+
if (connection.status === "closed" || attempt.controller.signal.aborted || (this.closeGenerations.get(name) ?? 0) !== generation) {
|
|
346
367
|
await this.disposeConnection(connection);
|
|
347
368
|
throwIfAborted(attemptSignal);
|
|
348
369
|
throw new Error(`MCP connection for ${name} was closed while connecting`);
|
|
@@ -350,18 +371,15 @@ export class McpServerManager {
|
|
|
350
371
|
connection.inFlight = this.connections.get(name)?.inFlight ?? 0;
|
|
351
372
|
this.connections.set(name, connection);
|
|
352
373
|
return connection;
|
|
353
|
-
})
|
|
354
|
-
this.connectPromises.set(name, promise);
|
|
355
|
-
this.connectAttempts.set(name, attemptController);
|
|
356
|
-
try {
|
|
357
|
-
return await promise;
|
|
358
|
-
}
|
|
359
|
-
finally {
|
|
374
|
+
}).finally(() => {
|
|
360
375
|
if (this.connectPromises.get(name) === promise)
|
|
361
376
|
this.connectPromises.delete(name);
|
|
362
|
-
if (this.connectAttempts.get(name) ===
|
|
377
|
+
if (this.connectAttempts.get(name) === attempt)
|
|
363
378
|
this.connectAttempts.delete(name);
|
|
364
|
-
}
|
|
379
|
+
});
|
|
380
|
+
this.connectPromises.set(name, promise);
|
|
381
|
+
this.connectAttempts.set(name, attempt);
|
|
382
|
+
return wait(promise, attempt);
|
|
365
383
|
}
|
|
366
384
|
/**
|
|
367
385
|
* Reconnect a server whose connection was proven stale (e.g. by a 404
|
|
@@ -493,6 +511,8 @@ export class McpServerManager {
|
|
|
493
511
|
else {
|
|
494
512
|
transport = new UnixSocketClientTransport(resolveConfigPath(definition.socket));
|
|
495
513
|
}
|
|
514
|
+
if (!definition.url)
|
|
515
|
+
trackToolTransport(transport);
|
|
496
516
|
if (traceObserver) {
|
|
497
517
|
const traceTransportKindValue = traceTransportKind(definition, transport);
|
|
498
518
|
transport = wrapTransportWithMcpTrace(transport, name, traceTransportKindValue, traceObserver);
|
|
@@ -536,11 +556,9 @@ export class McpServerManager {
|
|
|
536
556
|
status: "connected",
|
|
537
557
|
oauthProvider,
|
|
538
558
|
};
|
|
539
|
-
//
|
|
540
|
-
// client's late close must never change its replacement's status.
|
|
559
|
+
// Track closure during discovery too; this only changes this client's connection.
|
|
541
560
|
client.onclose = () => {
|
|
542
|
-
|
|
543
|
-
connection.status = "closed";
|
|
561
|
+
connection.status = "closed";
|
|
544
562
|
};
|
|
545
563
|
const discoveryOptions = this.buildRequestOptions(definition, signal);
|
|
546
564
|
const catalogs = [
|
|
@@ -671,7 +689,7 @@ export class McpServerManager {
|
|
|
671
689
|
createClient(serverName, definition) {
|
|
672
690
|
const capabilities = this.buildClientCapabilities(definition);
|
|
673
691
|
let client;
|
|
674
|
-
client = new ManagedClient({ name: `pi-mcp-${serverName}`, version:
|
|
692
|
+
client = new ManagedClient({ name: `pi-mcp-${serverName}`, version: ADAPTER_VERSION }, {
|
|
675
693
|
versionNegotiation: { mode: definition.protocolVersion ?? (definition.url ? "auto" : "legacy") },
|
|
676
694
|
listMaxPages: 0,
|
|
677
695
|
...(Object.keys(capabilities).length > 0 ? { capabilities } : {}),
|
|
@@ -936,8 +954,7 @@ export class McpServerManager {
|
|
|
936
954
|
onAuthChallenge?.(error);
|
|
937
955
|
};
|
|
938
956
|
}
|
|
939
|
-
|
|
940
|
-
trackToolHttpFailures(transport);
|
|
957
|
+
trackToolTransport(transport, true);
|
|
941
958
|
return { transport, oauthProvider: authProvider !== undefined };
|
|
942
959
|
}
|
|
943
960
|
async fetchAllTools(client, requestOptions) {
|
|
@@ -1021,7 +1038,7 @@ export class McpServerManager {
|
|
|
1021
1038
|
async close(name) {
|
|
1022
1039
|
this.beforeActivity();
|
|
1023
1040
|
this.closeGenerations.set(name, (this.closeGenerations.get(name) ?? 0) + 1);
|
|
1024
|
-
this.connectAttempts.get(name)?.abort(new Error(`MCP connection ${name} was closed`));
|
|
1041
|
+
this.connectAttempts.get(name)?.controller.abort(new Error(`MCP connection ${name} was closed`));
|
|
1025
1042
|
const pendingClose = this.closePromises.get(name);
|
|
1026
1043
|
if (pendingClose)
|
|
1027
1044
|
return pendingClose;
|
|
@@ -2,15 +2,18 @@ import { type FetchLike, type Transport } from "@modelcontextprotocol/client";
|
|
|
2
2
|
import { type McpConfig } from "./types.ts";
|
|
3
3
|
import type { McpServerManager, ServerConnection } from "./server-manager.ts";
|
|
4
4
|
export declare function isToolTransportFailure(error: unknown): boolean;
|
|
5
|
-
|
|
5
|
+
export declare function isInterruptedToolCall(error: unknown): boolean;
|
|
6
|
+
/** Interrupted outcome reporting is separate from the transport retry policy. */
|
|
7
|
+
export declare function trackToolCallOutcome<T>(fn: () => Promise<T>, signal?: AbortSignal): Promise<T>;
|
|
8
|
+
/** Retain fetch/body-error origin without parsing or buffering the response. */
|
|
6
9
|
export declare const trackToolTransportFailure: FetchLike;
|
|
7
10
|
/** Observe only the originating tool send, not OAuth or catalog requests. */
|
|
8
|
-
export declare function
|
|
11
|
+
export declare function trackToolTransport(transport: Transport, http?: boolean): void;
|
|
9
12
|
export declare function isTerminatedSession(err: unknown, hadSessionId: boolean): boolean;
|
|
10
13
|
export declare class SessionRecoveryAuthRequiredError extends Error {
|
|
11
14
|
readonly serverName: string;
|
|
12
|
-
readonly authMessage
|
|
13
|
-
constructor(serverName: string, authMessage?: string
|
|
15
|
+
readonly authMessage: string | undefined;
|
|
16
|
+
constructor(serverName: string, authMessage?: string);
|
|
14
17
|
}
|
|
15
18
|
export interface AuthChallengeContext {
|
|
16
19
|
connection: ServerConnection;
|