@bastani/atomic 0.9.25-alpha.2 → 0.9.25-alpha.3
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 +27 -0
- package/dist/builtin/intercom/package.json +2 -2
- package/dist/builtin/mcp/CHANGELOG.md +13 -0
- package/dist/builtin/mcp/index.bundle.mjs +489 -208
- package/dist/builtin/mcp/package.json +2 -2
- package/dist/builtin/subagents/package.json +3 -3
- package/dist/builtin/web-access/package.json +2 -2
- package/dist/builtin/workflows/CHANGELOG.md +12 -0
- package/dist/builtin/workflows/builtin/{chunk-e1254zvd.js → chunk-kfsnh3w7.js} +40 -12
- package/dist/builtin/workflows/builtin/{chunk-cpw5gtzg.js → chunk-rqmasd3d.js} +1 -1
- package/dist/builtin/workflows/builtin/{chunk-qy6g0baf.js → chunk-wz783pvd.js} +1 -1
- package/dist/builtin/workflows/builtin/goal.js +2 -2
- package/dist/builtin/workflows/builtin/index.js +3 -3
- package/dist/builtin/workflows/builtin/ralph.js +2 -2
- package/dist/builtin/workflows/package.json +2 -2
- package/dist/builtin/workflows/src/extension/index.bundle.mjs +472 -88
- package/dist/builtin/workflows/src/index.js +65 -28
- package/dist/core/agent-session-accessors.d.ts.map +1 -1
- package/dist/core/agent-session-accessors.js +7 -0
- package/dist/core/agent-session-accessors.js.map +1 -1
- package/dist/core/agent-session-extension-bindings.d.ts.map +1 -1
- package/dist/core/agent-session-extension-bindings.js +16 -2
- package/dist/core/agent-session-extension-bindings.js.map +1 -1
- package/dist/core/agent-session-methods.d.ts +7 -1
- package/dist/core/agent-session-methods.d.ts.map +1 -1
- package/dist/core/agent-session-methods.js.map +1 -1
- package/dist/core/agent-session-state.d.ts.map +1 -1
- package/dist/core/agent-session-state.js +3 -2
- package/dist/core/agent-session-state.js.map +1 -1
- package/dist/core/agent-session-types.d.ts +1 -0
- package/dist/core/agent-session-types.d.ts.map +1 -1
- package/dist/core/agent-session-types.js.map +1 -1
- package/dist/core/agent-session.d.ts +3 -0
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +6 -0
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/extensions/api-types.d.ts +3 -0
- package/dist/core/extensions/api-types.d.ts.map +1 -1
- package/dist/core/extensions/api-types.js.map +1 -1
- package/dist/core/extensions/index.d.ts +2 -0
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/index.js +1 -0
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/loader-api.d.ts.map +1 -1
- package/dist/core/extensions/loader-api.js +11 -0
- package/dist/core/extensions/loader-api.js.map +1 -1
- package/dist/core/extensions/loader-runtime.d.ts.map +1 -1
- package/dist/core/extensions/loader-runtime.js +3 -0
- package/dist/core/extensions/loader-runtime.js.map +1 -1
- package/dist/core/extensions/mcp-server-registry.d.ts.map +1 -1
- package/dist/core/extensions/mcp-server-registry.js +4 -0
- package/dist/core/extensions/mcp-server-registry.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +3 -0
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +4 -0
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/runtime-types.d.ts +3 -0
- package/dist/core/extensions/runtime-types.d.ts.map +1 -1
- package/dist/core/extensions/runtime-types.js.map +1 -1
- package/dist/core/extensions/tool-types.d.ts +1 -0
- package/dist/core/extensions/tool-types.d.ts.map +1 -1
- package/dist/core/extensions/tool-types.js.map +1 -1
- package/dist/core/extensions/workflow-run-control-hub.d.ts +23 -0
- package/dist/core/extensions/workflow-run-control-hub.d.ts.map +1 -0
- package/dist/core/extensions/workflow-run-control-hub.js +57 -0
- package/dist/core/extensions/workflow-run-control-hub.js.map +1 -0
- package/dist/core/extensions/workflow-run-control.d.ts +163 -0
- package/dist/core/extensions/workflow-run-control.d.ts.map +1 -0
- package/dist/core/extensions/workflow-run-control.js +73 -0
- package/dist/core/extensions/workflow-run-control.js.map +1 -0
- package/dist/core/mcp-servers.d.ts +4 -1
- package/dist/core/mcp-servers.d.ts.map +1 -1
- package/dist/core/mcp-servers.js.map +1 -1
- package/dist/core/remote-catalog-provider.d.ts.map +1 -1
- package/dist/core/remote-catalog-provider.js +4 -9
- package/dist/core/remote-catalog-provider.js.map +1 -1
- package/dist/core/sdk.js +1 -0
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/tool-loadout.d.ts +1 -0
- package/dist/core/tool-loadout.d.ts.map +1 -1
- package/dist/core/tool-loadout.js +3 -0
- package/dist/core/tool-loadout.js.map +1 -1
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +11 -30
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/extensions/codemode/execute.d.ts.map +1 -1
- package/dist/extensions/codemode/execute.js +26 -0
- package/dist/extensions/codemode/execute.js.map +1 -1
- package/dist/extensions/codemode/renderer.d.ts.map +1 -1
- package/dist/extensions/codemode/renderer.js +38 -23
- package/dist/extensions/codemode/renderer.js.map +1 -1
- package/dist/extensions/codemode/tool.d.ts.map +1 -1
- package/dist/extensions/codemode/tool.js +22 -10
- package/dist/extensions/codemode/tool.js.map +1 -1
- package/dist/extensions/tool-search/tool.d.ts +1 -1
- package/dist/extensions/tool-search/tool.d.ts.map +1 -1
- package/dist/extensions/tool-search/tool.js +3 -13
- package/dist/extensions/tool-search/tool.js.map +1 -1
- package/dist/index-extensions.d.ts +2 -1
- package/dist/index-extensions.d.ts.map +1 -1
- package/dist/index-extensions.js +1 -1
- package/dist/index-extensions.js.map +1 -1
- package/dist/modes/interactive/components/visual-truncate.d.ts +27 -3
- package/dist/modes/interactive/components/visual-truncate.d.ts.map +1 -1
- package/dist/modes/interactive/components/visual-truncate.js +39 -6
- package/dist/modes/interactive/components/visual-truncate.js.map +1 -1
- package/docs/extensions/events.md +2 -0
- package/docs/mcp-servers.md +47 -0
- package/docs/providers.md +8 -0
- package/docs/sdk/reference.md +16 -0
- package/docs/sdk.md +67 -1
- package/docs/settings.md +2 -0
- package/docs/tools.md +6 -0
- package/docs/workflows/operations.md +3 -1
- package/examples/extensions/built-in-tool-renderer.ts +16 -40
- package/examples/extensions/minimal-mode.ts +28 -108
- package/npm-shrinkwrap.json +69 -69
- package/package.json +8 -8
|
@@ -210,6 +210,90 @@ var init_state_lease = __esm(() => {
|
|
|
210
210
|
};
|
|
211
211
|
});
|
|
212
212
|
|
|
213
|
+
// dist/builtin/mcp/authorization-notice.ts
|
|
214
|
+
import { hyperlink } from "@earendil-works/pi-tui";
|
|
215
|
+
function authorizationNotice(url) {
|
|
216
|
+
const clickHint = process.platform === "darwin" ? "Cmd+click to open" : "Ctrl+click to open";
|
|
217
|
+
return `Approve access in your browser. If it did not open, visit:
|
|
218
|
+
${hyperlink(url, url)}
|
|
219
|
+
${hyperlink(clickHint, url)}`;
|
|
220
|
+
}
|
|
221
|
+
var init_authorization_notice = () => {};
|
|
222
|
+
|
|
223
|
+
// dist/builtin/mcp/provider-auth.ts
|
|
224
|
+
function isProviderAuth(auth) {
|
|
225
|
+
return typeof auth === "object" && auth !== null && typeof auth.provider === "string";
|
|
226
|
+
}
|
|
227
|
+
function providerAuthShapeError(auth) {
|
|
228
|
+
if (typeof auth !== "object" || auth === null)
|
|
229
|
+
return;
|
|
230
|
+
const provider = auth.provider;
|
|
231
|
+
return typeof provider === "string" && provider.trim() ? undefined : "auth.provider must be a provider name";
|
|
232
|
+
}
|
|
233
|
+
function providerAuthUrlError(value) {
|
|
234
|
+
if (!value)
|
|
235
|
+
return "auth.provider requires a url";
|
|
236
|
+
try {
|
|
237
|
+
const url = new URL(value);
|
|
238
|
+
if (url.protocol === "https:" || url.protocol === "http:" && LOOPBACK_HOSTS.has(url.hostname))
|
|
239
|
+
return;
|
|
240
|
+
} catch {}
|
|
241
|
+
return URL_REQUIREMENT;
|
|
242
|
+
}
|
|
243
|
+
function providerSignInMessage(serverName, provider) {
|
|
244
|
+
return `MCP server "${serverName}" requires sign-in. Run /login ${provider} to sign in.`;
|
|
245
|
+
}
|
|
246
|
+
function providerSignInGuidance(definition, serverName) {
|
|
247
|
+
return isProviderAuth(definition?.auth) ? providerSignInMessage(serverName, definition.auth.provider) : undefined;
|
|
248
|
+
}
|
|
249
|
+
function signInRequired(serverName, provider) {
|
|
250
|
+
return new McpProviderAuthError(providerSignInMessage(serverName, provider), provider);
|
|
251
|
+
}
|
|
252
|
+
function createProviderAuthFetch(options) {
|
|
253
|
+
const { serverName, provider, token } = options;
|
|
254
|
+
const origin = new URL(options.serverUrl).origin;
|
|
255
|
+
return async (input, init) => {
|
|
256
|
+
let url = new URL(input);
|
|
257
|
+
for (let redirects = 0;; redirects++) {
|
|
258
|
+
if (url.origin !== origin) {
|
|
259
|
+
throw new McpProviderAuthError(`MCP server "${serverName}" request refused: provider credentials are only sent to the configured server origin.`);
|
|
260
|
+
}
|
|
261
|
+
const value = await token?.(provider);
|
|
262
|
+
if (!value)
|
|
263
|
+
throw signInRequired(serverName, provider);
|
|
264
|
+
const headers = new Headers(init?.headers);
|
|
265
|
+
headers.set("Authorization", `Bearer ${value}`);
|
|
266
|
+
const response = await (options.fetch ?? globalThis.fetch)(url, { ...init, headers, redirect: "manual" });
|
|
267
|
+
if (response.status === 401) {
|
|
268
|
+
await response.body?.cancel().catch(() => {});
|
|
269
|
+
throw signInRequired(serverName, provider);
|
|
270
|
+
}
|
|
271
|
+
const location = response.status >= 300 && response.status < 400 ? response.headers.get("location") : null;
|
|
272
|
+
if (!location)
|
|
273
|
+
return response;
|
|
274
|
+
await response.body?.cancel().catch(() => {});
|
|
275
|
+
const target = new URL(location, url);
|
|
276
|
+
const samePreservingRedirect = response.status === 307 || response.status === 308;
|
|
277
|
+
if (!samePreservingRedirect || target.origin !== origin || redirects >= MAX_SAME_ORIGIN_REDIRECTS) {
|
|
278
|
+
throw new McpProviderAuthError(`MCP server "${serverName}" redirected the request; provider credentials are not sent across redirects.`);
|
|
279
|
+
}
|
|
280
|
+
url = target;
|
|
281
|
+
}
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
var LOOPBACK_HOSTS, MAX_SAME_ORIGIN_REDIRECTS = 3, URL_REQUIREMENT = "auth.provider requires an https URL, or http on localhost, 127.0.0.1, or [::1]", McpProviderAuthError;
|
|
285
|
+
var init_provider_auth = __esm(() => {
|
|
286
|
+
LOOPBACK_HOSTS = new Set(["localhost", "127.0.0.1", "[::1]"]);
|
|
287
|
+
McpProviderAuthError = class McpProviderAuthError extends Error {
|
|
288
|
+
provider;
|
|
289
|
+
constructor(message, provider) {
|
|
290
|
+
super(message);
|
|
291
|
+
this.provider = provider;
|
|
292
|
+
this.name = "McpProviderAuthError";
|
|
293
|
+
}
|
|
294
|
+
};
|
|
295
|
+
});
|
|
296
|
+
|
|
213
297
|
// dist/builtin/mcp/agent-dir.ts
|
|
214
298
|
import { homedir } from "node:os";
|
|
215
299
|
import { join, resolve } from "node:path";
|
|
@@ -6453,10 +6537,141 @@ var init_tool_call_timeout = __esm(() => {
|
|
|
6453
6537
|
};
|
|
6454
6538
|
});
|
|
6455
6539
|
|
|
6540
|
+
// dist/builtin/mcp/utils.ts
|
|
6541
|
+
var exports_utils = {};
|
|
6542
|
+
__export(exports_utils, {
|
|
6543
|
+
extractToolUiStreamMode: () => extractToolUiStreamMode,
|
|
6544
|
+
formatAuthRequiredMessage: () => formatAuthRequiredMessage,
|
|
6545
|
+
getConfigPathFromArgv: () => getConfigPathFromArgv,
|
|
6546
|
+
interpolateEnvRecord: () => interpolateEnvRecord,
|
|
6547
|
+
interpolateEnvVars: () => interpolateEnvVars,
|
|
6548
|
+
openPath: () => openPath,
|
|
6549
|
+
openUrl: () => openUrl,
|
|
6550
|
+
parallelLimit: () => parallelLimit,
|
|
6551
|
+
resolveBearerToken: () => resolveBearerToken,
|
|
6552
|
+
resolveConfigPath: () => resolveConfigPath,
|
|
6553
|
+
resolveServerUrl: () => resolveServerUrl,
|
|
6554
|
+
truncateAtWord: () => truncateAtWord,
|
|
6555
|
+
unflattenToolArguments: () => unflattenToolArguments
|
|
6556
|
+
});
|
|
6557
|
+
import { unflattenArgumentsWithSchema } from "@bastani/atomic";
|
|
6558
|
+
import { homedir as homedir2, platform } from "node:os";
|
|
6559
|
+
import { join as join2 } from "node:path";
|
|
6560
|
+
async function execOpen(pi, target, browser) {
|
|
6561
|
+
const os = platform();
|
|
6562
|
+
if (os === "darwin") {
|
|
6563
|
+
return browser ? pi.exec("open", ["-a", browser, target]) : pi.exec("open", [target]);
|
|
6564
|
+
}
|
|
6565
|
+
if (os === "win32") {
|
|
6566
|
+
return browser ? pi.exec("cmd", ["/c", "start", "", browser, target]) : pi.exec("cmd", ["/c", "start", "", target]);
|
|
6567
|
+
}
|
|
6568
|
+
return browser ? pi.exec(browser, [target]) : pi.exec("xdg-open", [target]);
|
|
6569
|
+
}
|
|
6570
|
+
async function openUrl(pi, url, browser) {
|
|
6571
|
+
const result = await execOpen(pi, url, browser);
|
|
6572
|
+
if (result.code !== 0) {
|
|
6573
|
+
throw new Error(result.stderr || `Failed to open browser (exit code ${result.code})`);
|
|
6574
|
+
}
|
|
6575
|
+
}
|
|
6576
|
+
async function openPath(pi, targetPath) {
|
|
6577
|
+
const result = await execOpen(pi, targetPath);
|
|
6578
|
+
if (result.code !== 0) {
|
|
6579
|
+
throw new Error(result.stderr || `Failed to open path (exit code ${result.code})`);
|
|
6580
|
+
}
|
|
6581
|
+
}
|
|
6582
|
+
async function parallelLimit(items, limit, fn) {
|
|
6583
|
+
const results = [];
|
|
6584
|
+
let index = 0;
|
|
6585
|
+
async function worker() {
|
|
6586
|
+
while (index < items.length) {
|
|
6587
|
+
const i = index++;
|
|
6588
|
+
results[i] = await fn(items[i]);
|
|
6589
|
+
}
|
|
6590
|
+
}
|
|
6591
|
+
const workers = Array(Math.min(limit, items.length)).fill(null).map(() => worker());
|
|
6592
|
+
await Promise.all(workers);
|
|
6593
|
+
return results;
|
|
6594
|
+
}
|
|
6595
|
+
function getConfigPathFromArgv() {
|
|
6596
|
+
const idx = process.argv.indexOf("--mcp-config");
|
|
6597
|
+
if (idx >= 0 && idx + 1 < process.argv.length) {
|
|
6598
|
+
return process.argv[idx + 1];
|
|
6599
|
+
}
|
|
6600
|
+
return;
|
|
6601
|
+
}
|
|
6602
|
+
function interpolateEnvVars(value) {
|
|
6603
|
+
return value.replace(/\$\{(\w+)\}/g, (_, name) => process.env[name] ?? "").replace(/\$env:(\w+)/g, (_, name) => process.env[name] ?? "");
|
|
6604
|
+
}
|
|
6605
|
+
function resolveServerUrl(value) {
|
|
6606
|
+
const resolved = interpolateEnvVars(value);
|
|
6607
|
+
try {
|
|
6608
|
+
const url = new URL(resolved);
|
|
6609
|
+
if (url.protocol === "http:" || url.protocol === "https:")
|
|
6610
|
+
return resolved;
|
|
6611
|
+
} catch {}
|
|
6612
|
+
throw new Error("Invalid MCP server url: expected a non-empty HTTP(S) URL after environment variable interpolation.");
|
|
6613
|
+
}
|
|
6614
|
+
function interpolateEnvRecord(values) {
|
|
6615
|
+
if (!values)
|
|
6616
|
+
return;
|
|
6617
|
+
const resolved = {};
|
|
6618
|
+
for (const [key, value] of Object.entries(values)) {
|
|
6619
|
+
resolved[key] = interpolateEnvVars(value);
|
|
6620
|
+
}
|
|
6621
|
+
return resolved;
|
|
6622
|
+
}
|
|
6623
|
+
function resolveConfigPath(value) {
|
|
6624
|
+
if (value === undefined)
|
|
6625
|
+
return;
|
|
6626
|
+
const resolved = interpolateEnvVars(value);
|
|
6627
|
+
if (resolved === "~")
|
|
6628
|
+
return homedir2();
|
|
6629
|
+
if (resolved.startsWith("~/") || resolved.startsWith("~\\")) {
|
|
6630
|
+
return join2(homedir2(), resolved.slice(2));
|
|
6631
|
+
}
|
|
6632
|
+
return resolved;
|
|
6633
|
+
}
|
|
6634
|
+
function resolveBearerToken(definition) {
|
|
6635
|
+
if (definition.bearerToken !== undefined) {
|
|
6636
|
+
return interpolateEnvVars(definition.bearerToken);
|
|
6637
|
+
}
|
|
6638
|
+
return definition.bearerTokenEnv ? process.env[definition.bearerTokenEnv] : undefined;
|
|
6639
|
+
}
|
|
6640
|
+
function truncateAtWord(text, target) {
|
|
6641
|
+
if (!text || text.length <= target)
|
|
6642
|
+
return text;
|
|
6643
|
+
const truncated = text.slice(0, target);
|
|
6644
|
+
const lastSpace = truncated.lastIndexOf(" ");
|
|
6645
|
+
if (lastSpace > target * 0.6) {
|
|
6646
|
+
return truncated.slice(0, lastSpace) + "...";
|
|
6647
|
+
}
|
|
6648
|
+
return truncated + "...";
|
|
6649
|
+
}
|
|
6650
|
+
function formatAuthRequiredMessage(config, serverName, defaultMessage) {
|
|
6651
|
+
const template = config.settings?.authRequiredMessage;
|
|
6652
|
+
return template ? template.replaceAll("${server}", serverName) : defaultMessage;
|
|
6653
|
+
}
|
|
6654
|
+
function extractToolUiStreamMode(toolMeta) {
|
|
6655
|
+
const uiMeta = toolMeta?.ui;
|
|
6656
|
+
if (!uiMeta || typeof uiMeta !== "object")
|
|
6657
|
+
return;
|
|
6658
|
+
const streamMode = uiMeta["pi-mcp-adapter.streamMode"];
|
|
6659
|
+
if (streamMode === "eager" || streamMode === "stream-first") {
|
|
6660
|
+
return streamMode;
|
|
6661
|
+
}
|
|
6662
|
+
return;
|
|
6663
|
+
}
|
|
6664
|
+
function unflattenToolArguments(args, inputSchema) {
|
|
6665
|
+
if (args === null || args === undefined)
|
|
6666
|
+
return {};
|
|
6667
|
+
return unflattenArgumentsWithSchema(args, inputSchema);
|
|
6668
|
+
}
|
|
6669
|
+
var init_utils = () => {};
|
|
6670
|
+
|
|
6456
6671
|
// dist/builtin/mcp/config.ts
|
|
6457
6672
|
import { existsSync as existsSync2, readFileSync as readFileSync2 } from "node:fs";
|
|
6458
|
-
import { homedir as
|
|
6459
|
-
import { dirname as dirname2, join as
|
|
6673
|
+
import { homedir as homedir3 } from "node:os";
|
|
6674
|
+
import { dirname as dirname2, join as join3, resolve as resolve2 } from "node:path";
|
|
6460
6675
|
import { CONFIG_DIR_NAME as CONFIG_DIR_NAME2, getProjectConfigPaths } from "@bastani/atomic";
|
|
6461
6676
|
function getPiGlobalConfigPath(overridePath) {
|
|
6462
6677
|
return overridePath ? resolve2(overridePath) : getAgentPath("mcp.json");
|
|
@@ -6472,7 +6687,7 @@ function getProjectPiConfigPaths(cwd = process.cwd()) {
|
|
|
6472
6687
|
}
|
|
6473
6688
|
function getMcpDiscoverySummary(overridePath, cwd = process.cwd()) {
|
|
6474
6689
|
const sources = getConfigSources(overridePath, cwd).map((source) => {
|
|
6475
|
-
const loaded = readValidatedConfig(source.readPath, `MCP config from ${source.readPath}
|
|
6690
|
+
const loaded = readValidatedConfig(source.readPath, `MCP config from ${source.readPath}`, source.scope === "global");
|
|
6476
6691
|
return {
|
|
6477
6692
|
id: source.id,
|
|
6478
6693
|
label: source.label,
|
|
@@ -6520,10 +6735,10 @@ function getMcpDiscoverySummary(overridePath, cwd = process.cwd()) {
|
|
|
6520
6735
|
function loadMcpConfig(overridePath, cwd = process.cwd(), contributions = []) {
|
|
6521
6736
|
let config = { mcpServers: validateContributedServers(contributions) };
|
|
6522
6737
|
for (const source of getConfigSources(overridePath, cwd)) {
|
|
6523
|
-
const loaded = readValidatedConfig(source.readPath, `MCP config from ${source.readPath}
|
|
6738
|
+
const loaded = readValidatedConfig(source.readPath, `MCP config from ${source.readPath}`, source.scope === "global");
|
|
6524
6739
|
if (!loaded)
|
|
6525
6740
|
continue;
|
|
6526
|
-
config = mergeConfigs(config, expandImports(loaded, cwd));
|
|
6741
|
+
config = mergeConfigs(config, expandImports(loaded, cwd, source.scope === "global"));
|
|
6527
6742
|
}
|
|
6528
6743
|
return withoutDisabledServers(config);
|
|
6529
6744
|
}
|
|
@@ -6547,7 +6762,7 @@ function validateContributedServers(contributions) {
|
|
|
6547
6762
|
const servers = {};
|
|
6548
6763
|
for (const contribution of contributions) {
|
|
6549
6764
|
try {
|
|
6550
|
-
Object.assign(servers,
|
|
6765
|
+
Object.assign(servers, validateServerEntries({ [contribution.name]: contribution.config }, contribution.origin === "extension", describeMcpContributionSource(contribution)));
|
|
6551
6766
|
} catch (error) {
|
|
6552
6767
|
const reason = error instanceof Error ? error.message : String(error);
|
|
6553
6768
|
const message = `Ignoring MCP server "${contribution.name}" from ${describeMcpContributionSource(contribution)}: ${reason}`;
|
|
@@ -6555,7 +6770,7 @@ function validateContributedServers(contributions) {
|
|
|
6555
6770
|
console.warn(message);
|
|
6556
6771
|
}
|
|
6557
6772
|
}
|
|
6558
|
-
return servers;
|
|
6773
|
+
return validateServerEntries(servers, true);
|
|
6559
6774
|
}
|
|
6560
6775
|
function withoutDisabledServers(config) {
|
|
6561
6776
|
const enabled = Object.entries(config.mcpServers).filter(([, entry]) => entry.disabled !== true);
|
|
@@ -6619,8 +6834,16 @@ function getConfigSources(overridePath, cwd = process.cwd()) {
|
|
|
6619
6834
|
return sources;
|
|
6620
6835
|
}
|
|
6621
6836
|
function mergeConfigs(base, next) {
|
|
6837
|
+
const servers = { ...base.mcpServers };
|
|
6838
|
+
for (const [name, entry] of Object.entries(next.mcpServers)) {
|
|
6839
|
+
for (const previous of Object.keys(servers)) {
|
|
6840
|
+
if (previous !== name && previous.replace(/-/g, "_") === name.replace(/-/g, "_"))
|
|
6841
|
+
delete servers[previous];
|
|
6842
|
+
}
|
|
6843
|
+
servers[name] = entry;
|
|
6844
|
+
}
|
|
6622
6845
|
return {
|
|
6623
|
-
mcpServers:
|
|
6846
|
+
mcpServers: servers,
|
|
6624
6847
|
imports: mergeImports(base.imports, next.imports),
|
|
6625
6848
|
settings: next.settings ? { ...base.settings, ...next.settings } : base.settings
|
|
6626
6849
|
};
|
|
@@ -6631,7 +6854,7 @@ function mergeImports(left, right) {
|
|
|
6631
6854
|
return;
|
|
6632
6855
|
return [...new Set(merged)];
|
|
6633
6856
|
}
|
|
6634
|
-
function expandImports(config, cwd = process.cwd()) {
|
|
6857
|
+
function expandImports(config, cwd = process.cwd(), allowProviderAuth = false) {
|
|
6635
6858
|
if (!config.imports?.length)
|
|
6636
6859
|
return config;
|
|
6637
6860
|
const importedServers = {};
|
|
@@ -6641,7 +6864,7 @@ function expandImports(config, cwd = process.cwd()) {
|
|
|
6641
6864
|
continue;
|
|
6642
6865
|
try {
|
|
6643
6866
|
const imported = JSON.parse(readFileSync2(importPath, "utf-8"));
|
|
6644
|
-
const servers = extractServers(imported, importKind);
|
|
6867
|
+
const servers = extractServers(imported, importKind, allowProviderAuth && importKind !== "vscode");
|
|
6645
6868
|
for (const [name, definition] of Object.entries(servers)) {
|
|
6646
6869
|
if (!importedServers[name]) {
|
|
6647
6870
|
importedServers[name] = definition;
|
|
@@ -6673,16 +6896,16 @@ function resolveImportPath(importKind, cwd = process.cwd()) {
|
|
|
6673
6896
|
function getImportServerCount(importKind, path) {
|
|
6674
6897
|
try {
|
|
6675
6898
|
const raw = JSON.parse(readFileSync2(path, "utf-8"));
|
|
6676
|
-
return Object.keys(extractServers(raw, importKind)).length;
|
|
6899
|
+
return Object.keys(extractServers(raw, importKind, importKind !== "vscode")).length;
|
|
6677
6900
|
} catch {
|
|
6678
6901
|
return 0;
|
|
6679
6902
|
}
|
|
6680
6903
|
}
|
|
6681
|
-
function readValidatedConfig(path, label) {
|
|
6904
|
+
function readValidatedConfig(path, label, allowProviderAuth) {
|
|
6682
6905
|
if (!existsSync2(path))
|
|
6683
6906
|
return null;
|
|
6684
6907
|
try {
|
|
6685
|
-
return validateMcpConfig(JSON.parse(readFileSync2(path, "utf-8")));
|
|
6908
|
+
return validateMcpConfig(JSON.parse(readFileSync2(path, "utf-8")), allowProviderAuth);
|
|
6686
6909
|
} catch (error) {
|
|
6687
6910
|
if (error instanceof McpTimeoutConfigError)
|
|
6688
6911
|
throw error;
|
|
@@ -6691,7 +6914,7 @@ function readValidatedConfig(path, label) {
|
|
|
6691
6914
|
return null;
|
|
6692
6915
|
}
|
|
6693
6916
|
}
|
|
6694
|
-
function validateMcpConfig(raw) {
|
|
6917
|
+
function validateMcpConfig(raw, allowProviderAuth = true) {
|
|
6695
6918
|
if (!raw || typeof raw !== "object") {
|
|
6696
6919
|
return { mcpServers: {} };
|
|
6697
6920
|
}
|
|
@@ -6701,12 +6924,47 @@ function validateMcpConfig(raw) {
|
|
|
6701
6924
|
return { mcpServers: {} };
|
|
6702
6925
|
}
|
|
6703
6926
|
return {
|
|
6704
|
-
mcpServers:
|
|
6927
|
+
mcpServers: validateServerEntries(servers, allowProviderAuth),
|
|
6705
6928
|
imports: Array.isArray(obj.imports) ? obj.imports : undefined,
|
|
6706
6929
|
settings: obj.settings
|
|
6707
6930
|
};
|
|
6708
6931
|
}
|
|
6709
|
-
function
|
|
6932
|
+
function serverEntryError(entry, allowProviderAuth) {
|
|
6933
|
+
const oauth = entry?.oauth;
|
|
6934
|
+
if (oauth && oauth.clientName !== undefined && (typeof oauth.clientName !== "string" || !oauth.clientName.trim())) {
|
|
6935
|
+
return "oauth.clientName must be a non-empty string";
|
|
6936
|
+
}
|
|
6937
|
+
const auth = entry?.auth;
|
|
6938
|
+
if (typeof auth !== "object" || auth === null)
|
|
6939
|
+
return;
|
|
6940
|
+
return providerAuthShapeError(auth) ?? (allowProviderAuth ? undefined : "auth.provider is only allowed in the global mcp.json and from extensions") ?? providerAuthUrlError(typeof entry?.url === "string" ? interpolateEnvVars(entry.url) : undefined);
|
|
6941
|
+
}
|
|
6942
|
+
function validateServerEntries(servers, allowProviderAuth, origin) {
|
|
6943
|
+
const candidates = {};
|
|
6944
|
+
for (const [name, entry] of Object.entries(servers)) {
|
|
6945
|
+
const reason = serverEntryError(entry, allowProviderAuth);
|
|
6946
|
+
if (reason) {
|
|
6947
|
+
if (!reportOwnedMcpLog("warn")) {
|
|
6948
|
+
console.warn(`Ignoring MCP server "${name}"${origin ? ` from ${origin}` : ""}: ${reason}`);
|
|
6949
|
+
}
|
|
6950
|
+
continue;
|
|
6951
|
+
}
|
|
6952
|
+
candidates[name] = entry;
|
|
6953
|
+
}
|
|
6954
|
+
const validated = validateMcpServerTimeouts(candidates);
|
|
6955
|
+
const accepted = {};
|
|
6956
|
+
for (const [name, entry] of Object.entries(validated)) {
|
|
6957
|
+
const clash = Object.keys(accepted).find((other) => other !== name && other.replace(/-/g, "_") === name.replace(/-/g, "_"));
|
|
6958
|
+
if (clash) {
|
|
6959
|
+
if (!reportOwnedMcpLog("warn"))
|
|
6960
|
+
console.warn(`MCP server "${name}" conflicts with "${clash}"`);
|
|
6961
|
+
continue;
|
|
6962
|
+
}
|
|
6963
|
+
accepted[name] = entry;
|
|
6964
|
+
}
|
|
6965
|
+
return accepted;
|
|
6966
|
+
}
|
|
6967
|
+
function extractServers(config, kind, allowProviderAuth) {
|
|
6710
6968
|
if (!config || typeof config !== "object")
|
|
6711
6969
|
return {};
|
|
6712
6970
|
const obj = config;
|
|
@@ -6727,7 +6985,7 @@ function extractServers(config, kind) {
|
|
|
6727
6985
|
if (!servers || typeof servers !== "object" || Array.isArray(servers)) {
|
|
6728
6986
|
return {};
|
|
6729
6987
|
}
|
|
6730
|
-
return
|
|
6988
|
+
return validateServerEntries(servers, allowProviderAuth);
|
|
6731
6989
|
}
|
|
6732
6990
|
function isRepoPromptServer(name, entry) {
|
|
6733
6991
|
const normalizedName = name.toLowerCase();
|
|
@@ -6743,7 +7001,7 @@ function isRepoPromptServer(name, entry) {
|
|
|
6743
7001
|
function findProjectRoot(cwd = process.cwd()) {
|
|
6744
7002
|
let current = resolve2(cwd);
|
|
6745
7003
|
while (true) {
|
|
6746
|
-
if (existsSync2(
|
|
7004
|
+
if (existsSync2(join3(current, ".git")) || existsSync2(join3(current, "package.json")) || existsSync2(join3(current, PROJECT_CONFIG_NAME)) || existsSync2(join3(current, CONFIG_DIR_NAME2))) {
|
|
6747
7005
|
return current;
|
|
6748
7006
|
}
|
|
6749
7007
|
const parent = dirname2(current);
|
|
@@ -6763,7 +7021,7 @@ function detectRepoPrompt(summary, cwd = process.cwd()) {
|
|
|
6763
7021
|
for (const source of summary.sources) {
|
|
6764
7022
|
if (source.kind !== "shared" || source.serverCount === 0)
|
|
6765
7023
|
continue;
|
|
6766
|
-
const config = readValidatedConfig(source.path, `MCP config from ${source.path}
|
|
7024
|
+
const config = readValidatedConfig(source.path, `MCP config from ${source.path}`, source.scope === "global");
|
|
6767
7025
|
if (!config)
|
|
6768
7026
|
continue;
|
|
6769
7027
|
for (const [name, entry] of Object.entries(config.mcpServers)) {
|
|
@@ -6777,7 +7035,7 @@ function detectRepoPrompt(summary, cwd = process.cwd()) {
|
|
|
6777
7035
|
return { configured: false };
|
|
6778
7036
|
}
|
|
6779
7037
|
const projectRoot = findProjectRoot(cwd);
|
|
6780
|
-
const targetPath = projectRoot ?
|
|
7038
|
+
const targetPath = projectRoot ? join3(projectRoot, PROJECT_CONFIG_NAME) : GENERIC_GLOBAL_CONFIG_PATH;
|
|
6781
7039
|
return {
|
|
6782
7040
|
configured: false,
|
|
6783
7041
|
executablePath,
|
|
@@ -6853,7 +7111,7 @@ function getServerProvenance(overridePath, cwd = process.cwd(), contributions =
|
|
|
6853
7111
|
});
|
|
6854
7112
|
}
|
|
6855
7113
|
for (const source of getConfigSources(overridePath, cwd)) {
|
|
6856
|
-
const loaded = readValidatedConfig(source.readPath, `MCP config from ${source.readPath}
|
|
7114
|
+
const loaded = readValidatedConfig(source.readPath, `MCP config from ${source.readPath}`, source.scope === "global");
|
|
6857
7115
|
if (!loaded)
|
|
6858
7116
|
continue;
|
|
6859
7117
|
if (loaded.imports?.length) {
|
|
@@ -6863,7 +7121,7 @@ function getServerProvenance(overridePath, cwd = process.cwd(), contributions =
|
|
|
6863
7121
|
continue;
|
|
6864
7122
|
try {
|
|
6865
7123
|
const imported = JSON.parse(readFileSync2(importPath, "utf-8"));
|
|
6866
|
-
const servers = extractServers(imported, importKind);
|
|
7124
|
+
const servers = extractServers(imported, importKind, source.scope === "global" && importKind !== "vscode");
|
|
6867
7125
|
for (const name of Object.keys(servers)) {
|
|
6868
7126
|
if (!provenance.has(name) || provenance.get(name)?.kind === "contributed") {
|
|
6869
7127
|
provenance.set(name, { path: userPath, kind: "import", importKind });
|
|
@@ -6916,18 +7174,20 @@ var init_config = __esm(() => {
|
|
|
6916
7174
|
init_agent_dir();
|
|
6917
7175
|
init_config_write_utils();
|
|
6918
7176
|
init_tool_call_timeout();
|
|
6919
|
-
|
|
7177
|
+
init_utils();
|
|
7178
|
+
init_provider_auth();
|
|
7179
|
+
GENERIC_GLOBAL_CONFIG_PATH = join3(homedir3(), ".config", "mcp", "mcp.json");
|
|
6920
7180
|
PROJECT_PI_CONFIG_NAME = `${CONFIG_DIR_NAME2}/mcp.json`;
|
|
6921
|
-
REPOPROMPT_BINARY_CANDIDATES = [
|
|
7181
|
+
REPOPROMPT_BINARY_CANDIDATES = [join3(homedir3(), "RepoPrompt", "repoprompt_cli"), "/Applications/Repo Prompt.app/Contents/MacOS/repoprompt-mcp"];
|
|
6922
7182
|
IMPORT_PATHS = {
|
|
6923
7183
|
"claude-code": [
|
|
6924
|
-
|
|
6925
|
-
|
|
6926
|
-
|
|
7184
|
+
join3(homedir3(), ".claude", "mcp.json"),
|
|
7185
|
+
join3(homedir3(), ".claude.json"),
|
|
7186
|
+
join3(homedir3(), ".claude", "claude_desktop_config.json")
|
|
6927
7187
|
],
|
|
6928
|
-
"claude-desktop": [
|
|
6929
|
-
codex: [
|
|
6930
|
-
windsurf: [
|
|
7188
|
+
"claude-desktop": [join3(homedir3(), "Library", "Application Support", "Claude", "claude_desktop_config.json")],
|
|
7189
|
+
codex: [join3(homedir3(), ".codex", "config.json")],
|
|
7190
|
+
windsurf: [join3(homedir3(), ".windsurf", "mcp.json")],
|
|
6931
7191
|
vscode: [".vscode/mcp.json"]
|
|
6932
7192
|
};
|
|
6933
7193
|
});
|
|
@@ -9134,20 +9394,25 @@ function getServerPrefix(serverName, mode) {
|
|
|
9134
9394
|
}
|
|
9135
9395
|
function formatToolName(toolName, serverName, prefix) {
|
|
9136
9396
|
const p = getServerPrefix(serverName, prefix);
|
|
9137
|
-
|
|
9397
|
+
const name = (p ? `${p}_${toolName}` : toolName).replace(/[^A-Za-z0-9_]/g, "_");
|
|
9398
|
+
return /^\d/.test(name) ? `_${name}` : name;
|
|
9138
9399
|
}
|
|
9139
9400
|
function normalizeToolName(value) {
|
|
9140
9401
|
return value.replace(/-/g, "_");
|
|
9141
9402
|
}
|
|
9403
|
+
function legacyToolName(toolName, serverName, prefix) {
|
|
9404
|
+
const p = getServerPrefix(serverName, prefix);
|
|
9405
|
+
return p ? `${p}_${toolName}` : toolName;
|
|
9406
|
+
}
|
|
9142
9407
|
function isToolExcluded(toolName, serverName, prefix, excludeTools) {
|
|
9143
9408
|
if (!Array.isArray(excludeTools) || excludeTools.length === 0)
|
|
9144
9409
|
return false;
|
|
9145
|
-
const
|
|
9146
|
-
|
|
9147
|
-
|
|
9148
|
-
normalizeToolName(formatToolName(toolName, serverName,
|
|
9149
|
-
normalizeToolName(
|
|
9150
|
-
|
|
9410
|
+
const modes = new Set([prefix, "server", "short"]);
|
|
9411
|
+
const candidates = new Set([normalizeToolName(toolName)]);
|
|
9412
|
+
for (const mode of modes) {
|
|
9413
|
+
candidates.add(normalizeToolName(formatToolName(toolName, serverName, mode)));
|
|
9414
|
+
candidates.add(normalizeToolName(legacyToolName(toolName, serverName, mode)));
|
|
9415
|
+
}
|
|
9151
9416
|
for (const excluded of excludeTools) {
|
|
9152
9417
|
if (typeof excluded !== "string")
|
|
9153
9418
|
continue;
|
|
@@ -9161,6 +9426,27 @@ var init_types2 = __esm(() => {
|
|
|
9161
9426
|
init_ui_stream_types();
|
|
9162
9427
|
});
|
|
9163
9428
|
|
|
9429
|
+
// dist/builtin/mcp/tool-names.ts
|
|
9430
|
+
import { createHash } from "node:crypto";
|
|
9431
|
+
function assignToolNames(names, server, prefix) {
|
|
9432
|
+
const unique = [...new Set(names)];
|
|
9433
|
+
const counts = new Map;
|
|
9434
|
+
for (const name of unique) {
|
|
9435
|
+
const plain = formatToolName(name, server, prefix);
|
|
9436
|
+
counts.set(plain, (counts.get(plain) ?? 0) + 1);
|
|
9437
|
+
}
|
|
9438
|
+
return new Map(unique.map((name) => {
|
|
9439
|
+
const plain = formatToolName(name, server, prefix);
|
|
9440
|
+
if (plain.length <= 64 && counts.get(plain) === 1)
|
|
9441
|
+
return [name, plain];
|
|
9442
|
+
const hash = createHash("sha256").update(`${server}\x00${name}`).digest("hex").slice(0, 8);
|
|
9443
|
+
return [name, `${plain.slice(0, 55)}_${hash}`];
|
|
9444
|
+
}));
|
|
9445
|
+
}
|
|
9446
|
+
var init_tool_names = __esm(() => {
|
|
9447
|
+
init_types2();
|
|
9448
|
+
});
|
|
9449
|
+
|
|
9164
9450
|
// dist/builtin/mcp/resource-tools.ts
|
|
9165
9451
|
function resourceNameToToolName(name) {
|
|
9166
9452
|
let result = name.replace(/[^a-zA-Z0-9]/g, "_").replace(/_+/g, "_").replace(/^_+/, "").replace(/_+$/, "").toLowerCase();
|
|
@@ -9170,141 +9456,10 @@ function resourceNameToToolName(name) {
|
|
|
9170
9456
|
return result;
|
|
9171
9457
|
}
|
|
9172
9458
|
|
|
9173
|
-
// dist/builtin/mcp/utils.ts
|
|
9174
|
-
var exports_utils = {};
|
|
9175
|
-
__export(exports_utils, {
|
|
9176
|
-
extractToolUiStreamMode: () => extractToolUiStreamMode,
|
|
9177
|
-
formatAuthRequiredMessage: () => formatAuthRequiredMessage,
|
|
9178
|
-
getConfigPathFromArgv: () => getConfigPathFromArgv,
|
|
9179
|
-
interpolateEnvRecord: () => interpolateEnvRecord,
|
|
9180
|
-
interpolateEnvVars: () => interpolateEnvVars,
|
|
9181
|
-
openPath: () => openPath,
|
|
9182
|
-
openUrl: () => openUrl,
|
|
9183
|
-
parallelLimit: () => parallelLimit,
|
|
9184
|
-
resolveBearerToken: () => resolveBearerToken,
|
|
9185
|
-
resolveConfigPath: () => resolveConfigPath,
|
|
9186
|
-
resolveServerUrl: () => resolveServerUrl,
|
|
9187
|
-
truncateAtWord: () => truncateAtWord,
|
|
9188
|
-
unflattenToolArguments: () => unflattenToolArguments
|
|
9189
|
-
});
|
|
9190
|
-
import { unflattenArgumentsWithSchema } from "@bastani/atomic";
|
|
9191
|
-
import { homedir as homedir3, platform } from "node:os";
|
|
9192
|
-
import { join as join3 } from "node:path";
|
|
9193
|
-
async function execOpen(pi, target, browser) {
|
|
9194
|
-
const os = platform();
|
|
9195
|
-
if (os === "darwin") {
|
|
9196
|
-
return browser ? pi.exec("open", ["-a", browser, target]) : pi.exec("open", [target]);
|
|
9197
|
-
}
|
|
9198
|
-
if (os === "win32") {
|
|
9199
|
-
return browser ? pi.exec("cmd", ["/c", "start", "", browser, target]) : pi.exec("cmd", ["/c", "start", "", target]);
|
|
9200
|
-
}
|
|
9201
|
-
return browser ? pi.exec(browser, [target]) : pi.exec("xdg-open", [target]);
|
|
9202
|
-
}
|
|
9203
|
-
async function openUrl(pi, url, browser) {
|
|
9204
|
-
const result = await execOpen(pi, url, browser);
|
|
9205
|
-
if (result.code !== 0) {
|
|
9206
|
-
throw new Error(result.stderr || `Failed to open browser (exit code ${result.code})`);
|
|
9207
|
-
}
|
|
9208
|
-
}
|
|
9209
|
-
async function openPath(pi, targetPath) {
|
|
9210
|
-
const result = await execOpen(pi, targetPath);
|
|
9211
|
-
if (result.code !== 0) {
|
|
9212
|
-
throw new Error(result.stderr || `Failed to open path (exit code ${result.code})`);
|
|
9213
|
-
}
|
|
9214
|
-
}
|
|
9215
|
-
async function parallelLimit(items, limit, fn) {
|
|
9216
|
-
const results = [];
|
|
9217
|
-
let index = 0;
|
|
9218
|
-
async function worker() {
|
|
9219
|
-
while (index < items.length) {
|
|
9220
|
-
const i = index++;
|
|
9221
|
-
results[i] = await fn(items[i]);
|
|
9222
|
-
}
|
|
9223
|
-
}
|
|
9224
|
-
const workers = Array(Math.min(limit, items.length)).fill(null).map(() => worker());
|
|
9225
|
-
await Promise.all(workers);
|
|
9226
|
-
return results;
|
|
9227
|
-
}
|
|
9228
|
-
function getConfigPathFromArgv() {
|
|
9229
|
-
const idx = process.argv.indexOf("--mcp-config");
|
|
9230
|
-
if (idx >= 0 && idx + 1 < process.argv.length) {
|
|
9231
|
-
return process.argv[idx + 1];
|
|
9232
|
-
}
|
|
9233
|
-
return;
|
|
9234
|
-
}
|
|
9235
|
-
function interpolateEnvVars(value) {
|
|
9236
|
-
return value.replace(/\$\{(\w+)\}/g, (_, name) => process.env[name] ?? "").replace(/\$env:(\w+)/g, (_, name) => process.env[name] ?? "");
|
|
9237
|
-
}
|
|
9238
|
-
function resolveServerUrl(value) {
|
|
9239
|
-
const resolved = interpolateEnvVars(value);
|
|
9240
|
-
try {
|
|
9241
|
-
const url = new URL(resolved);
|
|
9242
|
-
if (url.protocol === "http:" || url.protocol === "https:")
|
|
9243
|
-
return resolved;
|
|
9244
|
-
} catch {}
|
|
9245
|
-
throw new Error("Invalid MCP server url: expected a non-empty HTTP(S) URL after environment variable interpolation.");
|
|
9246
|
-
}
|
|
9247
|
-
function interpolateEnvRecord(values) {
|
|
9248
|
-
if (!values)
|
|
9249
|
-
return;
|
|
9250
|
-
const resolved = {};
|
|
9251
|
-
for (const [key, value] of Object.entries(values)) {
|
|
9252
|
-
resolved[key] = interpolateEnvVars(value);
|
|
9253
|
-
}
|
|
9254
|
-
return resolved;
|
|
9255
|
-
}
|
|
9256
|
-
function resolveConfigPath(value) {
|
|
9257
|
-
if (value === undefined)
|
|
9258
|
-
return;
|
|
9259
|
-
const resolved = interpolateEnvVars(value);
|
|
9260
|
-
if (resolved === "~")
|
|
9261
|
-
return homedir3();
|
|
9262
|
-
if (resolved.startsWith("~/") || resolved.startsWith("~\\")) {
|
|
9263
|
-
return join3(homedir3(), resolved.slice(2));
|
|
9264
|
-
}
|
|
9265
|
-
return resolved;
|
|
9266
|
-
}
|
|
9267
|
-
function resolveBearerToken(definition) {
|
|
9268
|
-
if (definition.bearerToken !== undefined) {
|
|
9269
|
-
return interpolateEnvVars(definition.bearerToken);
|
|
9270
|
-
}
|
|
9271
|
-
return definition.bearerTokenEnv ? process.env[definition.bearerTokenEnv] : undefined;
|
|
9272
|
-
}
|
|
9273
|
-
function truncateAtWord(text, target) {
|
|
9274
|
-
if (!text || text.length <= target)
|
|
9275
|
-
return text;
|
|
9276
|
-
const truncated = text.slice(0, target);
|
|
9277
|
-
const lastSpace = truncated.lastIndexOf(" ");
|
|
9278
|
-
if (lastSpace > target * 0.6) {
|
|
9279
|
-
return truncated.slice(0, lastSpace) + "...";
|
|
9280
|
-
}
|
|
9281
|
-
return truncated + "...";
|
|
9282
|
-
}
|
|
9283
|
-
function formatAuthRequiredMessage(config, serverName, defaultMessage) {
|
|
9284
|
-
const template = config.settings?.authRequiredMessage;
|
|
9285
|
-
return template ? template.replaceAll("${server}", serverName) : defaultMessage;
|
|
9286
|
-
}
|
|
9287
|
-
function extractToolUiStreamMode(toolMeta) {
|
|
9288
|
-
const uiMeta = toolMeta?.ui;
|
|
9289
|
-
if (!uiMeta || typeof uiMeta !== "object")
|
|
9290
|
-
return;
|
|
9291
|
-
const streamMode = uiMeta["pi-mcp-adapter.streamMode"];
|
|
9292
|
-
if (streamMode === "eager" || streamMode === "stream-first") {
|
|
9293
|
-
return streamMode;
|
|
9294
|
-
}
|
|
9295
|
-
return;
|
|
9296
|
-
}
|
|
9297
|
-
function unflattenToolArguments(args, inputSchema) {
|
|
9298
|
-
if (args === null || args === undefined)
|
|
9299
|
-
return {};
|
|
9300
|
-
return unflattenArgumentsWithSchema(args, inputSchema);
|
|
9301
|
-
}
|
|
9302
|
-
var init_utils = () => {};
|
|
9303
|
-
|
|
9304
9459
|
// dist/builtin/mcp/metadata-cache.ts
|
|
9305
9460
|
import { existsSync as existsSync3, readFileSync as readFileSync3, writeFileSync as writeFileSync2, renameSync as renameSync2, mkdirSync as mkdirSync2 } from "node:fs";
|
|
9306
9461
|
import { dirname as dirname3 } from "node:path";
|
|
9307
|
-
import { createHash } from "node:crypto";
|
|
9462
|
+
import { createHash as createHash2 } from "node:crypto";
|
|
9308
9463
|
function getMetadataCachePath() {
|
|
9309
9464
|
return getAgentPath("mcp-cache.json");
|
|
9310
9465
|
}
|
|
@@ -9359,7 +9514,7 @@ function computeServerHash(definition) {
|
|
|
9359
9514
|
excludeTools: definition.excludeTools
|
|
9360
9515
|
};
|
|
9361
9516
|
const normalized = stableStringify(identity);
|
|
9362
|
-
return
|
|
9517
|
+
return createHash2("sha256").update(normalized).digest("hex");
|
|
9363
9518
|
}
|
|
9364
9519
|
function isServerCacheValid(entry, definition, maxAgeMs = CACHE_MAX_AGE_MS) {
|
|
9365
9520
|
if (!entry || entry.configHash !== computeServerHash(definition))
|
|
@@ -9372,6 +9527,10 @@ function isServerCacheValid(entry, definition, maxAgeMs = CACHE_MAX_AGE_MS) {
|
|
|
9372
9527
|
}
|
|
9373
9528
|
function reconstructToolMetadata(serverName, entry, prefix, definition) {
|
|
9374
9529
|
const metadata = [];
|
|
9530
|
+
const names = assignToolNames([
|
|
9531
|
+
...(entry.tools ?? []).filter((tool) => tool?.name).map((tool) => tool.name),
|
|
9532
|
+
...definition.exposeResources !== false ? (entry.resources ?? []).filter((resource) => resource?.name && resource?.uri).map((resource) => `get_${resourceNameToToolName(resource.name)}`) : []
|
|
9533
|
+
], serverName, prefix);
|
|
9375
9534
|
for (const tool of entry.tools ?? []) {
|
|
9376
9535
|
if (!tool?.name)
|
|
9377
9536
|
continue;
|
|
@@ -9379,7 +9538,7 @@ function reconstructToolMetadata(serverName, entry, prefix, definition) {
|
|
|
9379
9538
|
continue;
|
|
9380
9539
|
}
|
|
9381
9540
|
metadata.push({
|
|
9382
|
-
name:
|
|
9541
|
+
name: names.get(tool.name),
|
|
9383
9542
|
originalName: tool.name,
|
|
9384
9543
|
description: tool.description ?? "",
|
|
9385
9544
|
inputSchema: tool.inputSchema,
|
|
@@ -9396,7 +9555,7 @@ function reconstructToolMetadata(serverName, entry, prefix, definition) {
|
|
|
9396
9555
|
continue;
|
|
9397
9556
|
}
|
|
9398
9557
|
metadata.push({
|
|
9399
|
-
name:
|
|
9558
|
+
name: names.get(baseName),
|
|
9400
9559
|
originalName: baseName,
|
|
9401
9560
|
description: resource.description ?? `Read resource: ${resource.uri}`,
|
|
9402
9561
|
resourceUri: resource.uri
|
|
@@ -9445,6 +9604,7 @@ var init_metadata_cache = __esm(() => {
|
|
|
9445
9604
|
init_agent_dir();
|
|
9446
9605
|
init_app_bridge();
|
|
9447
9606
|
init_types2();
|
|
9607
|
+
init_tool_names();
|
|
9448
9608
|
init_utils();
|
|
9449
9609
|
CACHE_MAX_AGE_MS = 7 * 24 * 60 * 60 * 1000;
|
|
9450
9610
|
});
|
|
@@ -20222,7 +20382,7 @@ class McpOAuthProvider {
|
|
|
20222
20382
|
get clientMetadata() {
|
|
20223
20383
|
if (this.usesClientCredentials) {
|
|
20224
20384
|
return {
|
|
20225
|
-
client_name:
|
|
20385
|
+
client_name: this.config.clientName ?? "atomic",
|
|
20226
20386
|
redirect_uris: [],
|
|
20227
20387
|
grant_types: ["client_credentials"],
|
|
20228
20388
|
token_endpoint_auth_method: this.config.clientSecret ? "client_secret_post" : "none"
|
|
@@ -20234,7 +20394,7 @@ class McpOAuthProvider {
|
|
|
20234
20394
|
}
|
|
20235
20395
|
return {
|
|
20236
20396
|
redirect_uris: [redirectUrl],
|
|
20237
|
-
client_name:
|
|
20397
|
+
client_name: this.config.clientName ?? "atomic",
|
|
20238
20398
|
client_uri: "https://github.com/nicobailon/pi-mcp-adapter",
|
|
20239
20399
|
grant_types: ["authorization_code", "refresh_token"],
|
|
20240
20400
|
response_types: ["code"],
|
|
@@ -21314,7 +21474,7 @@ function redactDiagnosticText(message, endpoint, preserveSafeUrls = false) {
|
|
|
21314
21474
|
}
|
|
21315
21475
|
function sanitizeRemoteError(error, endpoint) {
|
|
21316
21476
|
const message = redactDiagnosticText(error instanceof Error ? error.message : String(error), endpoint);
|
|
21317
|
-
const safe = error instanceof UnauthorizedError ? new UnauthorizedError(message) : new Error(message);
|
|
21477
|
+
const safe = error instanceof UnauthorizedError ? new UnauthorizedError(message) : error instanceof McpProviderAuthError ? new McpProviderAuthError(message, error.provider) : new Error(message);
|
|
21318
21478
|
if (error instanceof Error && "code" in error && typeof error.code === "number") {
|
|
21319
21479
|
Object.assign(safe, { code: error.code });
|
|
21320
21480
|
}
|
|
@@ -21388,6 +21548,7 @@ function protectRemoteTransport(transport, endpoint) {
|
|
|
21388
21548
|
var init_remote_diagnostics = __esm(() => {
|
|
21389
21549
|
init_auth2();
|
|
21390
21550
|
init_types();
|
|
21551
|
+
init_provider_auth();
|
|
21391
21552
|
});
|
|
21392
21553
|
|
|
21393
21554
|
// dist/builtin/mcp/mcp-auth-flow.ts
|
|
@@ -21419,7 +21580,8 @@ function extractOAuthConfig(definition) {
|
|
|
21419
21580
|
grantType: definition.oauth?.grantType,
|
|
21420
21581
|
clientId: definition.oauth?.clientId,
|
|
21421
21582
|
clientSecret: definition.oauth?.clientSecret,
|
|
21422
|
-
scope: definition.oauth?.scope
|
|
21583
|
+
scope: definition.oauth?.scope,
|
|
21584
|
+
clientName: definition.oauth?.clientName
|
|
21423
21585
|
};
|
|
21424
21586
|
}
|
|
21425
21587
|
function assertActive(owner) {
|
|
@@ -21537,6 +21699,9 @@ async function performAuthentication(owner, serverUrl, definition) {
|
|
|
21537
21699
|
}
|
|
21538
21700
|
const callbackPromise = waitForCallback(started.oauthState);
|
|
21539
21701
|
try {
|
|
21702
|
+
owner.authorizationUrl = started.authorizationUrl;
|
|
21703
|
+
for (const listener of owner.authorizationListeners)
|
|
21704
|
+
listener(started.authorizationUrl);
|
|
21540
21705
|
if (!reportOwnedMcpLog("info"))
|
|
21541
21706
|
console.log(`MCP Auth: Opening browser for ${serverName}`);
|
|
21542
21707
|
try {
|
|
@@ -21564,11 +21729,17 @@ async function performAuthentication(owner, serverUrl, definition) {
|
|
|
21564
21729
|
throw failure;
|
|
21565
21730
|
}
|
|
21566
21731
|
}
|
|
21567
|
-
function authenticate(serverName, serverUrl, definition) {
|
|
21732
|
+
function authenticate(serverName, serverUrl, definition, onAuthorizationUrl) {
|
|
21568
21733
|
const { pendingAuthentications, oauthCleanupBarrier } = oauthLifecycle();
|
|
21569
21734
|
const inFlight = pendingAuthentications.get(serverName);
|
|
21570
|
-
if (inFlight)
|
|
21735
|
+
if (inFlight) {
|
|
21736
|
+
if (onAuthorizationUrl) {
|
|
21737
|
+
inFlight.authorizationListeners.add(onAuthorizationUrl);
|
|
21738
|
+
if (inFlight.authorizationUrl)
|
|
21739
|
+
onAuthorizationUrl(inFlight.authorizationUrl);
|
|
21740
|
+
}
|
|
21571
21741
|
return inFlight.result;
|
|
21742
|
+
}
|
|
21572
21743
|
let resolve;
|
|
21573
21744
|
let reject;
|
|
21574
21745
|
const result = new Promise((resolveResult, rejectResult) => {
|
|
@@ -21579,7 +21750,7 @@ function authenticate(serverName, serverUrl, definition) {
|
|
|
21579
21750
|
const inheritedCleanup = oauthCleanupBarrier.wait();
|
|
21580
21751
|
let owner;
|
|
21581
21752
|
const producer = inheritedCleanup.then(() => performAuthentication(owner, serverUrl, definition));
|
|
21582
|
-
owner = { serverName, controller, result, producer, resolve, reject };
|
|
21753
|
+
owner = { serverName, controller, result, producer, resolve, reject, authorizationListeners: new Set(onAuthorizationUrl ? [onAuthorizationUrl] : []) };
|
|
21583
21754
|
pendingAuthentications.set(serverName, owner);
|
|
21584
21755
|
const removeOwner = () => {
|
|
21585
21756
|
if (pendingAuthentications.get(serverName) === owner)
|
|
@@ -21886,9 +22057,13 @@ class McpServerManager {
|
|
|
21886
22057
|
connectPromises = new Map;
|
|
21887
22058
|
uiStreamListeners = new Map;
|
|
21888
22059
|
samplingConfig;
|
|
22060
|
+
providerToken;
|
|
21889
22061
|
setSamplingConfig(config) {
|
|
21890
22062
|
this.samplingConfig = config;
|
|
21891
22063
|
}
|
|
22064
|
+
setProviderTokenResolver(resolver) {
|
|
22065
|
+
this.providerToken = resolver;
|
|
22066
|
+
}
|
|
21892
22067
|
async connect(name, definition) {
|
|
21893
22068
|
if (this.connectPromises.has(name)) {
|
|
21894
22069
|
return this.connectPromises.get(name);
|
|
@@ -21930,7 +22105,23 @@ class McpServerManager {
|
|
|
21930
22105
|
stderr: definition.debug ? "inherit" : "ignore"
|
|
21931
22106
|
});
|
|
21932
22107
|
} else if (definition.url !== undefined) {
|
|
21933
|
-
|
|
22108
|
+
try {
|
|
22109
|
+
transport = await this.createHttpTransport(definition, name);
|
|
22110
|
+
} catch (error) {
|
|
22111
|
+
if (error instanceof McpProviderAuthError && error.provider !== undefined) {
|
|
22112
|
+
return {
|
|
22113
|
+
client,
|
|
22114
|
+
transport: new StreamableHTTPClientTransport(new URL(resolveServerUrl(definition.url))),
|
|
22115
|
+
definition,
|
|
22116
|
+
tools: [],
|
|
22117
|
+
resources: [],
|
|
22118
|
+
lastUsedAt: Date.now(),
|
|
22119
|
+
inFlight: 0,
|
|
22120
|
+
status: "needs-auth"
|
|
22121
|
+
};
|
|
22122
|
+
}
|
|
22123
|
+
throw error;
|
|
22124
|
+
}
|
|
21934
22125
|
} else {
|
|
21935
22126
|
throw new Error(`Server ${name} has no command or url`);
|
|
21936
22127
|
}
|
|
@@ -21952,7 +22143,7 @@ class McpServerManager {
|
|
|
21952
22143
|
status: "connected"
|
|
21953
22144
|
};
|
|
21954
22145
|
} catch (error) {
|
|
21955
|
-
if (error instanceof UnauthorizedError && supportsOAuth(definition)) {
|
|
22146
|
+
if (error instanceof UnauthorizedError && supportsOAuth(definition) || error instanceof McpProviderAuthError && error.provider !== undefined) {
|
|
21956
22147
|
await client.close().catch(() => {});
|
|
21957
22148
|
await transport.close().catch(() => {});
|
|
21958
22149
|
return {
|
|
@@ -21995,12 +22186,25 @@ class McpServerManager {
|
|
|
21995
22186
|
grantType: definition.oauth?.grantType,
|
|
21996
22187
|
clientId: definition.oauth?.clientId,
|
|
21997
22188
|
clientSecret: definition.oauth?.clientSecret,
|
|
21998
|
-
scope: definition.oauth?.scope
|
|
22189
|
+
scope: definition.oauth?.scope,
|
|
22190
|
+
clientName: definition.oauth?.clientName
|
|
21999
22191
|
};
|
|
22000
22192
|
authProvider = new McpOAuthProvider(serverName, resolvedUrl, oauthConfig, {
|
|
22001
22193
|
onRedirect: async (_authUrl) => {}
|
|
22002
22194
|
});
|
|
22003
22195
|
}
|
|
22196
|
+
let providerFetch;
|
|
22197
|
+
if (isProviderAuth(definition.auth)) {
|
|
22198
|
+
const urlError = providerAuthUrlError(resolvedUrl);
|
|
22199
|
+
if (urlError)
|
|
22200
|
+
throw new Error(`MCP server "${serverName}": ${urlError}`);
|
|
22201
|
+
providerFetch = createProviderAuthFetch({
|
|
22202
|
+
serverName,
|
|
22203
|
+
provider: definition.auth.provider,
|
|
22204
|
+
serverUrl: resolvedUrl,
|
|
22205
|
+
token: this.providerToken
|
|
22206
|
+
});
|
|
22207
|
+
}
|
|
22004
22208
|
const protect = (transport) => {
|
|
22005
22209
|
if (authProvider) {
|
|
22006
22210
|
const close = transport.close.bind(transport);
|
|
@@ -22014,20 +22218,56 @@ class McpServerManager {
|
|
|
22014
22218
|
const streamableTransport = protect(new StreamableHTTPClientTransport(url, {
|
|
22015
22219
|
requestInit,
|
|
22016
22220
|
authProvider,
|
|
22017
|
-
fetch: authProvider?.fetch
|
|
22221
|
+
fetch: authProvider?.fetch ?? providerFetch
|
|
22018
22222
|
}));
|
|
22019
22223
|
try {
|
|
22020
22224
|
const testClient = new Client({ name: "pi-mcp-probe", version: "2.1.2" });
|
|
22021
22225
|
await testClient.connect(streamableTransport);
|
|
22022
22226
|
await testClient.close().catch(() => {});
|
|
22023
22227
|
await streamableTransport.close().catch(() => {});
|
|
22024
|
-
return protect(new StreamableHTTPClientTransport(url, { requestInit, authProvider, fetch: authProvider?.fetch }));
|
|
22228
|
+
return protect(new StreamableHTTPClientTransport(url, { requestInit, authProvider, fetch: authProvider?.fetch ?? providerFetch }));
|
|
22025
22229
|
} catch (error) {
|
|
22026
22230
|
await streamableTransport.close().catch(() => {});
|
|
22027
|
-
if (error instanceof UnauthorizedError) {
|
|
22231
|
+
if (error instanceof UnauthorizedError || error instanceof McpProviderAuthError) {
|
|
22028
22232
|
throw error;
|
|
22029
22233
|
}
|
|
22030
|
-
|
|
22234
|
+
let pendingStart;
|
|
22235
|
+
const sseTransport = new SSEClientTransport(url, {
|
|
22236
|
+
requestInit,
|
|
22237
|
+
authProvider,
|
|
22238
|
+
fetch: authProvider?.fetch ?? providerFetch,
|
|
22239
|
+
eventSourceInit: providerFetch ? {
|
|
22240
|
+
fetch: async (input, init) => {
|
|
22241
|
+
const attempt = pendingStart;
|
|
22242
|
+
if (attempt)
|
|
22243
|
+
attempt.error = undefined;
|
|
22244
|
+
try {
|
|
22245
|
+
return await providerFetch(input, init);
|
|
22246
|
+
} catch (error) {
|
|
22247
|
+
if (attempt && pendingStart === attempt && !init?.signal?.aborted && error instanceof McpProviderAuthError) {
|
|
22248
|
+
attempt.error = error;
|
|
22249
|
+
}
|
|
22250
|
+
throw error;
|
|
22251
|
+
}
|
|
22252
|
+
}
|
|
22253
|
+
} : undefined
|
|
22254
|
+
});
|
|
22255
|
+
if (providerFetch) {
|
|
22256
|
+
const start = sseTransport.start.bind(sseTransport);
|
|
22257
|
+
sseTransport.start = async () => {
|
|
22258
|
+
const attempt = {};
|
|
22259
|
+
pendingStart = attempt;
|
|
22260
|
+
try {
|
|
22261
|
+
await start();
|
|
22262
|
+
} catch (error) {
|
|
22263
|
+
throw attempt.error ?? error;
|
|
22264
|
+
} finally {
|
|
22265
|
+
if (pendingStart === attempt)
|
|
22266
|
+
pendingStart = undefined;
|
|
22267
|
+
}
|
|
22268
|
+
};
|
|
22269
|
+
}
|
|
22270
|
+
return protect(sseTransport);
|
|
22031
22271
|
}
|
|
22032
22272
|
}
|
|
22033
22273
|
async fetchAllTools(client) {
|
|
@@ -22155,12 +22395,17 @@ var init_server_manager = __esm(() => {
|
|
|
22155
22395
|
init_sampling_handler();
|
|
22156
22396
|
init_utils();
|
|
22157
22397
|
init_remote_diagnostics();
|
|
22398
|
+
init_provider_auth();
|
|
22158
22399
|
});
|
|
22159
22400
|
|
|
22160
22401
|
// dist/builtin/mcp/tool-metadata.ts
|
|
22161
22402
|
function buildToolMetadata(tools, resources, definition, serverName, prefix) {
|
|
22162
22403
|
const metadata = [];
|
|
22163
22404
|
const failedTools = [];
|
|
22405
|
+
const names = assignToolNames([
|
|
22406
|
+
...tools.filter((tool) => tool?.name).map((tool) => tool.name),
|
|
22407
|
+
...definition.exposeResources !== false ? resources.filter((resource) => resource?.name && resource?.uri).map((resource) => `get_${resourceNameToToolName(resource.name)}`) : []
|
|
22408
|
+
], serverName, prefix);
|
|
22164
22409
|
for (const tool of tools) {
|
|
22165
22410
|
if (!tool?.name) {
|
|
22166
22411
|
failedTools.push("(unnamed)");
|
|
@@ -22176,7 +22421,7 @@ function buildToolMetadata(tools, resources, definition, serverName, prefix) {
|
|
|
22176
22421
|
failedTools.push(tool.name);
|
|
22177
22422
|
}
|
|
22178
22423
|
metadata.push({
|
|
22179
|
-
name:
|
|
22424
|
+
name: names.get(tool.name),
|
|
22180
22425
|
originalName: tool.name,
|
|
22181
22426
|
description: tool.description ?? "",
|
|
22182
22427
|
inputSchema: tool.inputSchema,
|
|
@@ -22186,12 +22431,14 @@ function buildToolMetadata(tools, resources, definition, serverName, prefix) {
|
|
|
22186
22431
|
}
|
|
22187
22432
|
if (definition.exposeResources !== false) {
|
|
22188
22433
|
for (const resource of resources) {
|
|
22434
|
+
if (!resource?.name || !resource?.uri)
|
|
22435
|
+
continue;
|
|
22189
22436
|
const baseName = `get_${resourceNameToToolName(resource.name)}`;
|
|
22190
22437
|
if (isToolExcluded(baseName, serverName, prefix, definition.excludeTools)) {
|
|
22191
22438
|
continue;
|
|
22192
22439
|
}
|
|
22193
22440
|
metadata.push({
|
|
22194
|
-
name:
|
|
22441
|
+
name: names.get(baseName),
|
|
22195
22442
|
originalName: baseName,
|
|
22196
22443
|
description: resource.description ?? `Read resource: ${resource.uri}`,
|
|
22197
22444
|
resourceUri: resource.uri
|
|
@@ -22282,6 +22529,7 @@ function formatProperty(name, schema, required, indent) {
|
|
|
22282
22529
|
var init_tool_metadata = __esm(() => {
|
|
22283
22530
|
init_app_bridge();
|
|
22284
22531
|
init_types2();
|
|
22532
|
+
init_tool_names();
|
|
22285
22533
|
init_utils();
|
|
22286
22534
|
});
|
|
22287
22535
|
|
|
@@ -22420,6 +22668,7 @@ async function initializeMcp(pi, ctx) {
|
|
|
22420
22668
|
const contributions = pi.getMcpServerContributions?.() ?? [];
|
|
22421
22669
|
const config = loadMcpConfig(configPath, ctx.cwd, contributions);
|
|
22422
22670
|
const manager = new McpServerManager;
|
|
22671
|
+
manager.setProviderTokenResolver((provider) => ctx.modelRegistry.getApiKeyForProvider(provider));
|
|
22423
22672
|
const lifecycle = new McpLifecycleManager(manager);
|
|
22424
22673
|
try {
|
|
22425
22674
|
const samplingAutoApprove = config.settings?.samplingAutoApprove === true;
|
|
@@ -22482,7 +22731,12 @@ async function initializeMcp(pi, ctx) {
|
|
|
22482
22731
|
try {
|
|
22483
22732
|
const connection = await manager.connect(name, definition);
|
|
22484
22733
|
if (connection.status === "needs-auth") {
|
|
22485
|
-
return {
|
|
22734
|
+
return {
|
|
22735
|
+
name,
|
|
22736
|
+
definition,
|
|
22737
|
+
connection: null,
|
|
22738
|
+
error: providerSignInGuidance(definition, name) ?? `OAuth authentication required. Run /mcp-auth ${name}.`
|
|
22739
|
+
};
|
|
22486
22740
|
}
|
|
22487
22741
|
return { name, definition, connection, error: null };
|
|
22488
22742
|
} catch (error) {
|
|
@@ -22655,7 +22909,9 @@ function getFailureAgeSeconds(state, serverName) {
|
|
|
22655
22909
|
async function lazyConnect(state, serverName) {
|
|
22656
22910
|
const connection = state.manager.getConnection(serverName);
|
|
22657
22911
|
if (connection?.status === "needs-auth") {
|
|
22658
|
-
|
|
22912
|
+
if (!isProviderAuth(state.config.mcpServers[serverName]?.auth))
|
|
22913
|
+
return false;
|
|
22914
|
+
await state.manager.close(serverName);
|
|
22659
22915
|
}
|
|
22660
22916
|
if (connection?.status === "connected") {
|
|
22661
22917
|
updateServerMetadata(state, serverName);
|
|
@@ -22712,6 +22968,7 @@ var init_init = __esm(() => {
|
|
|
22712
22968
|
init_tool_metadata();
|
|
22713
22969
|
init_ui_resource_handler();
|
|
22714
22970
|
init_utils();
|
|
22971
|
+
init_provider_auth();
|
|
22715
22972
|
init_logger();
|
|
22716
22973
|
FAILURE_BACKOFF_MS = 60 * 1000;
|
|
22717
22974
|
});
|
|
@@ -23487,7 +23744,7 @@ var init_mcp_panel_types = __esm(() => {
|
|
|
23487
23744
|
});
|
|
23488
23745
|
|
|
23489
23746
|
// dist/builtin/mcp/mcp-panel-renderer.ts
|
|
23490
|
-
import { truncateToWidth as truncateToWidth2, visibleWidth as visibleWidth2 } from "@earendil-works/pi-tui";
|
|
23747
|
+
import { Text, truncateToWidth as truncateToWidth2, visibleWidth as visibleWidth2 } from "@earendil-works/pi-tui";
|
|
23491
23748
|
function bold(text) {
|
|
23492
23749
|
return `\x1B[1m${text}\x1B[22m`;
|
|
23493
23750
|
}
|
|
@@ -23662,7 +23919,8 @@ function renderMcpPanel(context) {
|
|
|
23662
23919
|
lines.push(emptyRow());
|
|
23663
23920
|
}
|
|
23664
23921
|
if (context.authNotice) {
|
|
23665
|
-
|
|
23922
|
+
for (const line of new Text(fg2(t.needsAuth, context.authNotice), 0, 0).render(Math.max(1, innerW - 1)))
|
|
23923
|
+
lines.push(row(line));
|
|
23666
23924
|
lines.push(emptyRow());
|
|
23667
23925
|
}
|
|
23668
23926
|
}
|
|
@@ -23930,7 +24188,10 @@ class McpPanel {
|
|
|
23930
24188
|
this.authInFlight = server.name;
|
|
23931
24189
|
this.authNotice = `Authenticating ${server.name}...`;
|
|
23932
24190
|
this.tui.requestRender();
|
|
23933
|
-
this.callbacks.authenticate(server.name
|
|
24191
|
+
this.callbacks.authenticate(server.name, (url) => {
|
|
24192
|
+
this.authNotice = authorizationNotice(url);
|
|
24193
|
+
this.tui.requestRender();
|
|
24194
|
+
}).then((result) => {
|
|
23934
24195
|
server.connectionStatus = this.callbacks.getConnectionStatus(server.name);
|
|
23935
24196
|
this.authNotice = result.ok ? `OAuth finished for ${server.name}. Run reconnect if it is still idle.` : `OAuth failed for ${server.name}${result.message ? `: ${result.message}` : ". Check the notification for details."}`;
|
|
23936
24197
|
this.authInFlight = null;
|
|
@@ -24033,6 +24294,7 @@ function createMcpPanel(config, cache, provenance, callbacks, tui, done, options
|
|
|
24033
24294
|
return new McpPanel(config, cache, provenance, callbacks, tui, done, options ?? {});
|
|
24034
24295
|
}
|
|
24035
24296
|
var init_mcp_panel = __esm(() => {
|
|
24297
|
+
init_authorization_notice();
|
|
24036
24298
|
init_mcp_panel_state();
|
|
24037
24299
|
init_mcp_panel_renderer();
|
|
24038
24300
|
init_mcp_panel_types();
|
|
@@ -24106,7 +24368,7 @@ async function reconnectServers(state, ctx, targetServer) {
|
|
|
24106
24368
|
const connection = await state.manager.connect(name, definition);
|
|
24107
24369
|
if (connection.status === "needs-auth") {
|
|
24108
24370
|
if (ctx.hasUI) {
|
|
24109
|
-
ctx.ui.notify(`MCP: ${name} requires OAuth. Run /mcp-auth ${name} first.`, "warning");
|
|
24371
|
+
ctx.ui.notify(providerSignInGuidance(definition, name) ?? `MCP: ${name} requires OAuth. Run /mcp-auth ${name} first.`, "warning");
|
|
24110
24372
|
}
|
|
24111
24373
|
continue;
|
|
24112
24374
|
}
|
|
@@ -24131,7 +24393,7 @@ async function reconnectServers(state, ctx, targetServer) {
|
|
|
24131
24393
|
}
|
|
24132
24394
|
updateStatusBar(state);
|
|
24133
24395
|
}
|
|
24134
|
-
async function authenticateServer(serverName, config, ctx) {
|
|
24396
|
+
async function authenticateServer(serverName, config, ctx, onAuthorizationUrl) {
|
|
24135
24397
|
if (!ctx.hasUI)
|
|
24136
24398
|
return { ok: false, message: "OAuth authentication requires an interactive session." };
|
|
24137
24399
|
const definition = config.mcpServers[serverName];
|
|
@@ -24153,7 +24415,12 @@ async function authenticateServer(serverName, config, ctx) {
|
|
|
24153
24415
|
}
|
|
24154
24416
|
try {
|
|
24155
24417
|
ctx.ui.setStatus("mcp-auth", `Authenticating ${serverName}...`);
|
|
24156
|
-
const status = await authenticate(serverName, definition.url, definition)
|
|
24418
|
+
const status = await authenticate(serverName, definition.url, definition, (url) => {
|
|
24419
|
+
if (onAuthorizationUrl)
|
|
24420
|
+
onAuthorizationUrl(url);
|
|
24421
|
+
else
|
|
24422
|
+
ctx.ui.notify(authorizationNotice(url), "info");
|
|
24423
|
+
});
|
|
24157
24424
|
if (status === "authenticated") {
|
|
24158
24425
|
const message = `OAuth authentication successful for "${serverName}"! Run /mcp reconnect ${serverName} to connect with the new token.`;
|
|
24159
24426
|
ctx.ui.notify(`OAuth authentication successful for "${serverName}"!
|
|
@@ -24262,7 +24529,7 @@ function buildMcpPanelCallbacks(state, config, ctx) {
|
|
|
24262
24529
|
const definition = config.mcpServers[serverName];
|
|
24263
24530
|
return definition ? supportsOAuth(definition) : false;
|
|
24264
24531
|
},
|
|
24265
|
-
authenticate: (serverName) => authenticateServer(serverName, config, ctx),
|
|
24532
|
+
authenticate: (serverName, onAuthorizationUrl) => authenticateServer(serverName, config, ctx, onAuthorizationUrl),
|
|
24266
24533
|
getConnectionStatus: (serverName) => {
|
|
24267
24534
|
const definition = config.mcpServers[serverName];
|
|
24268
24535
|
const connection = state.manager.getConnection(serverName);
|
|
@@ -24342,6 +24609,8 @@ async function openMcpAuthPanel(state, pi, ctx, configOverridePath) {
|
|
|
24342
24609
|
return { configChanged: false };
|
|
24343
24610
|
}
|
|
24344
24611
|
var init_commands = __esm(() => {
|
|
24612
|
+
init_authorization_notice();
|
|
24613
|
+
init_provider_auth();
|
|
24345
24614
|
init_config();
|
|
24346
24615
|
init_init();
|
|
24347
24616
|
init_metadata_cache();
|
|
@@ -25688,7 +25957,7 @@ function asCallToolResult(result) {
|
|
|
25688
25957
|
}
|
|
25689
25958
|
|
|
25690
25959
|
// dist/builtin/mcp/direct-tool-executor.ts
|
|
25691
|
-
function getDirectAuthRequiredMessage(state, serverName, defaultMessage = `MCP server "${serverName}" requires OAuth authentication. Run /mcp-auth ${serverName} first.`) {
|
|
25960
|
+
function getDirectAuthRequiredMessage(state, serverName, defaultMessage = providerSignInGuidance(state.config.mcpServers[serverName], serverName) ?? `MCP server "${serverName}" requires OAuth authentication. Run /mcp-auth ${serverName} first.`) {
|
|
25692
25961
|
return formatAuthRequiredMessage(state.config, serverName, defaultMessage);
|
|
25693
25962
|
}
|
|
25694
25963
|
function getDirectAuthFailedMessage(state, serverName, message) {
|
|
@@ -25927,6 +26196,7 @@ ${formatSchema(spec.inputSchema)}`;
|
|
|
25927
26196
|
};
|
|
25928
26197
|
}
|
|
25929
26198
|
var init_direct_tool_executor = __esm(() => {
|
|
26199
|
+
init_provider_auth();
|
|
25930
26200
|
init_init();
|
|
25931
26201
|
init_tool_metadata();
|
|
25932
26202
|
init_ui_session();
|
|
@@ -25981,6 +26251,10 @@ function resolveDirectTools(config, cache, prefix, envOverride) {
|
|
|
25981
26251
|
const serverCache = cache.servers[serverName];
|
|
25982
26252
|
if (!serverCache || !isServerCacheValid(serverCache, definition))
|
|
25983
26253
|
continue;
|
|
26254
|
+
const names = assignToolNames([
|
|
26255
|
+
...(serverCache.tools ?? []).filter((tool) => tool?.name).map((tool) => tool.name),
|
|
26256
|
+
...definition.exposeResources !== false ? (serverCache.resources ?? []).filter((resource) => resource?.name && resource?.uri).map((resource) => `get_${resourceNameToToolName(resource.name)}`) : []
|
|
26257
|
+
], serverName, prefix);
|
|
25984
26258
|
let toolFilter = false;
|
|
25985
26259
|
if (envOverride) {
|
|
25986
26260
|
if (envSelection.servers.has(serverName)) {
|
|
@@ -25998,11 +26272,13 @@ function resolveDirectTools(config, cache, prefix, envOverride) {
|
|
|
25998
26272
|
if (!toolFilter)
|
|
25999
26273
|
continue;
|
|
26000
26274
|
for (const tool of serverCache.tools ?? []) {
|
|
26275
|
+
if (!tool?.name)
|
|
26276
|
+
continue;
|
|
26001
26277
|
if (toolFilter !== true && !toolFilter.includes(tool.name))
|
|
26002
26278
|
continue;
|
|
26003
26279
|
if (isToolExcluded(tool.name, serverName, prefix, definition.excludeTools))
|
|
26004
26280
|
continue;
|
|
26005
|
-
const prefixedName =
|
|
26281
|
+
const prefixedName = names.get(tool.name);
|
|
26006
26282
|
if (BUILTIN_NAMES.has(prefixedName)) {
|
|
26007
26283
|
if (!reportOwnedMcpLog("warn"))
|
|
26008
26284
|
console.warn(`MCP: skipping direct tool "${prefixedName}" (collides with builtin)`);
|
|
@@ -26026,12 +26302,14 @@ function resolveDirectTools(config, cache, prefix, envOverride) {
|
|
|
26026
26302
|
}
|
|
26027
26303
|
if (definition.exposeResources !== false) {
|
|
26028
26304
|
for (const resource of serverCache.resources ?? []) {
|
|
26305
|
+
if (!resource?.name || !resource?.uri)
|
|
26306
|
+
continue;
|
|
26029
26307
|
const baseName = `get_${resourceNameToToolName(resource.name)}`;
|
|
26030
26308
|
if (toolFilter !== true && !toolFilter.includes(baseName))
|
|
26031
26309
|
continue;
|
|
26032
26310
|
if (isToolExcluded(baseName, serverName, prefix, definition.excludeTools))
|
|
26033
26311
|
continue;
|
|
26034
|
-
const prefixedName =
|
|
26312
|
+
const prefixedName = names.get(baseName);
|
|
26035
26313
|
if (BUILTIN_NAMES.has(prefixedName)) {
|
|
26036
26314
|
if (!reportOwnedMcpLog("warn"))
|
|
26037
26315
|
console.warn(`MCP: skipping direct resource tool "${prefixedName}" (collides with builtin)`);
|
|
@@ -26076,6 +26354,7 @@ var init_direct_tools = __esm(() => {
|
|
|
26076
26354
|
init_diagnostics();
|
|
26077
26355
|
init_metadata_cache();
|
|
26078
26356
|
init_types2();
|
|
26357
|
+
init_tool_names();
|
|
26079
26358
|
init_direct_tool_executor();
|
|
26080
26359
|
BUILTIN_NAMES = new Set(["read", "bash", "edit", "write", "grep", "find", "search", "ls", "mcp"]);
|
|
26081
26360
|
});
|
|
@@ -26580,7 +26859,7 @@ var init_proxy_info_modes = __esm(() => {
|
|
|
26580
26859
|
});
|
|
26581
26860
|
|
|
26582
26861
|
// dist/builtin/mcp/proxy-auth.ts
|
|
26583
|
-
function getAuthRequiredMessage(state, serverName, defaultMessage = `Server "${serverName}" requires OAuth authentication. Run /mcp-auth ${serverName} first.`) {
|
|
26862
|
+
function getAuthRequiredMessage(state, serverName, defaultMessage = providerSignInGuidance(state.config.mcpServers[serverName], serverName) ?? `Server "${serverName}" requires OAuth authentication. Run /mcp-auth ${serverName} first.`) {
|
|
26584
26863
|
return formatAuthRequiredMessage(state.config, serverName, defaultMessage);
|
|
26585
26864
|
}
|
|
26586
26865
|
function getAuthFailedMessage(state, serverName, message) {
|
|
@@ -26619,6 +26898,7 @@ async function attemptAutoAuth(state, serverName) {
|
|
|
26619
26898
|
var init_proxy_auth = __esm(() => {
|
|
26620
26899
|
init_mcp_auth_flow();
|
|
26621
26900
|
init_utils();
|
|
26901
|
+
init_provider_auth();
|
|
26622
26902
|
});
|
|
26623
26903
|
|
|
26624
26904
|
// dist/builtin/mcp/proxy-connect.ts
|
|
@@ -26719,7 +26999,7 @@ async function executeCall(state, toolName, args, serverOverride, getPiTools, si
|
|
|
26719
26999
|
}
|
|
26720
27000
|
}
|
|
26721
27001
|
}
|
|
26722
|
-
if (serverName && !toolMeta) {
|
|
27002
|
+
if (serverName && (!toolMeta || state.manager.getConnection(serverName)?.status === "needs-auth" && isProviderAuth(state.config.mcpServers[serverName]?.auth))) {
|
|
26723
27003
|
const connected = await waitForCaller(() => lazyConnect(state, serverName), signal);
|
|
26724
27004
|
signal?.throwIfAborted();
|
|
26725
27005
|
assertMcpStateLease(assertActive);
|
|
@@ -27086,6 +27366,7 @@ var init_proxy_call = __esm(() => {
|
|
|
27086
27366
|
init_apps_cancellation();
|
|
27087
27367
|
init_state_lease();
|
|
27088
27368
|
init_tool_call_timeout();
|
|
27369
|
+
init_provider_auth();
|
|
27089
27370
|
});
|
|
27090
27371
|
|
|
27091
27372
|
// dist/builtin/mcp/proxy-modes.ts
|
|
@@ -27197,7 +27478,7 @@ import { Type } from "typebox";
|
|
|
27197
27478
|
|
|
27198
27479
|
// dist/builtin/mcp/tool-result-renderer.ts
|
|
27199
27480
|
import { keyText } from "@bastani/atomic";
|
|
27200
|
-
import { Text } from "@earendil-works/pi-tui";
|
|
27481
|
+
import { Text as Text2 } from "@earendil-works/pi-tui";
|
|
27201
27482
|
function blockToLines(block) {
|
|
27202
27483
|
if (block.type === "text") {
|
|
27203
27484
|
return block.text.split(`
|
|
@@ -27218,7 +27499,7 @@ function formatMcpToolResultLines(result, expanded, maxCollapsedLines = 5) {
|
|
|
27218
27499
|
}
|
|
27219
27500
|
function renderMcpToolResult(result, options, theme, context) {
|
|
27220
27501
|
if (options.isPartial) {
|
|
27221
|
-
return new
|
|
27502
|
+
return new Text2(theme.fg("warning", "Running MCP tool..."), 0, 0);
|
|
27222
27503
|
}
|
|
27223
27504
|
const hasErrorDetails = Boolean(result.details.error);
|
|
27224
27505
|
const display = formatMcpToolResultLines(result, options.expanded || context?.isError === true || hasErrorDetails);
|
|
@@ -27227,14 +27508,14 @@ function renderMcpToolResult(result, options, theme, context) {
|
|
|
27227
27508
|
const expandKey = keyText("app.tools.expand");
|
|
27228
27509
|
const hint = display.truncated && !options.expanded && expandKey ? `
|
|
27229
27510
|
${theme.fg("muted", `(${expandKey} Expand)`)}` : "";
|
|
27230
|
-
return new
|
|
27511
|
+
return new Text2(`${output}${hint}`, 0, 0);
|
|
27231
27512
|
}
|
|
27232
27513
|
|
|
27233
27514
|
// dist/builtin/mcp/tool-call-renderer.ts
|
|
27234
27515
|
init_tool_metadata();
|
|
27235
27516
|
init_types2();
|
|
27236
27517
|
import { formatToolCallWithArgs } from "@bastani/atomic";
|
|
27237
|
-
import { stripTerminalSequences, Text as
|
|
27518
|
+
import { stripTerminalSequences, Text as Text3 } from "@earendil-works/pi-tui";
|
|
27238
27519
|
function textArg(value) {
|
|
27239
27520
|
return typeof value === "string" && value.length > 0 ? value : undefined;
|
|
27240
27521
|
}
|
|
@@ -27259,8 +27540,8 @@ function redactArguments(value) {
|
|
|
27259
27540
|
function header(theme, server, operation, args, expanded = false) {
|
|
27260
27541
|
const clean = (value) => stripTerminalSequences(value).replace(/[\r\n\t]/g, " ");
|
|
27261
27542
|
if (server && args && Object.keys(args).length > 0)
|
|
27262
|
-
return new
|
|
27263
|
-
return new
|
|
27543
|
+
return new Text3(formatToolCallWithArgs(`MCP${server ? ` ${clean(server)}` : ""} · ${clean(operation)}`, redactArguments(args), { fg: (name, text) => theme.fg(name, text), bold: (text) => theme.bold?.(text) ?? text }, expanded), 0, 0);
|
|
27544
|
+
return new Text3(theme.fg("toolTitle", `MCP${server ? ` ${clean(server)}` : ""}`) + theme.fg("muted", ` · ${clean(operation)}`), 0, 0);
|
|
27264
27545
|
}
|
|
27265
27546
|
function renderMcpDirectToolCall(server, tool, theme, args, expanded = false) {
|
|
27266
27547
|
return header(theme, server, tool, args, expanded);
|