@fitchmultz/pi-mcp-adapter 8.0.6 → 8.0.7
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 +128 -8
- package/OAUTH.md +13 -16
- package/README.md +8 -8
- package/cli.js +67 -28
- package/dist/abort.js +18 -9
- package/dist/client-operations.js +4 -2
- package/dist/commands.js +77 -43
- package/dist/config.js +194 -105
- package/dist/connection-runtime.d.ts +2 -2
- package/dist/connection-runtime.js +29 -18
- package/dist/consent-manager.d.ts +2 -2
- package/dist/consent-manager.js +5 -2
- package/dist/direct-tools.d.ts +1 -1
- package/dist/direct-tools.js +13 -7
- package/dist/elicitation-handler.d.ts +2 -3
- package/dist/elicitation-handler.js +113 -58
- package/dist/gateway-arguments.d.ts +1 -1
- package/dist/gateway-arguments.js +90 -23
- package/dist/glimpse-ui.js +10 -5
- package/dist/host-html-template.d.ts +3 -1
- package/dist/host-html-template.js +9 -12
- package/dist/index.d.ts +1 -1
- package/dist/index.js +264 -119
- package/dist/init.d.ts +1 -3
- package/dist/init.js +91 -51
- package/dist/legacy-migration.d.ts +1 -1
- package/dist/legacy-migration.js +17 -12
- package/dist/lifecycle.d.ts +3 -3
- package/dist/lifecycle.js +33 -17
- package/dist/logger.d.ts +2 -2
- package/dist/logger.js +4 -2
- package/dist/mcp-auth-flow.js +150 -58
- package/dist/mcp-auth.d.ts +7 -7
- package/dist/mcp-auth.js +189 -138
- package/dist/mcp-callback-server.js +19 -8
- package/dist/mcp-code.js +168 -54
- package/dist/mcp-keyring-helper.cjs +57 -23
- package/dist/mcp-oauth-provider.d.ts +6 -7
- package/dist/mcp-oauth-provider.js +146 -72
- package/dist/mcp-oauth-runtime.js +29 -16
- package/dist/mcp-output-guard.js +193 -65
- package/dist/mcp-output-preview.js +41 -20
- package/dist/mcp-panel.d.ts +9 -9
- package/dist/mcp-panel.js +141 -70
- package/dist/mcp-script-worker.mjs +135 -43
- package/dist/mcp-setup-panel.d.ts +8 -8
- package/dist/mcp-setup-panel.js +130 -44
- package/dist/mcp-status.js +14 -7
- package/dist/mcp-trace.d.ts +10 -5
- package/dist/mcp-trace.js +127 -61
- package/dist/metadata-cache.d.ts +3 -4
- package/dist/metadata-cache.js +83 -43
- package/dist/npx-resolver.js +101 -60
- package/dist/onboarding-state.js +4 -2
- package/dist/plain-result-reader.js +78 -31
- package/dist/prompts.js +36 -20
- package/dist/proxy-modes.js +670 -193
- package/dist/resource-tools.js +30 -9
- package/dist/runtime-owner.js +36 -18
- package/dist/sampling-handler.d.ts +1 -2
- package/dist/sampling-handler.js +41 -21
- package/dist/search-ranking.d.ts +1 -1
- package/dist/search-ranking.js +67 -34
- package/dist/server-manager.d.ts +11 -11
- package/dist/server-manager.js +283 -166
- package/dist/session-recovery.js +113 -61
- package/dist/tool-approval.js +9 -3
- package/dist/tool-loader.js +154 -55
- package/dist/tool-metadata.d.ts +1 -1
- package/dist/tool-metadata.js +51 -23
- package/dist/tool-registrar.js +32 -10
- package/dist/tool-result-renderer.js +58 -33
- package/dist/types.d.ts +2 -2
- package/dist/types.js +39 -18
- package/dist/ui-message-history.js +33 -13
- package/dist/ui-resource-handler.d.ts +3 -3
- package/dist/ui-resource-handler.js +37 -21
- package/dist/ui-server.js +101 -43
- package/dist/ui-session.js +66 -29
- package/dist/ui-stream-types.js +14 -4
- package/dist/ui-tool-visibility.js +12 -6
- package/dist/unix-socket-transport.d.ts +1 -2
- package/dist/unix-socket-transport.js +19 -12
- package/dist/utils.d.ts +2 -0
- package/dist/utils.js +60 -35
- package/package.json +26 -2
- package/skills/mcp-scripting/SKILL.md +6 -6
package/dist/index.js
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import { Type } from "typebox";
|
|
2
|
-
import { cloneMcpConfig, isPathInsideProject, loadMcpConfig, writeProjectServerDisabledOverride } from "./config.js";
|
|
3
|
-
import { buildProxyDescription, directToolSelection, getMissingConfiguredDirectToolServers } from "./direct-tools.js";
|
|
4
|
-
import { getMetadataCachePath, isServerCacheValid, loadMetadataCache, reconstructToolMetadata } from "./metadata-cache.js";
|
|
2
|
+
import { cloneMcpConfig, isPathInsideProject, loadMcpConfig, writeProjectServerDisabledOverride, } from "./config.js";
|
|
3
|
+
import { buildProxyDescription, directToolSelection, getMissingConfiguredDirectToolServers, } from "./direct-tools.js";
|
|
4
|
+
import { getMetadataCachePath, isServerCacheValid, loadMetadataCache, reconstructToolMetadata, } from "./metadata-cache.js";
|
|
5
5
|
import { createPromptCommand, resolveCachedPrompts } from "./prompts.js";
|
|
6
6
|
import { logger } from "./logger.js";
|
|
7
|
-
import { DEFAULT_MCP_SCRIPT_TIMEOUT_MS, formatTerminalError } from "./utils.js";
|
|
7
|
+
import { DEFAULT_MCP_SCRIPT_TIMEOUT_MS, formatTerminalError, MAX_CONCURRENT_SERVER_CONNECTS, parallelLimit, } from "./utils.js";
|
|
8
8
|
import { createOAuthRuntime, shutdownOAuth } from "./mcp-oauth-runtime.js";
|
|
9
9
|
import { renderMcpProxyToolCall, renderMcpToolResult } from "./tool-result-renderer.js";
|
|
10
|
-
import { createMcpRuntimeOwner, createOwnedUi, isAbortError } from "./runtime-owner.js";
|
|
10
|
+
import { createMcpRuntimeOwner, createOwnedUi, isAbortError, } from "./runtime-owner.js";
|
|
11
11
|
import { publishMcpStatusShutdown } from "./mcp-status.js";
|
|
12
12
|
import { MAX_PAGE_SIZE, paginate, rankToolMatches } from "./search-ranking.js";
|
|
13
13
|
import { createToolLoader } from "./tool-loader.js";
|
|
14
|
-
import { gatewayParameters, prepareGatewayArguments } from "./gateway-arguments.js";
|
|
15
|
-
import { guardMcpOutput, guardedMcpDetails, readMcpResult, resolveMcpOutputGuardOptions } from "./mcp-output-guard.js";
|
|
14
|
+
import { gatewayParameters, prepareGatewayArguments, } from "./gateway-arguments.js";
|
|
15
|
+
import { guardMcpOutput, guardedMcpDetails, readMcpResult, resolveMcpOutputGuardOptions, } from "./mcp-output-guard.js";
|
|
16
16
|
import { abortable, throwIfAborted } from "./abort.js";
|
|
17
17
|
export { MCP_STATUS_EVENT, MCP_STATUS_SNAPSHOT_VERSION, } from "./types.js";
|
|
18
18
|
const INIT_WAIT_TIMEOUT_MS = 30_000;
|
|
@@ -71,43 +71,49 @@ function installMcpAdapter(pi, options) {
|
|
|
71
71
|
failures.push(error);
|
|
72
72
|
}
|
|
73
73
|
try {
|
|
74
|
-
if (currentState.owner)
|
|
74
|
+
if (currentState.owner) {
|
|
75
75
|
await currentState.owner.stop(reason);
|
|
76
|
-
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
77
78
|
await currentState.lifecycle.gracefulShutdown();
|
|
79
|
+
}
|
|
78
80
|
}
|
|
79
81
|
catch (error) {
|
|
80
82
|
failures.push(error);
|
|
81
83
|
}
|
|
82
|
-
if (failures.length)
|
|
84
|
+
if (failures.length) {
|
|
83
85
|
throw new AggregateError(failures, "MCP state persistence/cleanup failed");
|
|
86
|
+
}
|
|
84
87
|
}
|
|
85
|
-
const earlyConfig = programmaticConfig
|
|
86
|
-
? cloneMcpConfig(sessionConfig)
|
|
87
|
-
: { mcpServers: {} };
|
|
88
|
+
const earlyConfig = programmaticConfig ? cloneMcpConfig(sessionConfig) : { mcpServers: {} };
|
|
88
89
|
const earlyCache = null;
|
|
89
90
|
let currentConfig = earlyConfig;
|
|
90
91
|
const envRaw = process.env.MCP_DIRECT_TOOLS;
|
|
91
|
-
const envDirectToolOverride = envRaw
|
|
92
|
+
const envDirectToolOverride = envRaw
|
|
93
|
+
?.split(",")
|
|
94
|
+
.map((s) => s.trim())
|
|
95
|
+
.filter(Boolean);
|
|
92
96
|
const toolLoader = createToolLoader(pi, () => state, () => initPromise, beforeExecute);
|
|
93
97
|
let runtimeCwd;
|
|
94
98
|
let proxyToolRegistered = false;
|
|
95
99
|
let proxyToolDescription = null;
|
|
96
100
|
let directToolsFrozen = false;
|
|
97
101
|
function applyDirectToolConfigChanges(changes) {
|
|
98
|
-
if (!state)
|
|
102
|
+
if (!state) {
|
|
99
103
|
return;
|
|
104
|
+
}
|
|
100
105
|
for (const [serverName, value] of changes) {
|
|
101
106
|
const definition = state.config.mcpServers[serverName];
|
|
102
|
-
if (!definition)
|
|
107
|
+
if (!definition) {
|
|
103
108
|
continue;
|
|
109
|
+
}
|
|
104
110
|
state.config.mcpServers[serverName] = { ...definition, directTools: value };
|
|
105
111
|
}
|
|
106
112
|
}
|
|
107
113
|
function syncToolSurface(ctx) {
|
|
108
114
|
const config = state?.config ?? currentConfig;
|
|
109
115
|
const cache = loadMetadataCache(state?.metadataCacheEnabled ?? false);
|
|
110
|
-
toolLoader.sync(config, cache, envRaw === "__none__" ? null : envDirectToolOverride, specs => syncGateways(config, cache, specs));
|
|
116
|
+
toolLoader.sync(config, cache, envRaw === "__none__" ? null : envDirectToolOverride, (specs) => syncGateways(config, cache, specs));
|
|
111
117
|
}
|
|
112
118
|
const registeredPromptCommands = new Set();
|
|
113
119
|
function registerPromptCommands(specs) {
|
|
@@ -123,8 +129,9 @@ function installMcpAdapter(pi, options) {
|
|
|
123
129
|
function syncPromptCommands() {
|
|
124
130
|
registerPromptCommands([...(state?.promptMetadata?.values() ?? [])].flat());
|
|
125
131
|
}
|
|
126
|
-
if (!options.transformConfig)
|
|
132
|
+
if (!options.transformConfig) {
|
|
127
133
|
registerPromptCommands(resolveCachedPrompts(earlyConfig, false));
|
|
134
|
+
}
|
|
128
135
|
const getPiTools = () => pi.getAllTools();
|
|
129
136
|
pi.registerFlag("mcp-config", {
|
|
130
137
|
description: "Path to MCP config file",
|
|
@@ -133,13 +140,16 @@ function installMcpAdapter(pi, options) {
|
|
|
133
140
|
function startInitialization(init, ctx, owner, oauthRuntime, runtimeConfig, generation) {
|
|
134
141
|
const promise = init.initializeMcp(pi, ctx, owner, {
|
|
135
142
|
...(programmaticConfig ? { config: runtimeConfig } : { resolvedConfig: runtimeConfig }),
|
|
136
|
-
...(options.outputDirectory !== undefined
|
|
143
|
+
...(options.outputDirectory !== undefined
|
|
144
|
+
? { outputDirectory: options.outputDirectory }
|
|
145
|
+
: {}),
|
|
137
146
|
oauthRuntime,
|
|
138
147
|
statusEvents: pi.events,
|
|
139
148
|
...(options.onToolCall ? { onToolCall: options.onToolCall } : {}),
|
|
140
149
|
});
|
|
141
150
|
initPromise = promise;
|
|
142
|
-
return promise
|
|
151
|
+
return promise
|
|
152
|
+
.then(async (nextState) => {
|
|
143
153
|
if (!owner.isActive() || generation !== lifecycleGeneration || initPromise !== promise) {
|
|
144
154
|
try {
|
|
145
155
|
await shutdownState(nextState, "stale_session_start");
|
|
@@ -151,8 +161,9 @@ function installMcpAdapter(pi, options) {
|
|
|
151
161
|
}
|
|
152
162
|
state = nextState;
|
|
153
163
|
nextState.onToolMetadataUpdated = (_serverName, _reason) => {
|
|
154
|
-
if (state !== nextState || !owner.isActive())
|
|
164
|
+
if (state !== nextState || !owner.isActive()) {
|
|
155
165
|
return;
|
|
166
|
+
}
|
|
156
167
|
syncPromptCommands();
|
|
157
168
|
if (directToolsFrozen) {
|
|
158
169
|
logger.debug(`MCP: metadata update for ${_serverName} (${_reason}) skipped — directTools frozen`);
|
|
@@ -160,9 +171,11 @@ function installMcpAdapter(pi, options) {
|
|
|
160
171
|
}
|
|
161
172
|
syncToolSurface(ctx);
|
|
162
173
|
};
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
174
|
+
const uncachedSelectedServers = toolLoader
|
|
175
|
+
.selectedServers()
|
|
176
|
+
.filter((server) => !nextState.toolMetadata.has(server) && nextState.config.mcpServers[server]);
|
|
177
|
+
if (uncachedSelectedServers.length > 0) {
|
|
178
|
+
await parallelLimit(uncachedSelectedServers, MAX_CONCURRENT_SERVER_CONNECTS, (server) => init.lazyConnect(nextState, server, owner.signal));
|
|
166
179
|
}
|
|
167
180
|
owner.throwIfInactive();
|
|
168
181
|
syncPromptCommands();
|
|
@@ -171,9 +184,10 @@ function installMcpAdapter(pi, options) {
|
|
|
171
184
|
initPromise = null;
|
|
172
185
|
if (nextState.config.settings?.freezeDirectTools === true) {
|
|
173
186
|
directToolsFrozen = true;
|
|
174
|
-
logger.info(
|
|
187
|
+
logger.info('MCP: direct tools frozen after initial sync — reconnects won\'t rebuild the system prompt; use mcp({ action: "connect", server: "server" }) to rediscover');
|
|
175
188
|
}
|
|
176
|
-
})
|
|
189
|
+
})
|
|
190
|
+
.catch(async (err) => {
|
|
177
191
|
if (!owner.isActive() || generation !== lifecycleGeneration) {
|
|
178
192
|
return;
|
|
179
193
|
}
|
|
@@ -182,13 +196,11 @@ function installMcpAdapter(pi, options) {
|
|
|
182
196
|
}
|
|
183
197
|
console.error(`MCP initialization failed: ${formatTerminalError(err)}`);
|
|
184
198
|
initPromise = null;
|
|
185
|
-
if (state)
|
|
199
|
+
if (state) {
|
|
186
200
|
return;
|
|
201
|
+
}
|
|
187
202
|
try {
|
|
188
|
-
await Promise.all([
|
|
189
|
-
owner.stop("MCP initialization failed"),
|
|
190
|
-
shutdownOAuth(oauthRuntime),
|
|
191
|
-
]);
|
|
203
|
+
await Promise.all([owner.stop("MCP initialization failed"), shutdownOAuth(oauthRuntime)]);
|
|
192
204
|
}
|
|
193
205
|
catch (error) {
|
|
194
206
|
console.error(`MCP: failed to clean rejected initialization: ${formatTerminalError(error)}`);
|
|
@@ -221,8 +233,9 @@ function installMcpAdapter(pi, options) {
|
|
|
221
233
|
catch (error) {
|
|
222
234
|
console.error(`MCP: failed to shut down previous session state: ${formatTerminalError(error)}`);
|
|
223
235
|
}
|
|
224
|
-
if (generation !== lifecycleGeneration || !owner.isActive())
|
|
236
|
+
if (generation !== lifecycleGeneration || !owner.isActive()) {
|
|
225
237
|
return;
|
|
238
|
+
}
|
|
226
239
|
let runtimeConfig;
|
|
227
240
|
if (programmaticConfig) {
|
|
228
241
|
currentConfigPath = undefined;
|
|
@@ -230,24 +243,27 @@ function installMcpAdapter(pi, options) {
|
|
|
230
243
|
}
|
|
231
244
|
else {
|
|
232
245
|
const registeredConfigPath = pi.getFlag("mcp-config");
|
|
233
|
-
currentConfigPath =
|
|
234
|
-
??
|
|
235
|
-
|
|
246
|
+
currentConfigPath =
|
|
247
|
+
options.configPath ??
|
|
248
|
+
(typeof registeredConfigPath === "string" ? registeredConfigPath : undefined);
|
|
249
|
+
runtimeConfig = loadMcpConfig(currentConfigPath, ctx.cwd, {
|
|
250
|
+
includeProject: ctx.isProjectTrusted(),
|
|
251
|
+
});
|
|
236
252
|
}
|
|
237
253
|
if (options.transformConfig) {
|
|
238
254
|
runtimeConfig = cloneMcpConfig(options.transformConfig(cloneMcpConfig(runtimeConfig), ctx));
|
|
239
255
|
}
|
|
240
256
|
currentConfig = runtimeConfig;
|
|
241
|
-
const metadataCacheEnabled = ctx.isProjectTrusted()
|
|
242
|
-
|| !isPathInsideProject(getMetadataCachePath(), ctx.cwd);
|
|
257
|
+
const metadataCacheEnabled = ctx.isProjectTrusted() || !isPathInsideProject(getMetadataCachePath(), ctx.cwd);
|
|
243
258
|
toolLoader.restore(ctx);
|
|
244
259
|
registerPromptCommands(resolveCachedPrompts(runtimeConfig, metadataCacheEnabled));
|
|
245
260
|
const runtimeCache = loadMetadataCache(metadataCacheEnabled);
|
|
246
|
-
toolLoader.sync(runtimeConfig, runtimeCache, envRaw === "__none__" ? null : envDirectToolOverride, specs => syncGateways(runtimeConfig, runtimeCache, specs));
|
|
261
|
+
toolLoader.sync(runtimeConfig, runtimeCache, envRaw === "__none__" ? null : envDirectToolOverride, (specs) => syncGateways(runtimeConfig, runtimeCache, specs));
|
|
247
262
|
const init = await import("./init.js");
|
|
248
263
|
initModule = init;
|
|
249
|
-
if (generation !== lifecycleGeneration || !owner.isActive())
|
|
264
|
+
if (generation !== lifecycleGeneration || !owner.isActive()) {
|
|
250
265
|
return;
|
|
266
|
+
}
|
|
251
267
|
const initialization = startInitialization(init, ctx, owner, oauthRuntime, runtimeConfig, generation);
|
|
252
268
|
if (envRaw !== undefined && envRaw !== "__none__") {
|
|
253
269
|
const missingEnvDirectTools = getMissingConfiguredDirectToolServers(runtimeConfig, runtimeCache, envDirectToolOverride);
|
|
@@ -262,12 +278,14 @@ function installMcpAdapter(pi, options) {
|
|
|
262
278
|
syncToolSurface(ctx);
|
|
263
279
|
});
|
|
264
280
|
pi.on("model_select", (_event, ctx) => {
|
|
265
|
-
if (state)
|
|
281
|
+
if (state) {
|
|
266
282
|
syncToolSurface(ctx);
|
|
283
|
+
}
|
|
267
284
|
});
|
|
268
285
|
pi.on("before_agent_start", async (_event, ctx) => {
|
|
269
|
-
if (ctx.cwd !== runtimeCwd)
|
|
286
|
+
if (ctx.cwd !== runtimeCwd) {
|
|
270
287
|
await startSession(ctx);
|
|
288
|
+
}
|
|
271
289
|
});
|
|
272
290
|
pi.on("session_shutdown", async () => {
|
|
273
291
|
// Cached tool selections exist before background server initialization finishes.
|
|
@@ -288,10 +306,11 @@ function installMcpAdapter(pi, options) {
|
|
|
288
306
|
shutdownState(currentState, "session_shutdown"),
|
|
289
307
|
oauthRuntime ? shutdownOAuth(oauthRuntime) : Promise.resolve(),
|
|
290
308
|
]);
|
|
291
|
-
const failures = results.flatMap(result => result.status === "rejected" ? [result.reason] : []);
|
|
309
|
+
const failures = results.flatMap((result) => result.status === "rejected" ? [result.reason] : []);
|
|
292
310
|
// Ordinary extension error handling owns reporting. Strict clean-exit hosts must see failure.
|
|
293
|
-
if (failures.length)
|
|
311
|
+
if (failures.length) {
|
|
294
312
|
throw new AggregateError(failures, "MCP session shutdown persistence/cleanup failed");
|
|
313
|
+
}
|
|
295
314
|
});
|
|
296
315
|
function createCommandContext(ctx) {
|
|
297
316
|
const owner = currentOwner;
|
|
@@ -322,8 +341,9 @@ function installMcpAdapter(pi, options) {
|
|
|
322
341
|
return null;
|
|
323
342
|
}
|
|
324
343
|
}
|
|
325
|
-
if (!state)
|
|
344
|
+
if (!state) {
|
|
326
345
|
ctx.ui?.notify("MCP not initialized", "error");
|
|
346
|
+
}
|
|
327
347
|
return state;
|
|
328
348
|
}
|
|
329
349
|
pi.registerCommand("mcp", {
|
|
@@ -345,10 +365,14 @@ function installMcpAdapter(pi, options) {
|
|
|
345
365
|
return subcommands.length > 0 ? subcommands : null;
|
|
346
366
|
}
|
|
347
367
|
const [, subcommand, argumentPrefix] = argumentMatch;
|
|
348
|
-
if ((subcommand !== "reconnect" &&
|
|
349
|
-
|
|
350
|
-
|
|
368
|
+
if ((subcommand !== "reconnect" &&
|
|
369
|
+
subcommand !== "logout" &&
|
|
370
|
+
subcommand !== "disable" &&
|
|
371
|
+
subcommand !== "enable") ||
|
|
372
|
+
argumentPrefix === undefined ||
|
|
373
|
+
!state) {
|
|
351
374
|
return null;
|
|
375
|
+
}
|
|
352
376
|
const servers = Object.keys(state.config.mcpServers)
|
|
353
377
|
.filter((serverName) => serverName.startsWith(argumentPrefix.trimStart()))
|
|
354
378
|
.map((serverName) => ({ value: `${subcommand} ${serverName}`, label: serverName }));
|
|
@@ -358,9 +382,10 @@ function installMcpAdapter(pi, options) {
|
|
|
358
382
|
const { owner: commandOwner, context: commandCtx } = createCommandContext(ctx);
|
|
359
383
|
const commandProjectTrusted = commandCtx.isProjectTrusted();
|
|
360
384
|
const commandState = await ensureCommandState(commandOwner, commandCtx);
|
|
361
|
-
if (!commandState)
|
|
385
|
+
if (!commandState) {
|
|
362
386
|
return;
|
|
363
|
-
|
|
387
|
+
}
|
|
388
|
+
const { showStatus, showTools, showPrompts, reconnectServers, logoutServer, openMcpPanel, openMcpSetup, } = await import("./commands.js");
|
|
364
389
|
const parts = args?.trim()?.split(/\s+/) ?? [];
|
|
365
390
|
const subcommand = parts[0] ?? "";
|
|
366
391
|
const targetServer = parts[1];
|
|
@@ -369,8 +394,9 @@ function installMcpAdapter(pi, options) {
|
|
|
369
394
|
case "reconnect":
|
|
370
395
|
commandOwner?.throwIfInactive();
|
|
371
396
|
await reconnectServers(commandState, commandCtx, targetServer);
|
|
372
|
-
if (directToolsFrozen)
|
|
397
|
+
if (directToolsFrozen) {
|
|
373
398
|
syncToolSurface(commandCtx);
|
|
399
|
+
}
|
|
374
400
|
break;
|
|
375
401
|
case "tools":
|
|
376
402
|
await showTools(commandState, commandCtx);
|
|
@@ -395,8 +421,9 @@ function installMcpAdapter(pi, options) {
|
|
|
395
421
|
case "logout": {
|
|
396
422
|
const serverName = rest;
|
|
397
423
|
if (!serverName) {
|
|
398
|
-
if (commandCtx.hasUI)
|
|
424
|
+
if (commandCtx.hasUI) {
|
|
399
425
|
commandCtx.ui?.notify("Usage: /mcp logout <server>", "error");
|
|
426
|
+
}
|
|
400
427
|
return;
|
|
401
428
|
}
|
|
402
429
|
commandOwner?.throwIfInactive();
|
|
@@ -468,8 +495,9 @@ function installMcpAdapter(pi, options) {
|
|
|
468
495
|
return;
|
|
469
496
|
}
|
|
470
497
|
const commandState = await ensureCommandState(commandOwner, commandCtx);
|
|
471
|
-
if (!commandState)
|
|
498
|
+
if (!commandState) {
|
|
472
499
|
return;
|
|
500
|
+
}
|
|
473
501
|
const { authenticateServer, openMcpAuthPanel, reconnectServer } = await import("./commands.js");
|
|
474
502
|
if (!serverName) {
|
|
475
503
|
if (programmaticConfig) {
|
|
@@ -491,76 +519,143 @@ function installMcpAdapter(pi, options) {
|
|
|
491
519
|
if (!state && initPromise) {
|
|
492
520
|
try {
|
|
493
521
|
const initialized = await awaitWithTimeout(abortable(initPromise, signal), INIT_WAIT_TIMEOUT_MS);
|
|
494
|
-
if (initialized === INIT_WAIT_TIMED_OUT)
|
|
522
|
+
if (initialized === INIT_WAIT_TIMED_OUT) {
|
|
495
523
|
return {
|
|
496
|
-
content: [
|
|
524
|
+
content: [
|
|
525
|
+
{
|
|
526
|
+
type: "text",
|
|
527
|
+
text: "MCP initialization is still in progress. Try again shortly.",
|
|
528
|
+
},
|
|
529
|
+
],
|
|
497
530
|
details: { error: "init_timeout", timeoutMs: INIT_WAIT_TIMEOUT_MS },
|
|
498
531
|
};
|
|
532
|
+
}
|
|
499
533
|
owner?.throwIfInactive();
|
|
500
534
|
state = initialized;
|
|
501
535
|
}
|
|
502
536
|
catch (error) {
|
|
503
|
-
if (signal?.aborted || (owner && isAbortError(error, owner.signal)))
|
|
537
|
+
if (signal?.aborted || (owner && isAbortError(error, owner.signal))) {
|
|
504
538
|
throw error;
|
|
539
|
+
}
|
|
505
540
|
const message = error instanceof Error ? error.message : String(error);
|
|
506
|
-
return {
|
|
541
|
+
return {
|
|
542
|
+
content: [{ type: "text", text: `MCP initialization failed: ${message}` }],
|
|
543
|
+
details: { error: "init_failed", message },
|
|
544
|
+
};
|
|
507
545
|
}
|
|
508
546
|
}
|
|
509
547
|
owner?.throwIfInactive();
|
|
510
|
-
return state ?? {
|
|
548
|
+
return (state ?? {
|
|
549
|
+
content: [{ type: "text", text: "MCP not initialized" }],
|
|
550
|
+
details: { error: "not_initialized" },
|
|
551
|
+
});
|
|
511
552
|
}
|
|
512
|
-
const unavailableFeatures = (enable = [], tools) => enable.filter(feature => !tools.some(tool => tool.name === (feature === "gateway" ? "mcp" : "mcp_script")));
|
|
553
|
+
const unavailableFeatures = (enable = [], tools) => enable.filter((feature) => !tools.some((tool) => tool.name === (feature === "gateway" ? "mcp" : "mcp_script")));
|
|
513
554
|
async function searchAndLoad(params, signal, ctx) {
|
|
514
555
|
throwIfAborted(signal);
|
|
515
|
-
if (params.query === undefined && !params.enable?.length)
|
|
556
|
+
if (params.query === undefined && !params.enable?.length) {
|
|
516
557
|
throw new Error("Provide query or enable.");
|
|
558
|
+
}
|
|
517
559
|
// Loading front doors does not require initialization or connect to a server.
|
|
518
560
|
if (params.query === undefined) {
|
|
519
561
|
const tools = toolLoader.activate([], params.enable);
|
|
520
562
|
const unavailable = unavailableFeatures(params.enable, tools);
|
|
521
|
-
return {
|
|
563
|
+
return {
|
|
564
|
+
content: [
|
|
565
|
+
{
|
|
566
|
+
type: "text",
|
|
567
|
+
text: `Loaded for the next request: ${JSON.stringify(tools)}${unavailable.length ? `. Unavailable under configuration or host policy: ${unavailable.join(", ")}` : ""}`,
|
|
568
|
+
},
|
|
569
|
+
],
|
|
570
|
+
details: { loaded: tools, unavailable },
|
|
571
|
+
tools,
|
|
572
|
+
};
|
|
522
573
|
}
|
|
523
574
|
const ready = await getToolState(signal);
|
|
524
|
-
if ("content" in ready)
|
|
575
|
+
if ("content" in ready) {
|
|
525
576
|
return { ...ready, tools: [] };
|
|
577
|
+
}
|
|
526
578
|
const proxy = await import("./proxy-modes.js");
|
|
527
579
|
if (params.server && !ready.toolMetadata.has(params.server)) {
|
|
528
580
|
const discovery = await proxy.executeConnect(ready, params.server, signal);
|
|
529
|
-
if (discovery.details.error)
|
|
581
|
+
if (discovery.details.error) {
|
|
530
582
|
return { ...discovery, tools: [] };
|
|
583
|
+
}
|
|
531
584
|
}
|
|
532
585
|
syncToolSurface(ctx);
|
|
533
|
-
const matches = params.query.trim()
|
|
534
|
-
|
|
586
|
+
const matches = params.query.trim()
|
|
587
|
+
? rankToolMatches(ready, params.query, params.server)
|
|
588
|
+
: params.server
|
|
589
|
+
? (ready.toolMetadata.get(params.server) ?? [])
|
|
590
|
+
.filter((tool) => !tool.resourceUri)
|
|
591
|
+
.map((tool) => ({ server: params.server, tool }))
|
|
592
|
+
.sort((a, b) => a.tool.name.localeCompare(b.tool.name))
|
|
593
|
+
: [];
|
|
535
594
|
const page = paginate(matches, params.offset ?? 0, params.limit ?? 5);
|
|
536
595
|
const tools = toolLoader.activate(page.items, params.enable);
|
|
537
596
|
const unavailable = unavailableFeatures(params.enable, tools);
|
|
538
|
-
const typedCount = tools.filter(tool => tool.name !== "mcp" && tool.name !== "mcp_script").length;
|
|
597
|
+
const typedCount = tools.filter((tool) => tool.name !== "mcp" && tool.name !== "mcp_script").length;
|
|
539
598
|
const result = proxy.executeSearch(ready, params.query, params.server, typedCount < page.items.length, params.limit ?? 5, params.offset, "mcp_search");
|
|
540
599
|
const guarded = await guardMcpOutput([
|
|
541
600
|
...result.content,
|
|
542
|
-
{
|
|
543
|
-
|
|
601
|
+
{
|
|
602
|
+
type: "text",
|
|
603
|
+
text: tools.length
|
|
604
|
+
? `Loaded for the next request: ${JSON.stringify(tools)}`
|
|
605
|
+
: '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.',
|
|
606
|
+
},
|
|
607
|
+
...(unavailable.length
|
|
608
|
+
? [
|
|
609
|
+
{
|
|
610
|
+
type: "text",
|
|
611
|
+
text: `Unavailable under configuration or host policy: ${unavailable.join(", ")}`,
|
|
612
|
+
},
|
|
613
|
+
]
|
|
614
|
+
: []),
|
|
544
615
|
], resolveMcpOutputGuardOptions(ready.config.settings, ready.outputDirectory));
|
|
545
|
-
return {
|
|
616
|
+
return {
|
|
617
|
+
content: guarded.content,
|
|
618
|
+
details: {
|
|
619
|
+
...result.details,
|
|
620
|
+
...guardedMcpDetails(guarded),
|
|
621
|
+
loaded: tools,
|
|
622
|
+
...(unavailable.length ? { unavailable } : {}),
|
|
623
|
+
},
|
|
624
|
+
tools,
|
|
625
|
+
};
|
|
546
626
|
}
|
|
547
627
|
const searchDefinition = {
|
|
548
|
-
name: "mcp_search",
|
|
628
|
+
name: "mcp_search",
|
|
629
|
+
label: "MCP Search",
|
|
549
630
|
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.",
|
|
550
631
|
parameters: Type.Object({
|
|
551
632
|
query: Type.Optional(Type.String()),
|
|
552
|
-
enable: Type.Optional(Type.Array(Type.Union([Type.Literal("gateway"), Type.Literal("script")]), {
|
|
633
|
+
enable: Type.Optional(Type.Array(Type.Union([Type.Literal("gateway"), Type.Literal("script")]), {
|
|
634
|
+
minItems: 1,
|
|
635
|
+
uniqueItems: true,
|
|
636
|
+
})),
|
|
553
637
|
server: Type.Optional(Type.String()),
|
|
554
|
-
limit: Type.Optional(Type.Integer({
|
|
638
|
+
limit: Type.Optional(Type.Integer({
|
|
639
|
+
minimum: 1,
|
|
640
|
+
maximum: MAX_PAGE_SIZE,
|
|
641
|
+
description: "Tools to load (default 5).",
|
|
642
|
+
})),
|
|
555
643
|
offset: Type.Optional(Type.Integer({ minimum: 0 })),
|
|
556
|
-
}, {
|
|
644
|
+
}, {
|
|
645
|
+
anyOf: [
|
|
646
|
+
{ type: "object", required: ["query"] },
|
|
647
|
+
{ type: "object", required: ["enable"] },
|
|
648
|
+
],
|
|
649
|
+
}),
|
|
557
650
|
renderResult: renderMcpToolResult,
|
|
558
651
|
async execute(toolCallId, params, signal, _onUpdate, ctx) {
|
|
559
652
|
if (beforeExecute) {
|
|
560
|
-
if (currentOwner)
|
|
653
|
+
if (currentOwner) {
|
|
561
654
|
await currentOwner.runCallback("beforeExecute", () => beforeExecute(toolCallId, ctx));
|
|
562
|
-
|
|
655
|
+
}
|
|
656
|
+
else {
|
|
563
657
|
await beforeExecute(toolCallId, ctx);
|
|
658
|
+
}
|
|
564
659
|
}
|
|
565
660
|
return searchAndLoad(params, signal, ctx);
|
|
566
661
|
},
|
|
@@ -568,8 +663,9 @@ function installMcpAdapter(pi, options) {
|
|
|
568
663
|
pi.registerTool(searchDefinition);
|
|
569
664
|
let scriptToolRegistered = false;
|
|
570
665
|
function registerScriptTool() {
|
|
571
|
-
if (scriptToolRegistered)
|
|
666
|
+
if (scriptToolRegistered) {
|
|
572
667
|
return;
|
|
668
|
+
}
|
|
573
669
|
toolLoader.registerFeature("script", {
|
|
574
670
|
...(beforeExecute ? { executionMode: "sequential" } : {}),
|
|
575
671
|
name: "mcp_script",
|
|
@@ -577,18 +673,26 @@ function installMcpAdapter(pi, options) {
|
|
|
577
673
|
description: "Compose MCP calls with trusted JavaScript: await tools.search({query, server?}), tools.describe({path}), tools.call(path,args). Describe returns complete JSON schemas. Calls return {ok,data} with raw MCP results, or {ok:false,error,data?}. Resources: tools.resources({server}), tools.readResource({server,uri}). Saved results: tools.readResult({ref,path?,fields?,offset?,limit?}); never repeats a remote call. Use emit(value) to return selected data or content blocks. No Node, filesystem, or network globals. Prefer a direct tool for one call; use scripts for loops, filtering and chains.",
|
|
578
674
|
promptSnippet: "Batch multiple MCP tool calls in one JavaScript request (loop, filter, chain)",
|
|
579
675
|
parameters: Type.Object({
|
|
580
|
-
code: Type.String({
|
|
581
|
-
|
|
676
|
+
code: Type.String({
|
|
677
|
+
description: "Trusted JavaScript MCP script. Use tools.<prefixedToolName>(args) and emit(value).",
|
|
678
|
+
}),
|
|
679
|
+
timeoutMs: Type.Optional(Type.Number({
|
|
680
|
+
minimum: 1,
|
|
681
|
+
description: options.defaultScriptTimeoutMs === null
|
|
582
682
|
? "Execution timeout in milliseconds (no default deadline)"
|
|
583
|
-
: `Execution timeout in milliseconds (default: ${options.defaultScriptTimeoutMs ?? DEFAULT_MCP_SCRIPT_TIMEOUT_MS})
|
|
683
|
+
: `Execution timeout in milliseconds (default: ${options.defaultScriptTimeoutMs ?? DEFAULT_MCP_SCRIPT_TIMEOUT_MS})`,
|
|
684
|
+
})),
|
|
584
685
|
}),
|
|
585
686
|
renderResult: renderMcpToolResult,
|
|
586
687
|
async execute(toolCallId, params, signal, _onUpdate, ctx) {
|
|
587
688
|
const ready = await getToolState(signal);
|
|
588
|
-
if ("content" in ready)
|
|
689
|
+
if ("content" in ready) {
|
|
589
690
|
return ready;
|
|
691
|
+
}
|
|
590
692
|
const { runMcpScript } = await import("./mcp-code.js");
|
|
591
|
-
return runMcpScript(ready, params.code, params.timeoutMs ?? options.defaultScriptTimeoutMs, getPiTools, signal, toolCallId, beforeExecute
|
|
693
|
+
return runMcpScript(ready, params.code, params.timeoutMs ?? options.defaultScriptTimeoutMs, getPiTools, signal, toolCallId, beforeExecute
|
|
694
|
+
? (callSignal, operation) => beforeExecute(toolCallId, { ...ctx, signal: callSignal }, operation)
|
|
695
|
+
: undefined);
|
|
592
696
|
},
|
|
593
697
|
});
|
|
594
698
|
scriptToolRegistered = true;
|
|
@@ -596,7 +700,9 @@ function installMcpAdapter(pi, options) {
|
|
|
596
700
|
function registerProxyTool(description) {
|
|
597
701
|
toolLoader.registerFeature("gateway", {
|
|
598
702
|
...(beforeExecute ? { executionMode: "sequential" } : {}),
|
|
599
|
-
name: "mcp",
|
|
703
|
+
name: "mcp",
|
|
704
|
+
label: "MCP",
|
|
705
|
+
description,
|
|
600
706
|
promptSnippet: "MCP server operations, resources, saved result readback, and fallback tool calls",
|
|
601
707
|
renderCall: renderMcpProxyToolCall,
|
|
602
708
|
parameters: gatewayParameters,
|
|
@@ -605,51 +711,78 @@ function installMcpAdapter(pi, options) {
|
|
|
605
711
|
async execute(toolCallId, rawParams, signal, _onUpdate, ctx) {
|
|
606
712
|
const params = prepareGatewayArguments(rawParams);
|
|
607
713
|
if (beforeExecute && params.action !== "call" && params.action !== "read-resource") {
|
|
608
|
-
if (currentOwner)
|
|
714
|
+
if (currentOwner) {
|
|
609
715
|
await currentOwner.runCallback("beforeExecute", () => beforeExecute(toolCallId, ctx));
|
|
610
|
-
|
|
716
|
+
}
|
|
717
|
+
else {
|
|
611
718
|
await beforeExecute(toolCallId, ctx);
|
|
719
|
+
}
|
|
612
720
|
}
|
|
613
721
|
const ready = await getToolState(signal);
|
|
614
|
-
if ("content" in ready)
|
|
722
|
+
if ("content" in ready) {
|
|
615
723
|
return ready;
|
|
724
|
+
}
|
|
616
725
|
const proxy = await import("./proxy-modes.js");
|
|
617
726
|
const present = async (result) => {
|
|
618
727
|
const guarded = await guardMcpOutput(result.content, resolveMcpOutputGuardOptions(ready.config.settings, ready.outputDirectory));
|
|
619
|
-
return {
|
|
728
|
+
return {
|
|
729
|
+
content: guarded.content,
|
|
730
|
+
details: { ...result.details, ...guardedMcpDetails(guarded) },
|
|
731
|
+
};
|
|
620
732
|
};
|
|
621
733
|
const beforeDispatch = beforeExecute
|
|
622
734
|
? (callSignal, operation) => beforeExecute(toolCallId, { ...ctx, signal: callSignal }, operation)
|
|
623
735
|
: undefined;
|
|
624
|
-
if (params.server &&
|
|
736
|
+
if (params.server &&
|
|
737
|
+
["list", "search", "describe", "instructions"].includes(params.action) &&
|
|
738
|
+
!ready.toolMetadata.has(params.server)) {
|
|
625
739
|
const discovery = await proxy.executeConnect(ready, params.server, signal);
|
|
626
|
-
if (discovery.details.error)
|
|
740
|
+
if (discovery.details.error) {
|
|
627
741
|
return discovery;
|
|
742
|
+
}
|
|
628
743
|
syncToolSurface(ctx);
|
|
629
744
|
}
|
|
630
745
|
switch (params.action) {
|
|
631
|
-
case "ui-messages":
|
|
632
|
-
|
|
746
|
+
case "ui-messages":
|
|
747
|
+
return proxy.executeUiMessages(ready);
|
|
748
|
+
case "auth-start":
|
|
749
|
+
return proxy.executeAuthStart(ready, params.server, signal);
|
|
633
750
|
case "auth-complete": {
|
|
634
751
|
const input = params.args?.redirectUrl ?? params.args?.code ?? params.args?.input;
|
|
635
|
-
if (input !== undefined && (typeof input !== "string" || input.trim().length === 0))
|
|
752
|
+
if (input !== undefined && (typeof input !== "string" || input.trim().length === 0)) {
|
|
636
753
|
throw new Error("auth-complete requires a non-empty redirectUrl, code, or input");
|
|
754
|
+
}
|
|
637
755
|
return proxy.executeAuthComplete(ready, params.server, input, signal);
|
|
638
756
|
}
|
|
639
|
-
case "call":
|
|
757
|
+
case "call":
|
|
758
|
+
return proxy.executeCall(ready, params.tool, params.args, params.server, getPiTools, signal, { toolCallId }, beforeDispatch);
|
|
640
759
|
case "connect": {
|
|
641
760
|
const result = await proxy.executeConnect(ready, params.server, signal, params.limit, params.offset);
|
|
642
761
|
syncToolSurface(ctx);
|
|
643
762
|
return present(result);
|
|
644
763
|
}
|
|
645
|
-
case "describe":
|
|
646
|
-
|
|
647
|
-
case "
|
|
648
|
-
|
|
649
|
-
case "
|
|
650
|
-
|
|
651
|
-
case "
|
|
652
|
-
|
|
764
|
+
case "describe":
|
|
765
|
+
return present(proxy.executeDescribe(ready, params.tool, params.server));
|
|
766
|
+
case "instructions":
|
|
767
|
+
return present(proxy.executeInstructions(ready, params.server));
|
|
768
|
+
case "search":
|
|
769
|
+
return present(proxy.executeSearch(ready, params.query, params.server, params.includeSchemas, params.limit, params.offset));
|
|
770
|
+
case "list":
|
|
771
|
+
return present(proxy.executeList(ready, params.server, params.limit, params.offset));
|
|
772
|
+
case "resources":
|
|
773
|
+
return present(await (await import("./resource-tools.js")).executeResourceList(ready, params.server, params.limit, params.offset, signal));
|
|
774
|
+
case "read-resource":
|
|
775
|
+
return (await import("./resource-tools.js")).executeResourceRead(ready, params.server, params.uri, signal, { toolCallId }, beforeDispatch);
|
|
776
|
+
case "read-result":
|
|
777
|
+
return readMcpResult({
|
|
778
|
+
ref: params.ref,
|
|
779
|
+
...(params.path !== undefined ? { path: params.path } : {}),
|
|
780
|
+
...(params.fields ? { fields: params.fields } : {}),
|
|
781
|
+
...(params.offset !== undefined ? { offset: params.offset } : {}),
|
|
782
|
+
...(params.limit !== undefined ? { limit: params.limit } : {}),
|
|
783
|
+
}, resolveMcpOutputGuardOptions(ready.config.settings, ready.outputDirectory));
|
|
784
|
+
case "status":
|
|
785
|
+
return present(proxy.executeStatus(ready));
|
|
653
786
|
}
|
|
654
787
|
},
|
|
655
788
|
});
|
|
@@ -658,24 +791,30 @@ function installMcpAdapter(pi, options) {
|
|
|
658
791
|
}
|
|
659
792
|
function syncGateways(config, cache, directSpecs) {
|
|
660
793
|
const policy = {};
|
|
661
|
-
if (config.settings?.scriptMode !== false)
|
|
794
|
+
if (config.settings?.scriptMode !== false) {
|
|
662
795
|
policy.script = {};
|
|
796
|
+
}
|
|
663
797
|
const missingConfiguredDirectToolServers = getMissingConfiguredDirectToolServers(config, cache, envRaw === undefined || envRaw === "__none__" ? undefined : envDirectToolOverride);
|
|
664
|
-
const hasPinnedResources = envRaw !== "__none__" &&
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
798
|
+
const hasPinnedResources = envRaw !== "__none__" &&
|
|
799
|
+
Object.entries(config.mcpServers).some(([server, definition]) => {
|
|
800
|
+
if (definition.disabled === true) {
|
|
801
|
+
return false;
|
|
802
|
+
}
|
|
803
|
+
const selection = directToolSelection(config, server, envDirectToolOverride);
|
|
804
|
+
if (!selection) {
|
|
805
|
+
return false;
|
|
806
|
+
}
|
|
807
|
+
const entry = cache?.servers[server];
|
|
808
|
+
const metadata = state?.toolMetadata.get(server) ??
|
|
809
|
+
(entry && isServerCacheValid(entry, definition)
|
|
810
|
+
? reconstructToolMetadata(server, entry, config.settings?.toolPrefix ?? "server", definition)
|
|
811
|
+
: []);
|
|
812
|
+
return metadata.some((tool) => tool.resourceUri && (selection === true || selection.includes(tool.originalName)));
|
|
813
|
+
});
|
|
814
|
+
const shouldRegisterProxyTool = config.settings?.disableProxyTool !== true ||
|
|
815
|
+
hasPinnedResources ||
|
|
816
|
+
directSpecs.length === 0 ||
|
|
817
|
+
missingConfiguredDirectToolServers.length > 0;
|
|
679
818
|
if (shouldRegisterProxyTool) {
|
|
680
819
|
const description = buildProxyDescription(config);
|
|
681
820
|
if (!proxyToolRegistered || proxyToolDescription !== description) {
|
|
@@ -683,8 +822,9 @@ function installMcpAdapter(pi, options) {
|
|
|
683
822
|
}
|
|
684
823
|
policy.gateway = { eager: hasPinnedResources };
|
|
685
824
|
}
|
|
686
|
-
if (policy.script)
|
|
825
|
+
if (policy.script) {
|
|
687
826
|
registerScriptTool();
|
|
827
|
+
}
|
|
688
828
|
return policy;
|
|
689
829
|
}
|
|
690
830
|
// A transform needs the session context before any configured tool surface is registered.
|
|
@@ -694,8 +834,11 @@ function installMcpAdapter(pi, options) {
|
|
|
694
834
|
}
|
|
695
835
|
export function createMcpAdapter(options = {}) {
|
|
696
836
|
const { defaultScriptTimeoutMs } = options;
|
|
697
|
-
if (defaultScriptTimeoutMs !== undefined &&
|
|
698
|
-
|
|
837
|
+
if (defaultScriptTimeoutMs !== undefined &&
|
|
838
|
+
defaultScriptTimeoutMs !== null &&
|
|
839
|
+
(!Number.isInteger(defaultScriptTimeoutMs) ||
|
|
840
|
+
defaultScriptTimeoutMs < 1 ||
|
|
841
|
+
defaultScriptTimeoutMs > 2_147_483_647)) {
|
|
699
842
|
throw new RangeError("defaultScriptTimeoutMs must be an integer from 1 to 2147483647, or null");
|
|
700
843
|
}
|
|
701
844
|
const factoryConfig = options.config !== undefined ? cloneMcpConfig(options.config) : undefined;
|
|
@@ -703,7 +846,9 @@ export function createMcpAdapter(options = {}) {
|
|
|
703
846
|
installMcpAdapter(pi, {
|
|
704
847
|
...(options.configPath !== undefined ? { configPath: options.configPath } : {}),
|
|
705
848
|
...(defaultScriptTimeoutMs !== undefined ? { defaultScriptTimeoutMs } : {}),
|
|
706
|
-
...(options.outputDirectory !== undefined
|
|
849
|
+
...(options.outputDirectory !== undefined
|
|
850
|
+
? { outputDirectory: options.outputDirectory }
|
|
851
|
+
: {}),
|
|
707
852
|
...(factoryConfig !== undefined ? { config: cloneMcpConfig(factoryConfig) } : {}),
|
|
708
853
|
...(options.beforeExecute ? { beforeExecute: options.beforeExecute } : {}),
|
|
709
854
|
...(options.transformConfig ? { transformConfig: options.transformConfig } : {}),
|