@bastani/atomic 0.9.25 → 0.9.26-alpha.1
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 +34 -0
- package/dist/builtin/intercom/package.json +2 -2
- package/dist/builtin/mcp/OAUTH.md +1 -1
- package/dist/builtin/mcp/native-client-licenses/NOTICE +2 -2
- package/dist/builtin/mcp/package.json +1 -1
- package/dist/builtin/subagents/package.json +3 -3
- package/dist/builtin/web-access/package.json +2 -2
- package/dist/builtin/workflows/CHANGELOG.md +6 -0
- package/dist/builtin/workflows/package.json +2 -2
- package/dist/builtin/workflows/src/extension/index.bundle.mjs +17 -0
- package/dist/builtin/workflows/src/index.js +15 -0
- package/dist/cli/args.js +1 -1
- package/dist/cli/args.js.map +1 -1
- package/dist/core/agent-session-extension-bindings.d.ts.map +1 -1
- package/dist/core/agent-session-extension-bindings.js +4 -0
- package/dist/core/agent-session-extension-bindings.js.map +1 -1
- package/dist/core/agent-session-methods.d.ts +5 -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-prompt.d.ts.map +1 -1
- package/dist/core/agent-session-prompt.js +1 -0
- package/dist/core/agent-session-prompt.js.map +1 -1
- package/dist/core/agent-session-state.d.ts +14 -2
- package/dist/core/agent-session-state.d.ts.map +1 -1
- package/dist/core/agent-session-state.js +31 -6
- package/dist/core/agent-session-state.js.map +1 -1
- package/dist/core/agent-session-tool-registry.d.ts.map +1 -1
- package/dist/core/agent-session-tool-registry.js +5 -1
- package/dist/core/agent-session-tool-registry.js.map +1 -1
- package/dist/core/agent-session.d.ts +1 -0
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +2 -2
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/messages.d.ts.map +1 -1
- package/dist/core/messages.js +4 -3
- package/dist/core/messages.js.map +1 -1
- package/dist/core/model-registry.d.ts +2 -1
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +3 -0
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/oauth-login.d.ts +1 -0
- package/dist/core/oauth-login.d.ts.map +1 -1
- package/dist/core/oauth-login.js.map +1 -1
- package/dist/core/oauth-provider-metadata.d.ts.map +1 -1
- package/dist/core/oauth-provider-metadata.js +1 -0
- package/dist/core/oauth-provider-metadata.js.map +1 -1
- package/dist/core/settings-manager-resource-accessors.d.ts +3 -3
- package/dist/core/settings-manager-resource-accessors.d.ts.map +1 -1
- package/dist/core/settings-manager-resource-accessors.js +2 -1
- package/dist/core/settings-manager-resource-accessors.js.map +1 -1
- package/dist/core/settings-manager.d.ts +1 -1
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/settings-types.d.ts +2 -1
- package/dist/core/settings-types.d.ts.map +1 -1
- package/dist/core/settings-types.js.map +1 -1
- package/dist/core/system-prompt.js +1 -1
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/extensions/codemode/execute.d.ts.map +1 -1
- package/dist/extensions/codemode/execute.js +133 -31
- package/dist/extensions/codemode/execute.js.map +1 -1
- package/dist/extensions/codemode/tool.d.ts +2 -1
- package/dist/extensions/codemode/tool.d.ts.map +1 -1
- package/dist/extensions/codemode/tool.js +25 -4
- package/dist/extensions/codemode/tool.js.map +1 -1
- package/dist/extensions/mcp/cli.js +2 -2
- package/dist/extensions/mcp/cli.js.map +1 -1
- package/dist/extensions/mcp/client/oauth/flow.d.ts +6 -0
- package/dist/extensions/mcp/client/oauth/flow.d.ts.map +1 -1
- package/dist/extensions/mcp/client/oauth/flow.js +23 -5
- package/dist/extensions/mcp/client/oauth/flow.js.map +1 -1
- package/dist/extensions/mcp/client/oauth/index.d.ts +1 -1
- package/dist/extensions/mcp/client/oauth/index.d.ts.map +1 -1
- package/dist/extensions/mcp/client/oauth/index.js +1 -1
- package/dist/extensions/mcp/client/oauth/index.js.map +1 -1
- package/dist/extensions/mcp/index.d.ts.map +1 -1
- package/dist/extensions/mcp/index.js +22 -12
- package/dist/extensions/mcp/index.js.map +1 -1
- package/dist/extensions/mcp/oauth.d.ts +12 -7
- package/dist/extensions/mcp/oauth.d.ts.map +1 -1
- package/dist/extensions/mcp/oauth.js +58 -24
- package/dist/extensions/mcp/oauth.js.map +1 -1
- package/dist/extensions/mcp/runtime.js +1 -1
- package/dist/extensions/mcp/runtime.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/main-session-options.d.ts.map +1 -1
- package/dist/main-session-options.js +6 -0
- package/dist/main-session-options.js.map +1 -1
- package/dist/main.js +1 -1
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/components/atomic-banner.d.ts +2 -0
- package/dist/modes/interactive/components/atomic-banner.d.ts.map +1 -1
- package/dist/modes/interactive/components/atomic-banner.js +9 -1
- package/dist/modes/interactive/components/atomic-banner.js.map +1 -1
- package/dist/modes/interactive/components/oauth-selector.d.ts +2 -0
- package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/oauth-selector.js +9 -4
- package/dist/modes/interactive/components/oauth-selector.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector-handlers.js +1 -1
- package/dist/modes/interactive/components/settings-selector-handlers.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector-items.js +3 -3
- package/dist/modes/interactive/components/settings-selector-items.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector-types.d.ts +3 -3
- package/dist/modes/interactive/components/settings-selector-types.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector-types.js.map +1 -1
- package/dist/modes/interactive/components/startup-identity.js +2 -2
- package/dist/modes/interactive/components/startup-identity.js.map +1 -1
- package/dist/modes/interactive/components/user-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/user-message.js +3 -4
- package/dist/modes/interactive/components/user-message.js.map +1 -1
- package/dist/modes/interactive/interactive-auth-login.js +14 -5
- package/dist/modes/interactive/interactive-auth-login.js.map +1 -1
- package/dist/modes/interactive/interactive-auth-routing.js +38 -17
- package/dist/modes/interactive/interactive-auth-routing.js.map +1 -1
- package/dist/modes/interactive/interactive-mode-surface.d.ts +6 -4
- package/dist/modes/interactive/interactive-mode-surface.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode-surface.js.map +1 -1
- package/dist/modes/interactive/interactive-resource-rendering.js +1 -1
- package/dist/modes/interactive/interactive-resource-rendering.js.map +1 -1
- package/dist/modes/interactive/interactive-selectors.js +2 -2
- package/dist/modes/interactive/interactive-selectors.js.map +1 -1
- package/dist/modes/interactive/interactive-startup.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-startup.js +12 -4
- package/dist/modes/interactive/interactive-startup.js.map +1 -1
- package/dist/modes/interactive/login-provider-options.d.ts +2 -1
- package/dist/modes/interactive/login-provider-options.d.ts.map +1 -1
- package/dist/modes/interactive/login-provider-options.js +11 -6
- package/dist/modes/interactive/login-provider-options.js.map +1 -1
- package/dist/modes/interactive/theme/system-theme.d.ts.map +1 -1
- package/dist/modes/interactive/theme/system-theme.js +10 -4
- package/dist/modes/interactive/theme/system-theme.js.map +1 -1
- package/docs/codemode.md +214 -0
- package/docs/docs.json +1 -0
- package/docs/extensions/api-reference.md +2 -0
- package/docs/getting-started/authentication.md +2 -2
- package/docs/guides.md +1 -1
- package/docs/mcp-servers.md +2 -0
- package/docs/providers.md +5 -3
- package/docs/reference/cli.md +1 -1
- package/docs/settings.md +1 -1
- package/docs/terminal-setup.md +2 -0
- package/docs/tools.md +1 -3
- package/docs/usage.md +1 -1
- package/npm-shrinkwrap.json +68 -73
- package/package.json +8 -8
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* `McpOAuthAuthorizationRequiredError`, and the user signs in through `/mcp`, which runs
|
|
7
7
|
* the authorization code flow (PKCE, dynamic client registration) against a loopback callback.
|
|
8
8
|
*
|
|
9
|
-
* Credentials live in `<agent-dir>/mcp-auth.json`, keyed by server URL.
|
|
9
|
+
* Credentials live in `<agent-dir>/mcp-auth.json`, keyed by server name and URL.
|
|
10
10
|
*/
|
|
11
11
|
import { createHash, randomUUID } from "node:crypto";
|
|
12
12
|
import { mkdirSync } from "node:fs";
|
|
@@ -15,7 +15,8 @@ import { oauthErrorHtml, oauthSuccessHtml } from "@bastani/pi-ai/utils/oauth-pag
|
|
|
15
15
|
import lockfile from "proper-lockfile";
|
|
16
16
|
import { APP_NAME, getAgentDir } from "../../config.js";
|
|
17
17
|
import { FileAuthStorageBackend } from "../../core/auth-storage.js";
|
|
18
|
-
import {
|
|
18
|
+
import { mcpNamespace } from "../../core/mcp-servers.js";
|
|
19
|
+
import { authorizeMcp, McpOAuthAuthorizationRequiredError, McpOAuthProvider, OAuthCallbackServer, parseWwwAuthenticate, stepUpScope, } from "./client/oauth/index.js";
|
|
19
20
|
const CALLBACK_HOST = "127.0.0.1";
|
|
20
21
|
const CALLBACK_PATH = "/callback";
|
|
21
22
|
/** Redirect URI for refreshes when none is stored. Refreshing never redirects the user. */
|
|
@@ -62,6 +63,17 @@ function parseStates(content) {
|
|
|
62
63
|
const parsed = JSON.parse(content);
|
|
63
64
|
return typeof parsed === "object" && parsed !== null && !Array.isArray(parsed) ? parsed : {};
|
|
64
65
|
}
|
|
66
|
+
function serializeStates(states) {
|
|
67
|
+
return `${JSON.stringify(states, null, 2)}\n`;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Keys of a server's state: by name and URL, so servers sharing a URL keep separate accounts, and the
|
|
71
|
+
* legacy key by URL alone, written by older versions.
|
|
72
|
+
*/
|
|
73
|
+
function storeKeys(name, serverUrl) {
|
|
74
|
+
const legacyKey = String(new URL(serverUrl));
|
|
75
|
+
return { key: `${mcpNamespace(name)}|${legacyKey}`, legacyKey };
|
|
76
|
+
}
|
|
65
77
|
/** Per-server OAuth state (client registration, tokens, pending PKCE verifier) in `mcp-auth.json`. */
|
|
66
78
|
export class McpOAuthCredentialStore {
|
|
67
79
|
backend;
|
|
@@ -71,17 +83,18 @@ export class McpOAuthCredentialStore {
|
|
|
71
83
|
this.backend = backend ?? new FileAuthStorageBackend(join(getAgentDir(), "mcp-auth.json"));
|
|
72
84
|
this.lockDir = backend ? lockDir : getAgentDir();
|
|
73
85
|
}
|
|
74
|
-
forServer(serverUrl) {
|
|
75
|
-
const key =
|
|
86
|
+
forServer(name, serverUrl) {
|
|
87
|
+
const { key, legacyKey } = storeKeys(name, serverUrl);
|
|
76
88
|
const scoped = (fenced) => {
|
|
77
|
-
const
|
|
89
|
+
const initial = this.read();
|
|
90
|
+
const generation = (initial[key] ?? initial[legacyKey])?.credentialGeneration;
|
|
78
91
|
const check = (state) => {
|
|
79
92
|
if (fenced && state?.credentialGeneration !== generation)
|
|
80
93
|
throw new McpSignInCancelledError();
|
|
81
94
|
};
|
|
82
95
|
return {
|
|
83
96
|
load: () => {
|
|
84
|
-
const state = this.
|
|
97
|
+
const state = this.claimLegacy(key, legacyKey)[key];
|
|
85
98
|
check(state);
|
|
86
99
|
if (!state)
|
|
87
100
|
return undefined;
|
|
@@ -145,25 +158,44 @@ export class McpOAuthCredentialStore {
|
|
|
145
158
|
await release().catch(() => undefined);
|
|
146
159
|
}
|
|
147
160
|
}
|
|
148
|
-
/** The
|
|
149
|
-
|
|
150
|
-
return this.
|
|
161
|
+
/** The first server to load legacy state takes it over; others with the same URL sign in again. */
|
|
162
|
+
claimLegacy(key, legacyKey) {
|
|
163
|
+
return this.backend.withLock((current) => {
|
|
164
|
+
const states = parseStates(current);
|
|
165
|
+
if (states[key] || !states[legacyKey])
|
|
166
|
+
return { result: states };
|
|
167
|
+
states[key] = states[legacyKey];
|
|
168
|
+
delete states[legacyKey];
|
|
169
|
+
return { result: states, next: serializeStates(states) };
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
/** The stored tokens of a server, for noticing sign-ins done by another process. Does not take over legacy state. */
|
|
173
|
+
tokens(name, serverUrl) {
|
|
174
|
+
const { key, legacyKey } = storeKeys(name, serverUrl);
|
|
175
|
+
const states = this.read();
|
|
176
|
+
return (states[key] ?? states[legacyKey])?.tokens;
|
|
151
177
|
}
|
|
152
178
|
/** Serialized logout: waits for rotated tokens to be saved before revoking the grant. */
|
|
153
|
-
removeAsync(serverUrl) {
|
|
154
|
-
const key =
|
|
155
|
-
return this.withRefreshLock(key, async () => this.remove(
|
|
179
|
+
removeAsync(name, serverUrl) {
|
|
180
|
+
const { key } = storeKeys(name, serverUrl);
|
|
181
|
+
return this.withRefreshLock(key, async () => this.remove(name, serverUrl));
|
|
156
182
|
}
|
|
157
|
-
/**
|
|
158
|
-
|
|
159
|
-
|
|
183
|
+
/**
|
|
184
|
+
* Synchronous revocation also fences late writes; logout callers should prefer removeAsync. Also removes
|
|
185
|
+
* legacy state the server would take over.
|
|
186
|
+
*/
|
|
187
|
+
remove(name, serverUrl) {
|
|
188
|
+
const { key, legacyKey } = storeKeys(name, serverUrl);
|
|
189
|
+
const hasCredentials = (state) => state !== undefined &&
|
|
190
|
+
Object.keys(state).some((field) => field !== "serverUrl" && field !== "credentialGeneration");
|
|
160
191
|
let removed = false;
|
|
161
192
|
this.write((states) => {
|
|
162
|
-
const
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
193
|
+
const own = states[key];
|
|
194
|
+
const legacy = own === undefined ? states[legacyKey] : undefined;
|
|
195
|
+
removed = hasCredentials(own) || hasCredentials(legacy);
|
|
196
|
+
if (legacy)
|
|
197
|
+
delete states[legacyKey];
|
|
198
|
+
states[key] = { serverUrl: legacyKey, credentialGeneration: randomUUID() };
|
|
167
199
|
});
|
|
168
200
|
return removed;
|
|
169
201
|
}
|
|
@@ -174,7 +206,7 @@ export class McpOAuthCredentialStore {
|
|
|
174
206
|
this.backend.withLock((current) => {
|
|
175
207
|
const states = parseStates(current);
|
|
176
208
|
update(states);
|
|
177
|
-
return { result: undefined, next:
|
|
209
|
+
return { result: undefined, next: serializeStates(states) };
|
|
178
210
|
});
|
|
179
211
|
}
|
|
180
212
|
}
|
|
@@ -334,6 +366,7 @@ export async function signInMcpServer(options) {
|
|
|
334
366
|
const { serverUrl, settings } = options;
|
|
335
367
|
const store = options.store.fenced();
|
|
336
368
|
const stored = await store.load();
|
|
369
|
+
const stepUp = options.challenge?.error === "insufficient_scope";
|
|
337
370
|
const callbackOptions = callbackSettings(settings);
|
|
338
371
|
// Reuse the port of the registered redirect URI so the registered client stays valid.
|
|
339
372
|
const registered = registeredRedirectUrls(stored?.clientInformation)[0];
|
|
@@ -361,11 +394,12 @@ export async function signInMcpServer(options) {
|
|
|
361
394
|
serverUrl,
|
|
362
395
|
resourceMetadataUrl: options.challenge?.resourceMetadataUrl,
|
|
363
396
|
authorizationServerMetadataUrl: settings.authServerMetadataUrl,
|
|
364
|
-
// A server asking for more scope gets it on top of the configured scope
|
|
365
|
-
|
|
397
|
+
// A server asking for more scope gets it on top of the configured scope and, since the challenge
|
|
398
|
+
// may list only the missing scopes, on top of the scope granted so far.
|
|
399
|
+
scope: mergeScopes(settings.scope, stepUp ? stepUpScope(stored?.tokens?.scope, options.challenge?.scope) : options.challenge?.scope),
|
|
366
400
|
};
|
|
367
401
|
// A refresh keeps the granted scope; a server asking for more needs the browser flow.
|
|
368
|
-
const skipRefresh =
|
|
402
|
+
const skipRefresh = stepUp;
|
|
369
403
|
if ((await authorizeMcp(provider, { ...flow, skipRefresh })) === "AUTHORIZED")
|
|
370
404
|
return;
|
|
371
405
|
if (!authorizationUrl)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oauth.js","sourceRoot":"","sources":["../../../src/extensions/mcp/oauth.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * OAuth sign-in for remote MCP servers.\n *\n * Connections never start a browser flow on their own. They send the stored access token and, after\n * a 401, try the stored refresh token. When that is not possible they fail with\n * `McpOAuthAuthorizationRequiredError`, and the user signs in through `/mcp`, which runs\n * the authorization code flow (PKCE, dynamic client registration) against a loopback callback.\n *\n * Credentials live in `<agent-dir>/mcp-auth.json`, keyed by server URL.\n */\n\nimport { createHash, randomUUID } from \"node:crypto\";\nimport { mkdirSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { oauthErrorHtml, oauthSuccessHtml } from \"@bastani/pi-ai/utils/oauth-page\";\nimport lockfile from \"proper-lockfile\";\nimport { APP_NAME, getAgentDir } from \"../../config.js\";\nimport { type AuthStorageBackend, FileAuthStorageBackend } from \"../../core/auth-storage.ts\";\nimport type { AuthProvider, McpFetch } from \"./client/index.js\";\nimport {\n\tauthorizeMcp,\n\tMcpOAuthAuthorizationRequiredError,\n\tMcpOAuthProvider,\n\ttype McpOAuthState,\n\ttype McpOAuthStateStore,\n\ttype OAuthCallback,\n\ttype OAuthCallbackPage,\n\tOAuthCallbackServer,\n\ttype OAuthChallenge,\n\ttype OAuthClientInformationMixed,\n\tparseWwwAuthenticate,\n} from \"./client/oauth/index.js\";\n\nconst CALLBACK_HOST = \"127.0.0.1\";\nconst CALLBACK_PATH = \"/callback\";\n/** Redirect URI for refreshes when none is stored. Refreshing never redirects the user. */\nconst FALLBACK_REDIRECT_URL = `http://${CALLBACK_HOST}${CALLBACK_PATH}`;\n/** Access tokens this close to expiry are refreshed before they are sent. */\nconst REFRESH_SKEW_MS = 30_000;\n/** Bounds each request of a refresh, so it cannot hold the refresh lock or delay shutdown for long. */\nconst REFRESH_REQUEST_TIMEOUT_MS = 15_000;\n/** A refresh lock that its holder stopped renewing (the process was killed) is taken over after this. */\nconst REFRESH_LOCK_STALE_MS = 20_000;\n/** How long to wait for another process's refresh: longer than a stale lock lives. */\nconst REFRESH_LOCK_WAIT_MS = 25_000;\nconst REFRESH_LOCK_RETRY_MS = 100;\n\nexport interface McpOAuthSettings {\n\tclientId?: string;\n\t/** Already resolved. */\n\tclientSecret?: string;\n\tcallbackPort?: number;\n\t/** Loopback redirect URI; see `McpOAuthConfig.callbackUrl`. */\n\tcallbackUrl?: string;\n\t/** Scopes to request, separated by spaces. */\n\tscope?: string;\n\t/** `client_name` for dynamic client registration. Default: `APP_NAME`. */\n\tclientName?: string;\n\t/** See `McpOAuthConfig.authServerMetadataUrl`. */\n\tauthServerMetadataUrl?: URL;\n}\n\n/** Where the loopback callback server listens and the redirect URI it serves. */\ninterface CallbackSettings {\n\t/** Address to listen on. */\n\thost: string;\n\t/** Host name in the redirect URI. */\n\tredirectHost: string;\n\tport: number | undefined;\n\tpath: string;\n\t/** The exact redirect URI, when the port is fixed. */\n\tfixedRedirectUrl: string | undefined;\n}\n\nfunction callbackSettings(settings: McpOAuthSettings): CallbackSettings {\n\tconst url = new URL(settings.callbackUrl ?? `http://${CALLBACK_HOST}${CALLBACK_PATH}`);\n\tconst address = url.hostname.replace(/^\\[|\\]$/g, \"\");\n\tconst port = url.port ? Number(url.port) : settings.callbackPort;\n\tlet fixedRedirectUrl: string | undefined;\n\t// A configured URI with a port is sent exactly as written, since servers compare it as a string.\n\tif (url.port) fixedRedirectUrl = settings.callbackUrl;\n\telse if (port !== undefined) {\n\t\turl.port = String(port);\n\t\tfixedRedirectUrl = url.href;\n\t}\n\treturn {\n\t\t// `localhost` is served on 127.0.0.1; browsers fall back to it when ::1 refuses.\n\t\thost: address === \"localhost\" ? CALLBACK_HOST : address,\n\t\tredirectHost: address,\n\t\tport,\n\t\tpath: url.pathname,\n\t\tfixedRedirectUrl,\n\t};\n}\n\n/** Scopes of both lists, each once. */\nfunction mergeScopes(...scopes: (string | undefined)[]): string | undefined {\n\tconst merged = [...new Set(scopes.flatMap((scope) => scope?.split(/\\s+/).filter(Boolean) ?? []))];\n\treturn merged.length > 0 ? merged.join(\" \") : undefined;\n}\n\n// A token-free tombstone keeps revocation durable, including for other processes' late sign-ins.\ntype StoredState = McpOAuthState & { credentialGeneration?: string };\ntype StoredStates = Record<string, StoredState>;\nconst refreshQueues = new WeakMap<AuthStorageBackend, Map<string, Promise<unknown>>>();\n\nfunction parseStates(content: string | undefined): StoredStates {\n\tif (!content?.trim()) return {};\n\tconst parsed: unknown = JSON.parse(content);\n\treturn typeof parsed === \"object\" && parsed !== null && !Array.isArray(parsed) ? (parsed as StoredStates) : {};\n}\n\nexport interface McpOAuthServerStore extends McpOAuthStateStore {\n\t/** Run `fn` while no other process refreshes the server's tokens. */\n\twithRefreshLock<T>(fn: () => Promise<T>): Promise<T>;\n\t/** Capture ownership for one flow; logout invalidates its subsequent reads and writes. */\n\tfenced(): McpOAuthStateStore;\n}\n\n/** Per-server OAuth state (client registration, tokens, pending PKCE verifier) in `mcp-auth.json`. */\nexport class McpOAuthCredentialStore {\n\tprivate readonly backend: AuthStorageBackend;\n\t/** Directory for the refresh lock files. Without one, refreshes are only serialized in this process. */\n\tprivate readonly lockDir: string | undefined;\n\n\tconstructor(backend?: AuthStorageBackend, lockDir?: string) {\n\t\tthis.backend = backend ?? new FileAuthStorageBackend(join(getAgentDir(), \"mcp-auth.json\"));\n\t\tthis.lockDir = backend ? lockDir : getAgentDir();\n\t}\n\n\tforServer(serverUrl: string): McpOAuthServerStore {\n\t\tconst key = String(new URL(serverUrl));\n\t\tconst scoped = (fenced: boolean): McpOAuthStateStore => {\n\t\t\tconst generation = this.read()[key]?.credentialGeneration;\n\t\t\tconst check = (state: StoredState | undefined) => {\n\t\t\t\tif (fenced && state?.credentialGeneration !== generation) throw new McpSignInCancelledError();\n\t\t\t};\n\t\t\treturn {\n\t\t\t\tload: () => {\n\t\t\t\t\tconst state = this.read()[key];\n\t\t\t\t\tcheck(state);\n\t\t\t\t\tif (!state) return undefined;\n\t\t\t\t\tconst { credentialGeneration: _generation, ...value } = state;\n\t\t\t\t\treturn Object.keys(value).length > 1 ? value : undefined;\n\t\t\t\t},\n\t\t\t\tsave: (state) =>\n\t\t\t\t\tthis.write((states) => {\n\t\t\t\t\t\tcheck(states[key]);\n\t\t\t\t\t\tstates[key] = { ...state, credentialGeneration: states[key]?.credentialGeneration };\n\t\t\t\t\t}),\n\t\t\t};\n\t\t};\n\t\treturn {\n\t\t\t...scoped(false),\n\t\t\tfenced: () => scoped(true),\n\t\t\twithRefreshLock: (fn) => this.withRefreshLock(key, fn),\n\t\t};\n\t}\n\n\t/**\n\t * A lock file per server. When the process exits, proper-lockfile removes the locks it holds; when\n\t * it is killed, the lock goes stale because it is no longer renewed, and the next process takes it over.\n\t */\n\tprivate async withRefreshLock<T>(key: string, fn: () => Promise<T>): Promise<T> {\n\t\tlet queues = refreshQueues.get(this.backend);\n\t\tif (!queues) {\n\t\t\tqueues = new Map();\n\t\t\trefreshQueues.set(this.backend, queues);\n\t\t}\n\t\tconst previous = queues.get(key) ?? Promise.resolve();\n\t\tconst running = previous.catch(() => undefined).then(() => this.withFileRefreshLock(key, fn));\n\t\tqueues.set(key, running);\n\t\ttry {\n\t\t\treturn await running;\n\t\t} finally {\n\t\t\tif (queues.get(key) === running) queues.delete(key);\n\t\t}\n\t}\n\n\tprivate async withFileRefreshLock<T>(key: string, fn: () => Promise<T>): Promise<T> {\n\t\tif (!this.lockDir) return fn();\n\t\tmkdirSync(this.lockDir, { recursive: true, mode: 0o700 });\n\t\tconst hash = createHash(\"sha256\").update(key).digest(\"hex\").slice(0, 16);\n\t\tconst release = await lockfile.lock(join(this.lockDir, `mcp-auth-refresh-${hash}`), {\n\t\t\trealpath: false,\n\t\t\tstale: REFRESH_LOCK_STALE_MS,\n\t\t\tretries: {\n\t\t\t\tretries: REFRESH_LOCK_WAIT_MS / REFRESH_LOCK_RETRY_MS,\n\t\t\t\tfactor: 1,\n\t\t\t\tminTimeout: REFRESH_LOCK_RETRY_MS,\n\t\t\t\tmaxTimeout: REFRESH_LOCK_RETRY_MS,\n\t\t\t},\n\t\t\t// The default throws from a timer. A lost lock at worst lets two refreshes overlap.\n\t\t\tonCompromised: () => {},\n\t\t});\n\t\ttry {\n\t\t\treturn await fn();\n\t\t} finally {\n\t\t\tawait release().catch(() => undefined);\n\t\t}\n\t}\n\n\t/** The stored tokens of a server, for noticing sign-ins done by another process. */\n\ttokens(serverUrl: string): McpOAuthState[\"tokens\"] {\n\t\treturn this.read()[String(new URL(serverUrl))]?.tokens;\n\t}\n\n\t/** Serialized logout: waits for rotated tokens to be saved before revoking the grant. */\n\tremoveAsync(serverUrl: string): Promise<boolean> {\n\t\tconst key = String(new URL(serverUrl));\n\t\treturn this.withRefreshLock(key, async () => this.remove(key));\n\t}\n\n\t/** Synchronous revocation also fences late writes; logout callers should prefer removeAsync. */\n\tremove(serverUrl: string): boolean {\n\t\tconst key = String(new URL(serverUrl));\n\t\tlet removed = false;\n\t\tthis.write((states) => {\n\t\t\tconst state = states[key];\n\t\t\tremoved =\n\t\t\t\tstate !== undefined &&\n\t\t\t\tObject.keys(state).some((field) => field !== \"serverUrl\" && field !== \"credentialGeneration\");\n\t\t\tstates[key] = { serverUrl: key, credentialGeneration: randomUUID() };\n\t\t});\n\t\treturn removed;\n\t}\n\n\tprivate read(): StoredStates {\n\t\treturn this.backend.withLock((current) => ({ result: parseStates(current) }));\n\t}\n\n\tprivate write(update: (states: StoredStates) => void): void {\n\t\tthis.backend.withLock((current) => {\n\t\t\tconst states = parseStates(current);\n\t\t\tupdate(states);\n\t\t\treturn { result: undefined, next: `${JSON.stringify(states, null, 2)}\\n` };\n\t\t});\n\t}\n}\n\nfunction registeredRedirectUrls(client: OAuthClientInformationMixed | undefined): string[] {\n\treturn client && \"redirect_uris\" in client ? client.redirect_uris : [];\n}\n\nfunction createProvider(\n\tserverUrl: string,\n\tstore: McpOAuthStateStore,\n\tsettings: McpOAuthSettings,\n\tredirectUrl: string,\n\tonRedirect: (url: URL) => void,\n): McpOAuthProvider {\n\treturn new McpOAuthProvider({\n\t\tserverUrl,\n\t\tredirectUrl,\n\t\tclientMetadata: { client_name: settings.clientName ?? APP_NAME },\n\t\tclientId: settings.clientId,\n\t\tclientSecret: settings.clientSecret,\n\t\tstore,\n\t\tonRedirect,\n\t});\n}\n\nexport interface McpAuthProvider extends AuthProvider {\n\t/** Resolves when no refresh is running, so shutdown does not drop rotated tokens before they are saved. */\n\tsettled(): Promise<void>;\n}\n\n/**\n * Auth provider for MCP connections: sends the stored access token and refreshes it when it is about\n * to expire or after a 401. Throws `McpOAuthAuthorizationRequiredError` when the user has to sign in,\n * including when the server asks for more scope (`insufficient_scope`). `onChallenge` receives the\n * server's `WWW-Authenticate` challenge so sign-in can use its resource metadata URL and scope.\n * `settings` is only called when a refresh is needed, so a secret that fails to resolve fails the\n * refresh instead of the whole connection setup.\n *\n * Many servers rotate refresh tokens, so two refreshes with the same refresh token lose the grant.\n * Requests in this process share one refresh, and other processes are kept out by the store's\n * refresh lock, held from reading the tokens to saving new ones. Tokens that changed meanwhile\n * (another process refreshed them, or the user signed in) are used without refreshing.\n */\nexport function createMcpAuthProvider(options: {\n\tserverUrl: string;\n\tstore: McpOAuthServerStore;\n\tsettings: () => McpOAuthSettings;\n\tonChallenge: (challenge: OAuthChallenge) => void;\n}): McpAuthProvider {\n\tconst { serverUrl, store } = options;\n\tlet refreshing: Promise<void> | undefined;\n\n\t/** Replace `staleToken`, the access token that expired or was rejected. */\n\tconst refresh = (staleToken: string | undefined, fetch: McpFetch = globalThis.fetch, challenge?: OAuthChallenge) => {\n\t\trefreshing ??= store\n\t\t\t.withRefreshLock(async () => {\n\t\t\t\tconst flowStore = store.fenced();\n\t\t\t\tconst state = await flowStore.load();\n\t\t\t\tif (state?.tokens?.access_token !== staleToken) return;\n\t\t\t\tif (!state?.tokens?.refresh_token) throw new McpOAuthAuthorizationRequiredError();\n\t\t\t\tconst settings = options.settings();\n\t\t\t\tconst redirectUrl =\n\t\t\t\t\tcallbackSettings(settings).fixedRedirectUrl ??\n\t\t\t\t\tregisteredRedirectUrls(state.clientInformation)[0] ??\n\t\t\t\t\tFALLBACK_REDIRECT_URL;\n\t\t\t\tconst provider = createProvider(serverUrl, flowStore, settings, redirectUrl, () => {});\n\t\t\t\t// Refreshes the tokens, or reports that a new sign-in is needed.\n\t\t\t\tconst result = await authorizeMcp(provider, {\n\t\t\t\t\tserverUrl,\n\t\t\t\t\tresourceMetadataUrl: challenge?.resourceMetadataUrl,\n\t\t\t\t\tauthorizationServerMetadataUrl: settings.authServerMetadataUrl,\n\t\t\t\t\tscope: challenge?.scope,\n\t\t\t\t\tfetch: (input, init) =>\n\t\t\t\t\t\tfetch(input, { ...init, signal: AbortSignal.timeout(REFRESH_REQUEST_TIMEOUT_MS) }),\n\t\t\t\t});\n\t\t\t\tif (result === \"REDIRECT\") throw new McpOAuthAuthorizationRequiredError();\n\t\t\t})\n\t\t\t.finally(() => {\n\t\t\t\trefreshing = undefined;\n\t\t\t});\n\t\treturn refreshing;\n\t};\n\n\treturn {\n\t\ttoken: async () => {\n\t\t\tawait refreshing?.catch(() => undefined);\n\t\t\tconst state = await store.load();\n\t\t\tconst token = state?.tokens?.access_token;\n\t\t\tconst expired = state?.tokensExpireAt !== undefined && state.tokensExpireAt - REFRESH_SKEW_MS <= Date.now();\n\t\t\tif (!expired || !state?.tokens?.refresh_token) return token;\n\t\t\t// Failures fall through: the request goes out with the old token and a 401 decides what happens.\n\t\t\tawait refresh(token).catch(() => undefined);\n\t\t\treturn (await store.load())?.tokens?.access_token;\n\t\t},\n\t\tonUnauthorized: async (context) => {\n\t\t\tconst challenge = parseWwwAuthenticate(context.response.headers.get(\"www-authenticate\"));\n\t\t\toptions.onChallenge(challenge);\n\t\t\t// A refresh keeps the granted scope, so more scope needs a new sign-in.\n\t\t\tif (challenge.error === \"insufficient_scope\") throw new McpOAuthAuthorizationRequiredError();\n\t\t\tawait refresh(context.token, context.fetch, challenge);\n\t\t},\n\t\tsettled: async () => {\n\t\t\tawait refreshing?.catch(() => undefined);\n\t\t},\n\t};\n}\n\nexport interface McpSignInPrompt {\n\t/** Show the authorization URL to the user and open it in a browser. */\n\tshowAuthorizationUrl(url: URL): void;\n\t/**\n\t * Ask for the redirect URL from the browser address bar, for when the browser cannot reach the\n\t * loopback callback (for example over SSH). Aborted once the callback arrives. Resolves to\n\t * `undefined` or an empty string when the user cancels.\n\t */\n\tpromptForRedirectUrl(signal: AbortSignal): Promise<string | undefined>;\n}\n\nexport class McpSignInCancelledError extends Error {\n\tconstructor() {\n\t\tsuper(\"Sign-in cancelled\");\n\t\tthis.name = \"McpSignInCancelledError\";\n\t}\n}\n\ntype AuthorizationResponse = Pick<OAuthCallback, \"code\" | \"iss\">;\n\nfunction responseFromRedirectUrl(input: string, state: string): AuthorizationResponse {\n\tlet url: URL;\n\ttry {\n\t\turl = new URL(input.trim());\n\t} catch {\n\t\tthrow new Error(\"Expected the full redirect URL from the browser address bar\");\n\t}\n\tconst error = url.searchParams.get(\"error\");\n\tif (error) throw new Error(url.searchParams.get(\"error_description\") ?? error);\n\tif (url.searchParams.get(\"state\") !== state) throw new Error(\"The redirect URL belongs to a different sign-in\");\n\tconst code = url.searchParams.get(\"code\");\n\tif (!code) throw new Error(\"The redirect URL does not contain an authorization code\");\n\treturn { code, iss: url.searchParams.get(\"iss\") ?? undefined };\n}\n\n/** Wait for the browser callback or a pasted redirect URL, whichever comes first. */\nasync function waitForAuthorizationResponse(\n\tcallback: OAuthCallbackServer,\n\tstate: string,\n\tprompt: McpSignInPrompt,\n): Promise<AuthorizationResponse> {\n\tconst controller = new AbortController();\n\tconst fromBrowser = callback.waitForCallback(state);\n\tconst fromUser = prompt.promptForRedirectUrl(controller.signal).then((input) => {\n\t\tif (!input?.trim()) throw new McpSignInCancelledError();\n\t\treturn responseFromRedirectUrl(input, state);\n\t});\n\ttry {\n\t\treturn await Promise.race([fromBrowser, fromUser]);\n\t} finally {\n\t\t// The losing side rejects once the prompt is aborted or the callback server closes.\n\t\tcontroller.abort();\n\t\tfromBrowser.catch(() => undefined);\n\t\tfromUser.catch(() => undefined);\n\t}\n}\n\n/** Listen on `port`, or on a free port when it is taken and not `required`. */\nasync function listenForCallback(\n\tsettings: CallbackSettings,\n\tport: number | undefined,\n\trequired: boolean,\n): Promise<OAuthCallbackServer> {\n\tconst options = {\n\t\thost: settings.host,\n\t\tredirectHost: settings.redirectHost,\n\t\tpath: settings.path,\n\t\trenderPage: (page: OAuthCallbackPage) =>\n\t\t\tpage.ok\n\t\t\t\t? oauthSuccessHtml(\"Signed in to the MCP server. You may now close this page.\")\n\t\t\t\t: oauthErrorHtml(page.message, page.details),\n\t};\n\ttry {\n\t\treturn await OAuthCallbackServer.listen({ ...options, port: port ?? 0 });\n\t} catch (error) {\n\t\tif (required || port === undefined) throw error;\n\t\treturn OAuthCallbackServer.listen(options);\n\t}\n}\n\n/**\n * Sign in to an MCP server. Uses the stored refresh token when possible; otherwise runs the browser\n * authorization code flow. Tokens are saved to `store`.\n */\nexport async function signInMcpServer(options: {\n\tserverUrl: string;\n\tstore: McpOAuthServerStore;\n\tsettings: McpOAuthSettings;\n\tchallenge?: OAuthChallenge;\n\tprompt: McpSignInPrompt;\n}): Promise<void> {\n\tconst { serverUrl, settings } = options;\n\tconst store = options.store.fenced();\n\tconst stored = await store.load();\n\tconst callbackOptions = callbackSettings(settings);\n\t// Reuse the port of the registered redirect URI so the registered client stays valid.\n\tconst registered = registeredRedirectUrls(stored?.clientInformation)[0];\n\tconst preferredPort =\n\t\tcallbackOptions.port ?? (registered ? Number(new URL(registered).port) || undefined : undefined);\n\tconst callback = await listenForCallback(callbackOptions, preferredPort, callbackOptions.port !== undefined);\n\tconst redirectUrl = callbackOptions.fixedRedirectUrl ?? callback.redirectUrl;\n\ttry {\n\t\tif (stored) {\n\t\t\tconst next: McpOAuthState = { ...stored };\n\t\t\t// Every sign-in gets a fresh `state` parameter.\n\t\t\tdelete next.oauthState;\n\t\t\t// A registered client cannot use another redirect URI, and its tokens belong to it.\n\t\t\tif (!settings.clientId && !registeredRedirectUrls(stored.clientInformation).includes(redirectUrl)) {\n\t\t\t\tdelete next.clientInformation;\n\t\t\t\tdelete next.tokens;\n\t\t\t\tdelete next.tokensExpireAt;\n\t\t\t}\n\t\t\tawait store.save(next);\n\t\t}\n\n\t\tlet authorizationUrl: URL | undefined;\n\t\tconst provider = createProvider(serverUrl, store, settings, redirectUrl, (url) => {\n\t\t\tauthorizationUrl = url;\n\t\t});\n\t\tconst flow = {\n\t\t\tserverUrl,\n\t\t\tresourceMetadataUrl: options.challenge?.resourceMetadataUrl,\n\t\t\tauthorizationServerMetadataUrl: settings.authServerMetadataUrl,\n\t\t\t// A server asking for more scope gets it on top of the configured scope.\n\t\t\tscope: mergeScopes(settings.scope, options.challenge?.scope),\n\t\t};\n\t\t// A refresh keeps the granted scope; a server asking for more needs the browser flow.\n\t\tconst skipRefresh = options.challenge?.error === \"insufficient_scope\";\n\t\tif ((await authorizeMcp(provider, { ...flow, skipRefresh })) === \"AUTHORIZED\") return;\n\t\tif (!authorizationUrl) throw new Error(\"OAuth flow did not produce an authorization URL\");\n\n\t\tconst state = await provider.state();\n\t\toptions.prompt.showAuthorizationUrl(authorizationUrl);\n\t\tconst { code, iss } = await waitForAuthorizationResponse(callback, state, options.prompt);\n\t\tawait authorizeMcp(provider, { ...flow, authorizationCode: code, iss });\n\t} finally {\n\t\tawait callback.close();\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"oauth.js","sourceRoot":"","sources":["../../../src/extensions/mcp/oauth.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * OAuth sign-in for remote MCP servers.\n *\n * Connections never start a browser flow on their own. They send the stored access token and, after\n * a 401, try the stored refresh token. When that is not possible they fail with\n * `McpOAuthAuthorizationRequiredError`, and the user signs in through `/mcp`, which runs\n * the authorization code flow (PKCE, dynamic client registration) against a loopback callback.\n *\n * Credentials live in `<agent-dir>/mcp-auth.json`, keyed by server name and URL.\n */\n\nimport { createHash, randomUUID } from \"node:crypto\";\nimport { mkdirSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { oauthErrorHtml, oauthSuccessHtml } from \"@bastani/pi-ai/utils/oauth-page\";\nimport lockfile from \"proper-lockfile\";\nimport { APP_NAME, getAgentDir } from \"../../config.js\";\nimport { type AuthStorageBackend, FileAuthStorageBackend } from \"../../core/auth-storage.ts\";\nimport { mcpNamespace } from \"../../core/mcp-servers.ts\";\nimport type { AuthProvider, McpFetch } from \"./client/index.js\";\nimport {\n\tauthorizeMcp,\n\tMcpOAuthAuthorizationRequiredError,\n\tMcpOAuthProvider,\n\ttype McpOAuthState,\n\ttype McpOAuthStateStore,\n\ttype OAuthCallback,\n\ttype OAuthCallbackPage,\n\tOAuthCallbackServer,\n\ttype OAuthChallenge,\n\ttype OAuthClientInformationMixed,\n\tparseWwwAuthenticate,\n\tstepUpScope,\n} from \"./client/oauth/index.js\";\n\nconst CALLBACK_HOST = \"127.0.0.1\";\nconst CALLBACK_PATH = \"/callback\";\n/** Redirect URI for refreshes when none is stored. Refreshing never redirects the user. */\nconst FALLBACK_REDIRECT_URL = `http://${CALLBACK_HOST}${CALLBACK_PATH}`;\n/** Access tokens this close to expiry are refreshed before they are sent. */\nconst REFRESH_SKEW_MS = 30_000;\n/** Bounds each request of a refresh, so it cannot hold the refresh lock or delay shutdown for long. */\nconst REFRESH_REQUEST_TIMEOUT_MS = 15_000;\n/** A refresh lock that its holder stopped renewing (the process was killed) is taken over after this. */\nconst REFRESH_LOCK_STALE_MS = 20_000;\n/** How long to wait for another process's refresh: longer than a stale lock lives. */\nconst REFRESH_LOCK_WAIT_MS = 25_000;\nconst REFRESH_LOCK_RETRY_MS = 100;\n\nexport interface McpOAuthSettings {\n\tclientId?: string;\n\t/** Already resolved. */\n\tclientSecret?: string;\n\tcallbackPort?: number;\n\t/** Loopback redirect URI; see `McpOAuthConfig.callbackUrl`. */\n\tcallbackUrl?: string;\n\t/** Scopes to request, separated by spaces. */\n\tscope?: string;\n\t/** `client_name` for dynamic client registration. Default: `APP_NAME`. */\n\tclientName?: string;\n\t/** See `McpOAuthConfig.authServerMetadataUrl`. */\n\tauthServerMetadataUrl?: URL;\n}\n\n/** Where the loopback callback server listens and the redirect URI it serves. */\ninterface CallbackSettings {\n\t/** Address to listen on. */\n\thost: string;\n\t/** Host name in the redirect URI. */\n\tredirectHost: string;\n\tport: number | undefined;\n\tpath: string;\n\t/** The exact redirect URI, when the port is fixed. */\n\tfixedRedirectUrl: string | undefined;\n}\n\nfunction callbackSettings(settings: McpOAuthSettings): CallbackSettings {\n\tconst url = new URL(settings.callbackUrl ?? `http://${CALLBACK_HOST}${CALLBACK_PATH}`);\n\tconst address = url.hostname.replace(/^\\[|\\]$/g, \"\");\n\tconst port = url.port ? Number(url.port) : settings.callbackPort;\n\tlet fixedRedirectUrl: string | undefined;\n\t// A configured URI with a port is sent exactly as written, since servers compare it as a string.\n\tif (url.port) fixedRedirectUrl = settings.callbackUrl;\n\telse if (port !== undefined) {\n\t\turl.port = String(port);\n\t\tfixedRedirectUrl = url.href;\n\t}\n\treturn {\n\t\t// `localhost` is served on 127.0.0.1; browsers fall back to it when ::1 refuses.\n\t\thost: address === \"localhost\" ? CALLBACK_HOST : address,\n\t\tredirectHost: address,\n\t\tport,\n\t\tpath: url.pathname,\n\t\tfixedRedirectUrl,\n\t};\n}\n\n/** Scopes of both lists, each once. */\nfunction mergeScopes(...scopes: (string | undefined)[]): string | undefined {\n\tconst merged = [...new Set(scopes.flatMap((scope) => scope?.split(/\\s+/).filter(Boolean) ?? []))];\n\treturn merged.length > 0 ? merged.join(\" \") : undefined;\n}\n\n// A token-free tombstone keeps revocation durable, including for other processes' late sign-ins.\ntype StoredState = McpOAuthState & { credentialGeneration?: string };\ntype StoredStates = Record<string, StoredState>;\nconst refreshQueues = new WeakMap<AuthStorageBackend, Map<string, Promise<unknown>>>();\n\nfunction parseStates(content: string | undefined): StoredStates {\n\tif (!content?.trim()) return {};\n\tconst parsed: unknown = JSON.parse(content);\n\treturn typeof parsed === \"object\" && parsed !== null && !Array.isArray(parsed) ? (parsed as StoredStates) : {};\n}\n\nfunction serializeStates(states: StoredStates): string {\n\treturn `${JSON.stringify(states, null, 2)}\\n`;\n}\n\n/**\n * Keys of a server's state: by name and URL, so servers sharing a URL keep separate accounts, and the\n * legacy key by URL alone, written by older versions.\n */\nfunction storeKeys(name: string, serverUrl: string): { key: string; legacyKey: string } {\n\tconst legacyKey = String(new URL(serverUrl));\n\treturn { key: `${mcpNamespace(name)}|${legacyKey}`, legacyKey };\n}\n\nexport interface McpOAuthServerStore extends McpOAuthStateStore {\n\t/** Run `fn` while no other process refreshes the server's tokens. */\n\twithRefreshLock<T>(fn: () => Promise<T>): Promise<T>;\n\t/** Capture ownership for one flow; logout invalidates its subsequent reads and writes. */\n\tfenced(): McpOAuthStateStore;\n}\n\n/** Per-server OAuth state (client registration, tokens, pending PKCE verifier) in `mcp-auth.json`. */\nexport class McpOAuthCredentialStore {\n\tprivate readonly backend: AuthStorageBackend;\n\t/** Directory for the refresh lock files. Without one, refreshes are only serialized in this process. */\n\tprivate readonly lockDir: string | undefined;\n\n\tconstructor(backend?: AuthStorageBackend, lockDir?: string) {\n\t\tthis.backend = backend ?? new FileAuthStorageBackend(join(getAgentDir(), \"mcp-auth.json\"));\n\t\tthis.lockDir = backend ? lockDir : getAgentDir();\n\t}\n\n\tforServer(name: string, serverUrl: string): McpOAuthServerStore {\n\t\tconst { key, legacyKey } = storeKeys(name, serverUrl);\n\t\tconst scoped = (fenced: boolean): McpOAuthStateStore => {\n\t\t\tconst initial = this.read();\n\t\t\tconst generation = (initial[key] ?? initial[legacyKey])?.credentialGeneration;\n\t\t\tconst check = (state: StoredState | undefined) => {\n\t\t\t\tif (fenced && state?.credentialGeneration !== generation) throw new McpSignInCancelledError();\n\t\t\t};\n\t\t\treturn {\n\t\t\t\tload: () => {\n\t\t\t\t\tconst state = this.claimLegacy(key, legacyKey)[key];\n\t\t\t\t\tcheck(state);\n\t\t\t\t\tif (!state) return undefined;\n\t\t\t\t\tconst { credentialGeneration: _generation, ...value } = state;\n\t\t\t\t\treturn Object.keys(value).length > 1 ? value : undefined;\n\t\t\t\t},\n\t\t\t\tsave: (state) =>\n\t\t\t\t\tthis.write((states) => {\n\t\t\t\t\t\tcheck(states[key]);\n\t\t\t\t\t\tstates[key] = { ...state, credentialGeneration: states[key]?.credentialGeneration };\n\t\t\t\t\t}),\n\t\t\t};\n\t\t};\n\t\treturn {\n\t\t\t...scoped(false),\n\t\t\tfenced: () => scoped(true),\n\t\t\twithRefreshLock: (fn) => this.withRefreshLock(key, fn),\n\t\t};\n\t}\n\n\t/**\n\t * A lock file per server. When the process exits, proper-lockfile removes the locks it holds; when\n\t * it is killed, the lock goes stale because it is no longer renewed, and the next process takes it over.\n\t */\n\tprivate async withRefreshLock<T>(key: string, fn: () => Promise<T>): Promise<T> {\n\t\tlet queues = refreshQueues.get(this.backend);\n\t\tif (!queues) {\n\t\t\tqueues = new Map();\n\t\t\trefreshQueues.set(this.backend, queues);\n\t\t}\n\t\tconst previous = queues.get(key) ?? Promise.resolve();\n\t\tconst running = previous.catch(() => undefined).then(() => this.withFileRefreshLock(key, fn));\n\t\tqueues.set(key, running);\n\t\ttry {\n\t\t\treturn await running;\n\t\t} finally {\n\t\t\tif (queues.get(key) === running) queues.delete(key);\n\t\t}\n\t}\n\n\tprivate async withFileRefreshLock<T>(key: string, fn: () => Promise<T>): Promise<T> {\n\t\tif (!this.lockDir) return fn();\n\t\tmkdirSync(this.lockDir, { recursive: true, mode: 0o700 });\n\t\tconst hash = createHash(\"sha256\").update(key).digest(\"hex\").slice(0, 16);\n\t\tconst release = await lockfile.lock(join(this.lockDir, `mcp-auth-refresh-${hash}`), {\n\t\t\trealpath: false,\n\t\t\tstale: REFRESH_LOCK_STALE_MS,\n\t\t\tretries: {\n\t\t\t\tretries: REFRESH_LOCK_WAIT_MS / REFRESH_LOCK_RETRY_MS,\n\t\t\t\tfactor: 1,\n\t\t\t\tminTimeout: REFRESH_LOCK_RETRY_MS,\n\t\t\t\tmaxTimeout: REFRESH_LOCK_RETRY_MS,\n\t\t\t},\n\t\t\t// The default throws from a timer. A lost lock at worst lets two refreshes overlap.\n\t\t\tonCompromised: () => {},\n\t\t});\n\t\ttry {\n\t\t\treturn await fn();\n\t\t} finally {\n\t\t\tawait release().catch(() => undefined);\n\t\t}\n\t}\n\n\t/** The first server to load legacy state takes it over; others with the same URL sign in again. */\n\tprivate claimLegacy(key: string, legacyKey: string): StoredStates {\n\t\treturn this.backend.withLock((current) => {\n\t\t\tconst states = parseStates(current);\n\t\t\tif (states[key] || !states[legacyKey]) return { result: states };\n\t\t\tstates[key] = states[legacyKey];\n\t\t\tdelete states[legacyKey];\n\t\t\treturn { result: states, next: serializeStates(states) };\n\t\t});\n\t}\n\n\t/** The stored tokens of a server, for noticing sign-ins done by another process. Does not take over legacy state. */\n\ttokens(name: string, serverUrl: string): McpOAuthState[\"tokens\"] {\n\t\tconst { key, legacyKey } = storeKeys(name, serverUrl);\n\t\tconst states = this.read();\n\t\treturn (states[key] ?? states[legacyKey])?.tokens;\n\t}\n\n\t/** Serialized logout: waits for rotated tokens to be saved before revoking the grant. */\n\tremoveAsync(name: string, serverUrl: string): Promise<boolean> {\n\t\tconst { key } = storeKeys(name, serverUrl);\n\t\treturn this.withRefreshLock(key, async () => this.remove(name, serverUrl));\n\t}\n\n\t/**\n\t * Synchronous revocation also fences late writes; logout callers should prefer removeAsync. Also removes\n\t * legacy state the server would take over.\n\t */\n\tremove(name: string, serverUrl: string): boolean {\n\t\tconst { key, legacyKey } = storeKeys(name, serverUrl);\n\t\tconst hasCredentials = (state: StoredState | undefined) =>\n\t\t\tstate !== undefined &&\n\t\t\tObject.keys(state).some((field) => field !== \"serverUrl\" && field !== \"credentialGeneration\");\n\t\tlet removed = false;\n\t\tthis.write((states) => {\n\t\t\tconst own = states[key];\n\t\t\tconst legacy = own === undefined ? states[legacyKey] : undefined;\n\t\t\tremoved = hasCredentials(own) || hasCredentials(legacy);\n\t\t\tif (legacy) delete states[legacyKey];\n\t\t\tstates[key] = { serverUrl: legacyKey, credentialGeneration: randomUUID() };\n\t\t});\n\t\treturn removed;\n\t}\n\n\tprivate read(): StoredStates {\n\t\treturn this.backend.withLock((current) => ({ result: parseStates(current) }));\n\t}\n\n\tprivate write(update: (states: StoredStates) => void): void {\n\t\tthis.backend.withLock((current) => {\n\t\t\tconst states = parseStates(current);\n\t\t\tupdate(states);\n\t\t\treturn { result: undefined, next: serializeStates(states) };\n\t\t});\n\t}\n}\n\nfunction registeredRedirectUrls(client: OAuthClientInformationMixed | undefined): string[] {\n\treturn client && \"redirect_uris\" in client ? client.redirect_uris : [];\n}\n\nfunction createProvider(\n\tserverUrl: string,\n\tstore: McpOAuthStateStore,\n\tsettings: McpOAuthSettings,\n\tredirectUrl: string,\n\tonRedirect: (url: URL) => void,\n): McpOAuthProvider {\n\treturn new McpOAuthProvider({\n\t\tserverUrl,\n\t\tredirectUrl,\n\t\tclientMetadata: { client_name: settings.clientName ?? APP_NAME },\n\t\tclientId: settings.clientId,\n\t\tclientSecret: settings.clientSecret,\n\t\tstore,\n\t\tonRedirect,\n\t});\n}\n\nexport interface McpAuthProvider extends AuthProvider {\n\t/** Resolves when no refresh is running, so shutdown does not drop rotated tokens before they are saved. */\n\tsettled(): Promise<void>;\n}\n\n/**\n * Auth provider for MCP connections: sends the stored access token and refreshes it when it is about\n * to expire or after a 401. Throws `McpOAuthAuthorizationRequiredError` when the user has to sign in,\n * including when the server asks for more scope (`insufficient_scope`). `onChallenge` receives the\n * server's `WWW-Authenticate` challenge so sign-in can use its resource metadata URL and scope.\n * `settings` is only called when a refresh is needed, so a secret that fails to resolve fails the\n * refresh instead of the whole connection setup.\n *\n * Many servers rotate refresh tokens, so two refreshes with the same refresh token lose the grant.\n * Requests in this process share one refresh, and other processes are kept out by the store's\n * refresh lock, held from reading the tokens to saving new ones. Tokens that changed meanwhile\n * (another process refreshed them, or the user signed in) are used without refreshing.\n */\nexport function createMcpAuthProvider(options: {\n\tserverUrl: string;\n\tstore: McpOAuthServerStore;\n\tsettings: () => McpOAuthSettings;\n\tonChallenge: (challenge: OAuthChallenge) => void;\n}): McpAuthProvider {\n\tconst { serverUrl, store } = options;\n\tlet refreshing: Promise<void> | undefined;\n\n\t/** Replace `staleToken`, the access token that expired or was rejected. */\n\tconst refresh = (staleToken: string | undefined, fetch: McpFetch = globalThis.fetch, challenge?: OAuthChallenge) => {\n\t\trefreshing ??= store\n\t\t\t.withRefreshLock(async () => {\n\t\t\t\tconst flowStore = store.fenced();\n\t\t\t\tconst state = await flowStore.load();\n\t\t\t\tif (state?.tokens?.access_token !== staleToken) return;\n\t\t\t\tif (!state?.tokens?.refresh_token) throw new McpOAuthAuthorizationRequiredError();\n\t\t\t\tconst settings = options.settings();\n\t\t\t\tconst redirectUrl =\n\t\t\t\t\tcallbackSettings(settings).fixedRedirectUrl ??\n\t\t\t\t\tregisteredRedirectUrls(state.clientInformation)[0] ??\n\t\t\t\t\tFALLBACK_REDIRECT_URL;\n\t\t\t\tconst provider = createProvider(serverUrl, flowStore, settings, redirectUrl, () => {});\n\t\t\t\t// Refreshes the tokens, or reports that a new sign-in is needed.\n\t\t\t\tconst result = await authorizeMcp(provider, {\n\t\t\t\t\tserverUrl,\n\t\t\t\t\tresourceMetadataUrl: challenge?.resourceMetadataUrl,\n\t\t\t\t\tauthorizationServerMetadataUrl: settings.authServerMetadataUrl,\n\t\t\t\t\tscope: challenge?.scope,\n\t\t\t\t\tfetch: (input, init) =>\n\t\t\t\t\t\tfetch(input, { ...init, signal: AbortSignal.timeout(REFRESH_REQUEST_TIMEOUT_MS) }),\n\t\t\t\t});\n\t\t\t\tif (result === \"REDIRECT\") throw new McpOAuthAuthorizationRequiredError();\n\t\t\t})\n\t\t\t.finally(() => {\n\t\t\t\trefreshing = undefined;\n\t\t\t});\n\t\treturn refreshing;\n\t};\n\n\treturn {\n\t\ttoken: async () => {\n\t\t\tawait refreshing?.catch(() => undefined);\n\t\t\tconst state = await store.load();\n\t\t\tconst token = state?.tokens?.access_token;\n\t\t\tconst expired = state?.tokensExpireAt !== undefined && state.tokensExpireAt - REFRESH_SKEW_MS <= Date.now();\n\t\t\tif (!expired || !state?.tokens?.refresh_token) return token;\n\t\t\t// Failures fall through: the request goes out with the old token and a 401 decides what happens.\n\t\t\tawait refresh(token).catch(() => undefined);\n\t\t\treturn (await store.load())?.tokens?.access_token;\n\t\t},\n\t\tonUnauthorized: async (context) => {\n\t\t\tconst challenge = parseWwwAuthenticate(context.response.headers.get(\"www-authenticate\"));\n\t\t\toptions.onChallenge(challenge);\n\t\t\t// A refresh keeps the granted scope, so more scope needs a new sign-in.\n\t\t\tif (challenge.error === \"insufficient_scope\") throw new McpOAuthAuthorizationRequiredError();\n\t\t\tawait refresh(context.token, context.fetch, challenge);\n\t\t},\n\t\tsettled: async () => {\n\t\t\tawait refreshing?.catch(() => undefined);\n\t\t},\n\t};\n}\n\nexport interface McpSignInPrompt {\n\t/** Show the authorization URL to the user and open it in a browser. */\n\tshowAuthorizationUrl(url: URL): void;\n\t/**\n\t * Ask for the redirect URL from the browser address bar, for when the browser cannot reach the\n\t * loopback callback (for example over SSH). Aborted once the callback arrives. Resolves to\n\t * `undefined` or an empty string when the user cancels.\n\t */\n\tpromptForRedirectUrl(signal: AbortSignal): Promise<string | undefined>;\n}\n\nexport class McpSignInCancelledError extends Error {\n\tconstructor() {\n\t\tsuper(\"Sign-in cancelled\");\n\t\tthis.name = \"McpSignInCancelledError\";\n\t}\n}\n\ntype AuthorizationResponse = Pick<OAuthCallback, \"code\" | \"iss\">;\n\nfunction responseFromRedirectUrl(input: string, state: string): AuthorizationResponse {\n\tlet url: URL;\n\ttry {\n\t\turl = new URL(input.trim());\n\t} catch {\n\t\tthrow new Error(\"Expected the full redirect URL from the browser address bar\");\n\t}\n\tconst error = url.searchParams.get(\"error\");\n\tif (error) throw new Error(url.searchParams.get(\"error_description\") ?? error);\n\tif (url.searchParams.get(\"state\") !== state) throw new Error(\"The redirect URL belongs to a different sign-in\");\n\tconst code = url.searchParams.get(\"code\");\n\tif (!code) throw new Error(\"The redirect URL does not contain an authorization code\");\n\treturn { code, iss: url.searchParams.get(\"iss\") ?? undefined };\n}\n\n/** Wait for the browser callback or a pasted redirect URL, whichever comes first. */\nasync function waitForAuthorizationResponse(\n\tcallback: OAuthCallbackServer,\n\tstate: string,\n\tprompt: McpSignInPrompt,\n): Promise<AuthorizationResponse> {\n\tconst controller = new AbortController();\n\tconst fromBrowser = callback.waitForCallback(state);\n\tconst fromUser = prompt.promptForRedirectUrl(controller.signal).then((input) => {\n\t\tif (!input?.trim()) throw new McpSignInCancelledError();\n\t\treturn responseFromRedirectUrl(input, state);\n\t});\n\ttry {\n\t\treturn await Promise.race([fromBrowser, fromUser]);\n\t} finally {\n\t\t// The losing side rejects once the prompt is aborted or the callback server closes.\n\t\tcontroller.abort();\n\t\tfromBrowser.catch(() => undefined);\n\t\tfromUser.catch(() => undefined);\n\t}\n}\n\n/** Listen on `port`, or on a free port when it is taken and not `required`. */\nasync function listenForCallback(\n\tsettings: CallbackSettings,\n\tport: number | undefined,\n\trequired: boolean,\n): Promise<OAuthCallbackServer> {\n\tconst options = {\n\t\thost: settings.host,\n\t\tredirectHost: settings.redirectHost,\n\t\tpath: settings.path,\n\t\trenderPage: (page: OAuthCallbackPage) =>\n\t\t\tpage.ok\n\t\t\t\t? oauthSuccessHtml(\"Signed in to the MCP server. You may now close this page.\")\n\t\t\t\t: oauthErrorHtml(page.message, page.details),\n\t};\n\ttry {\n\t\treturn await OAuthCallbackServer.listen({ ...options, port: port ?? 0 });\n\t} catch (error) {\n\t\tif (required || port === undefined) throw error;\n\t\treturn OAuthCallbackServer.listen(options);\n\t}\n}\n\n/**\n * Sign in to an MCP server. Uses the stored refresh token when possible; otherwise runs the browser\n * authorization code flow. Tokens are saved to `store`.\n */\nexport async function signInMcpServer(options: {\n\tserverUrl: string;\n\tstore: McpOAuthServerStore;\n\tsettings: McpOAuthSettings;\n\tchallenge?: OAuthChallenge;\n\tprompt: McpSignInPrompt;\n}): Promise<void> {\n\tconst { serverUrl, settings } = options;\n\tconst store = options.store.fenced();\n\tconst stored = await store.load();\n\tconst stepUp = options.challenge?.error === \"insufficient_scope\";\n\tconst callbackOptions = callbackSettings(settings);\n\t// Reuse the port of the registered redirect URI so the registered client stays valid.\n\tconst registered = registeredRedirectUrls(stored?.clientInformation)[0];\n\tconst preferredPort =\n\t\tcallbackOptions.port ?? (registered ? Number(new URL(registered).port) || undefined : undefined);\n\tconst callback = await listenForCallback(callbackOptions, preferredPort, callbackOptions.port !== undefined);\n\tconst redirectUrl = callbackOptions.fixedRedirectUrl ?? callback.redirectUrl;\n\ttry {\n\t\tif (stored) {\n\t\t\tconst next: McpOAuthState = { ...stored };\n\t\t\t// Every sign-in gets a fresh `state` parameter.\n\t\t\tdelete next.oauthState;\n\t\t\t// A registered client cannot use another redirect URI, and its tokens belong to it.\n\t\t\tif (!settings.clientId && !registeredRedirectUrls(stored.clientInformation).includes(redirectUrl)) {\n\t\t\t\tdelete next.clientInformation;\n\t\t\t\tdelete next.tokens;\n\t\t\t\tdelete next.tokensExpireAt;\n\t\t\t}\n\t\t\tawait store.save(next);\n\t\t}\n\n\t\tlet authorizationUrl: URL | undefined;\n\t\tconst provider = createProvider(serverUrl, store, settings, redirectUrl, (url) => {\n\t\t\tauthorizationUrl = url;\n\t\t});\n\t\tconst flow = {\n\t\t\tserverUrl,\n\t\t\tresourceMetadataUrl: options.challenge?.resourceMetadataUrl,\n\t\t\tauthorizationServerMetadataUrl: settings.authServerMetadataUrl,\n\t\t\t// A server asking for more scope gets it on top of the configured scope and, since the challenge\n\t\t\t// may list only the missing scopes, on top of the scope granted so far.\n\t\t\tscope: mergeScopes(\n\t\t\t\tsettings.scope,\n\t\t\t\tstepUp ? stepUpScope(stored?.tokens?.scope, options.challenge?.scope) : options.challenge?.scope,\n\t\t\t),\n\t\t};\n\t\t// A refresh keeps the granted scope; a server asking for more needs the browser flow.\n\t\tconst skipRefresh = stepUp;\n\t\tif ((await authorizeMcp(provider, { ...flow, skipRefresh })) === \"AUTHORIZED\") return;\n\t\tif (!authorizationUrl) throw new Error(\"OAuth flow did not produce an authorization URL\");\n\n\t\tconst state = await provider.state();\n\t\toptions.prompt.showAuthorizationUrl(authorizationUrl);\n\t\tconst { code, iss } = await waitForAuthorizationResponse(callback, state, options.prompt);\n\t\tawait authorizeMcp(provider, { ...flow, authorizationCode: code, iss });\n\t} finally {\n\t\tawait callback.close();\n\t}\n}\n"]}
|
|
@@ -216,7 +216,7 @@ export class McpServerConnection {
|
|
|
216
216
|
this.authProvider = url
|
|
217
217
|
? createMcpAuthProvider({
|
|
218
218
|
serverUrl: url,
|
|
219
|
-
store: options.credentials.forServer(url),
|
|
219
|
+
store: options.credentials.forServer(this.entry.name, url),
|
|
220
220
|
settings: () => this.oauthSettings(),
|
|
221
221
|
onChallenge: (challenge) => {
|
|
222
222
|
this.challenge = challenge;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../../src/extensions/mcp/runtime.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The part of the MCP integration that talks to servers: connections, transports, and OAuth\n * sign-in. It pulls in the MCP client, so index.ts loads it through runtime.lazy.ts only when a\n * server is configured.\n */\n\nimport { homedir } from \"node:os\";\nimport { basename, join, resolve } from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\nimport { VERSION } from \"../../config.js\";\nimport { resolveMcpServerUrl } from \"../../core/mcp-servers.ts\";\nimport { resolveConfigValueOrThrow, resolveHeadersOrThrow } from \"../../core/resolve-config-value.ts\";\nimport {\n\ttype AuthProvider,\n\ttype CallToolResult,\n\tJSON_RPC_ERROR_CODES,\n\ttype ListResourcesResult,\n\ttype ListResourceTemplatesResult,\n\tMcpAuthRequiredError,\n\tMcpClient,\n\tMcpError,\n\ttype McpFetch,\n\tMcpHttpError,\n\ttype McpRequestOptions,\n\tMcpSessionExpiredError,\n\ttype Tool as McpTool,\n\ttype McpTransport,\n\ttype ReadResourceResult,\n\ttype Resource,\n\ttype ResourceTemplate,\n\tStdioTransport,\n\tStreamableHttpTransport,\n} from \"./client/index.js\";\nimport { McpOAuthAuthorizationRequiredError, type OAuthChallenge } from \"./client/oauth/index.js\";\nimport type { McpServerEntry } from \"./config.ts\";\nimport type { McpServerLog } from \"./log.ts\";\nimport {\n\tcreateMcpAuthProvider,\n\ttype McpAuthProvider,\n\ttype McpOAuthCredentialStore,\n\ttype McpOAuthSettings,\n} from \"./oauth.ts\";\nimport { isMcpAppResource, type McpResourceServer } from \"./resources.ts\";\nimport type { McpToolCaller } from \"./tools.ts\";\n\nexport { McpServerLog } from \"./log.ts\";\nexport { McpOAuthCredentialStore, McpSignInCancelledError, signInMcpServer } from \"./oauth.ts\";\n\nconst DEFAULT_TIMEOUT_SECONDS = 60;\nconst STDERR_TAIL_CHARS = 2_000;\n/** Delays between attempts to connect to an HTTP server that failed with a transient error. */\nconst CONNECT_RETRY_DELAYS_MS = [250, 1_000];\n/** Give canceled setup time to retire, without letting a broken transport block session cleanup. */\nconst OPENING_RETIREMENT_TIMEOUT_MS = 1_000;\n\nasync function boundedRetirement(retirement: Promise<unknown>): Promise<void> {\n\tlet timer: ReturnType<typeof setTimeout> | undefined;\n\ttry {\n\t\tawait Promise.race([\n\t\t\tretirement.catch(() => undefined),\n\t\t\tnew Promise<void>((resolve) => {\n\t\t\t\ttimer = setTimeout(resolve, OPENING_RETIREMENT_TIMEOUT_MS);\n\t\t\t}),\n\t\t]);\n\t} finally {\n\t\tclearTimeout(timer);\n\t}\n}\n\n/**\n * `disconnected`: the connection dropped (for example the stdio server exited); the next call\n * reconnects.\n */\ntype ServerState = \"connecting\" | \"connected\" | \"disconnected\" | \"needs-auth\" | \"failed\" | \"closed\";\n\nexport type McpTransportFactory = (\n\tentry: McpServerEntry,\n\tcwd: string,\n\tauthProvider: AuthProvider | undefined,\n) => McpTransport;\n\nfunction errorMessage(error: unknown): string {\n\treturn error instanceof Error ? error.message : String(error);\n}\n\n/** Network failures and overloaded or restarting servers, which are worth another attempt. */\nfunction isTransientError(error: unknown): boolean {\n\tif (error instanceof McpHttpError) {\n\t\treturn error.status === 408 || error.status === 429 || (error.status >= 500 && error.status !== 501);\n\t}\n\treturn error instanceof TypeError;\n}\n\nfunction providerAuthName(entry: McpServerEntry): string | undefined {\n\treturn \"url\" in entry.config ? entry.config.auth?.provider : undefined;\n}\n\nfunction validateProviderDestination(serverUrl: string): void {\n\tconst url = new URL(serverUrl);\n\tif (\n\t\turl.protocol !== \"https:\" &&\n\t\t!(url.protocol === \"http:\" && [\"localhost\", \"127.0.0.1\", \"[::1]\"].includes(url.hostname))\n\t) {\n\t\tthrow new Error(\"MCP provider credentials require HTTPS or exact loopback HTTP\");\n\t}\n}\n\n/** A provider token is granted to this configured origin, never to a redirect destination. */\nfunction providerFetch(serverUrl: string): McpFetch {\n\tconst origin = new URL(serverUrl).origin;\n\treturn async (input, init) => {\n\t\tlet url = new URL(input);\n\t\tlet request = { ...init, redirect: \"manual\" as const };\n\t\tfor (let redirects = 0; ; redirects++) {\n\t\t\tif (url.origin !== origin) throw new Error(\"MCP provider request cannot cross origins\");\n\t\t\tconst response = await fetch(url, request);\n\t\t\tconst location = response.headers.get(\"location\");\n\t\t\tif (![301, 302, 303, 307, 308].includes(response.status) || !location) return response;\n\t\t\tawait response.body?.cancel();\n\t\t\tif (redirects >= 10) throw new Error(\"Too many MCP provider redirects\");\n\t\t\turl = new URL(location, url);\n\t\t\tconst method = request.method?.toUpperCase() ?? \"GET\";\n\t\t\tif (\n\t\t\t\t(response.status === 303 && method !== \"HEAD\") ||\n\t\t\t\t([301, 302].includes(response.status) && method === \"POST\")\n\t\t\t) {\n\t\t\t\tconst headers = new Headers(request.headers);\n\t\t\t\tfor (const header of [\n\t\t\t\t\t\"content-type\",\n\t\t\t\t\t\"content-length\",\n\t\t\t\t\t\"content-encoding\",\n\t\t\t\t\t\"content-language\",\n\t\t\t\t\t\"content-location\",\n\t\t\t\t])\n\t\t\t\t\theaders.delete(header);\n\t\t\t\trequest = { ...request, method: \"GET\", body: undefined, headers };\n\t\t\t}\n\t\t}\n\t};\n}\n\nfunction signInRequiredMessage(entry: McpServerEntry): string {\n\tconst provider = providerAuthName(entry);\n\treturn `MCP server \"${entry.name}\" requires sign-in. Run ${provider ? `/login ${provider}` : \"/mcp\"} to sign in.`;\n}\n\n/** HTTP servers authenticate with OAuth unless they supply Authorization or a provider. */\nfunction usesOAuth(entry: McpServerEntry): boolean {\n\tconst { config } = entry;\n\tif (!(\"url\" in config) || config.auth) return false;\n\treturn !Object.keys(config.headers ?? {}).some((header) => header.toLowerCase() === \"authorization\");\n}\n\n/** `~` and `~/…` (also `~\\…` on Windows) name the home directory, like in a shell. */\nfunction expandHome(value: string): string {\n\tif (value === \"~\") return homedir();\n\tif (value.startsWith(\"~/\") || (process.platform === \"win32\" && value.startsWith(\"~\\\\\"))) {\n\t\treturn join(homedir(), value.slice(2));\n\t}\n\treturn value;\n}\n\nexport function createDefaultTransport(\n\tentry: McpServerEntry,\n\tcwd: string,\n\tauthProvider: AuthProvider | undefined,\n): McpTransport {\n\tconst { config, name } = entry;\n\tif (\"url\" in config) {\n\t\tconst url = resolveMcpServerUrl(config.url);\n\t\tif (config.auth) validateProviderDestination(url);\n\t\treturn new StreamableHttpTransport({\n\t\t\turl,\n\t\t\theaders: resolveHeadersOrThrow(config.headers, `MCP server \"${name}\"`),\n\t\t\tauthProvider,\n\t\t\tfetch: config.auth ? providerFetch(url) : undefined,\n\t\t});\n\t}\n\tif (!config.command) throw new Error(`MCP server \"${name}\" has no command or url`);\n\tconst env: Record<string, string> = {};\n\tfor (const [key, value] of Object.entries(config.env ?? {})) {\n\t\tenv[key] = resolveConfigValueOrThrow(value, `MCP server \"${name}\" env \"${key}\"`);\n\t}\n\treturn new StdioTransport({\n\t\tcommand: expandHome(config.command),\n\t\targs: config.args?.map(expandHome),\n\t\tcwd: resolve(cwd, expandHome(config.cwd ?? \".\")),\n\t\tenv,\n\t\tstderr: \"pipe\",\n\t});\n}\n\n/** Servers that do not implement `resources/templates/list` have no templates. */\nasync function withoutTemplates<T>(list: () => Promise<T>, empty: T): Promise<T> {\n\ttry {\n\t\treturn await list();\n\t} catch (error) {\n\t\tif (error instanceof McpError && error.code === JSON_RPC_ERROR_CODES.methodNotFound) return empty;\n\t\tthrow error;\n\t}\n}\n\nfunction listTemplates(client: McpClient, options: McpRequestOptions = {}): Promise<ResourceTemplate[]> {\n\treturn withoutTemplates(() => client.listResourceTemplates(options), []);\n}\n\n/**\n * Resources and templates at connect time, for the counts in `/mcp` and `pi mcp list`. A server\n * whose lists fail still connects: the resource tools list and read its resources on demand.\n */\nasync function fetchResources(\n\tclient: McpClient,\n): Promise<{ resources: Resource[]; resourceTemplates: ResourceTemplate[] }> {\n\tconst [resources, resourceTemplates] = await Promise.all([\n\t\tclient.listResources().catch(() => []),\n\t\tlistTemplates(client).catch(() => []),\n\t]);\n\treturn {\n\t\tresources: resources.filter((resource) => !isMcpAppResource(resource)),\n\t\tresourceTemplates: resourceTemplates.filter((template) => !isMcpAppResource(template)),\n\t};\n}\n\n/** One configured server. Reconnects lazily when a call finds the connection gone. */\nexport class McpServerConnection implements McpToolCaller, McpResourceServer {\n\treadonly entry: McpServerEntry;\n\tstate: ServerState = \"connecting\";\n\terror: string | undefined;\n\ttools: McpTool[] = [];\n\t/**\n\t * Whether the server offers resources. The lists below are what it listed at the last connect or\n\t * change, without MCP App resources.\n\t */\n\thasResources = false;\n\tresources: Resource[] = [];\n\tresourceTemplates: ResourceTemplate[] = [];\n\t/** Server instructions from `initialize`, describing its tools as a group. */\n\tinstructions: string | undefined;\n\t/** Last OAuth challenge from the server; sign-in uses its resource metadata URL and scope. */\n\tchallenge: OAuthChallenge | undefined;\n\tprivate client: McpClient | undefined;\n\tprivate opening: Promise<McpClient> | undefined;\n\tprivate initializingClient: McpClient | undefined;\n\tprivate initializingTransport: McpTransport | undefined;\n\tprivate closing: Promise<void> | undefined;\n\tprivate readonly activeRequests = new Map<McpClient, number>();\n\tprivate readonly retiringClients = new Map<McpClient, { promise: Promise<void>; close: () => Promise<void> }>();\n\tprivate closed = false;\n\t/** Stderr of the last stdio server that failed to connect. */\n\tprivate stderrTail: string | undefined;\n\tprivate readonly cwd: string;\n\tprivate readonly createTransport: McpTransportFactory;\n\tprivate readonly authProvider: McpAuthProvider | undefined;\n\tprivate readonly onTools: (connection: McpServerConnection) => void;\n\tprivate readonly onChange: ((connection: McpServerConnection) => void) | undefined;\n\tprivate readonly log: McpServerLog | undefined;\n\n\tconstructor(options: {\n\t\tentry: McpServerEntry;\n\t\tcwd: string;\n\t\tcreateTransport: McpTransportFactory;\n\t\tcredentials: McpOAuthCredentialStore;\n\t\t/** The current token of a pi provider, for servers with `auth.provider`. */\n\t\tproviderToken?: (provider: string) => Promise<string | undefined>;\n\t\tonTools: (connection: McpServerConnection) => void;\n\t\t/** Called when `state`, `error`, or `tools` change. */\n\t\tonChange?: (connection: McpServerConnection) => void;\n\t\t/** Receives the server's log messages (`notifications/message`). */\n\t\tlog?: McpServerLog;\n\t}) {\n\t\tconst config = options.entry.config;\n\t\t// Resolve once so the credential key, destination check, and transport use the same URL.\n\t\tthis.entry =\n\t\t\t\"url\" in config\n\t\t\t\t? { ...options.entry, config: { ...config, url: resolveMcpServerUrl(config.url) } }\n\t\t\t\t: options.entry;\n\t\tthis.cwd = options.cwd;\n\t\tthis.createTransport = options.createTransport;\n\t\tthis.onTools = options.onTools;\n\t\tthis.onChange = options.onChange;\n\t\tthis.log = options.log;\n\t\tconst url = this.oauthUrl;\n\t\tconst provider = providerAuthName(this.entry);\n\t\tif (provider && \"url\" in this.entry.config) validateProviderDestination(this.entry.config.url);\n\t\tthis.authProvider = url\n\t\t\t? createMcpAuthProvider({\n\t\t\t\t\tserverUrl: url,\n\t\t\t\t\tstore: options.credentials.forServer(url),\n\t\t\t\t\tsettings: () => this.oauthSettings(),\n\t\t\t\t\tonChallenge: (challenge) => {\n\t\t\t\t\t\tthis.challenge = challenge;\n\t\t\t\t\t},\n\t\t\t\t})\n\t\t\t: provider\n\t\t\t\t? // Read on every request, so the provider's refreshes apply; MCP stores no copy.\n\t\t\t\t\t{ token: async () => options.providerToken?.(provider), settled: async () => {} }\n\t\t\t\t: undefined;\n\t}\n\n\tget name(): string {\n\t\treturn this.entry.name;\n\t}\n\n\tget timeoutMs(): number {\n\t\treturn (this.entry.config.timeout ?? DEFAULT_TIMEOUT_SECONDS) * 1000;\n\t}\n\n\t/** Server URL when the server authenticates with OAuth. */\n\tget oauthUrl(): string | undefined {\n\t\treturn \"url\" in this.entry.config && usesOAuth(this.entry) ? this.entry.config.url : undefined;\n\t}\n\n\toauthSettings(): McpOAuthSettings {\n\t\tconst oauth = \"url\" in this.entry.config ? this.entry.config.oauth : undefined;\n\t\tif (!oauth) return {};\n\t\treturn {\n\t\t\tclientId: oauth.clientId,\n\t\t\tclientSecret:\n\t\t\t\toauth.clientSecret === undefined\n\t\t\t\t\t? undefined\n\t\t\t\t\t: resolveConfigValueOrThrow(oauth.clientSecret, `MCP server \"${this.entry.name}\" oauth.clientSecret`),\n\t\t\tcallbackPort: oauth.callbackPort,\n\t\t\tcallbackUrl: oauth.callbackUrl,\n\t\t\tscope: oauth.scope,\n\t\t\tclientName: oauth.clientName,\n\t\t\tauthServerMetadataUrl: oauth.authServerMetadataUrl ? new URL(oauth.authServerMetadataUrl) : undefined,\n\t\t};\n\t}\n\n\tgetClient(): Promise<McpClient> {\n\t\tif (this.closed) return Promise.reject(new Error(`MCP server \"${this.entry.name}\" is shut down`));\n\t\tif (this.client?.connectionState === \"connected\") return Promise.resolve(this.client);\n\t\tthis.opening ??= this.open().finally(() => {\n\t\t\tthis.opening = undefined;\n\t\t});\n\t\treturn this.opening;\n\t}\n\n\tcallTool(name: string, args: Record<string, unknown>, options: McpRequestOptions): Promise<CallToolResult> {\n\t\treturn this.withClient((client) => client.callTool(name, args, options));\n\t}\n\n\treadResource(uri: string, options: McpRequestOptions): Promise<ReadResourceResult> {\n\t\treturn this.withClient((client) => client.readResource(uri, options), true);\n\t}\n\n\tresourcesPage(cursor: string | undefined, options: McpRequestOptions): Promise<ListResourcesResult> {\n\t\treturn this.withClient((client) => client.listResourcesPage(cursor, options), true);\n\t}\n\n\tresourceTemplatesPage(cursor: string | undefined, options: McpRequestOptions): Promise<ListResourceTemplatesResult> {\n\t\treturn this.withClient(\n\t\t\t(client) =>\n\t\t\t\twithoutTemplates(() => client.listResourceTemplatesPage(cursor, options), { resourceTemplates: [] }),\n\t\t\ttrue,\n\t\t);\n\t}\n\n\tallResources(options: McpRequestOptions): Promise<Resource[]> {\n\t\treturn this.withClient((client) => client.listResources(options), true);\n\t}\n\n\tallResourceTemplates(options: McpRequestOptions): Promise<ResourceTemplate[]> {\n\t\treturn this.withClient((client) => listTemplates(client, options), true);\n\t}\n\n\t/**\n\t * Run a request, reconnecting when needed. `readOnly` requests are retried once after a transient\n\t * HTTP error; tool calls are not, since they may have run.\n\t */\n\tprivate async withClient<T>(run: (client: McpClient) => Promise<T>, readOnly = false): Promise<T> {\n\t\tfor (let attempt = 1; ; attempt++) {\n\t\t\tconst client = await this.getClient();\n\t\t\ttry {\n\t\t\t\treturn await this.runWithClient(client, run);\n\t\t\t} catch (error) {\n\t\t\t\tif (readOnly && attempt === 1 && error instanceof McpHttpError && isTransientError(error)) {\n\t\t\t\t\tawait new Promise((resolve) => setTimeout(resolve, CONNECT_RETRY_DELAYS_MS[0]));\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (error instanceof McpSessionExpiredError && attempt === 1) {\n\t\t\t\t\tif (this.closed) throw error;\n\t\t\t\t\tconst retirement = this.dropClient(client, true);\n\t\t\t\t\tif (!this.activeRequests.has(client)) await retirement;\n\t\t\t\t\tif (this.closed) throw error;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (!this.needsSignIn(error)) throw error;\n\t\t\t\tawait this.dropClient(client);\n\t\t\t\tthis.markNeedsAuth();\n\t\t\t\tthrow new Error(signInRequiredMessage(this.entry));\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate async runWithClient<T>(client: McpClient, run: (client: McpClient) => Promise<T>): Promise<T> {\n\t\tthis.activeRequests.set(client, (this.activeRequests.get(client) ?? 0) + 1);\n\t\ttry {\n\t\t\treturn await run(client);\n\t\t} finally {\n\t\t\tconst remaining = (this.activeRequests.get(client) ?? 1) - 1;\n\t\t\tif (remaining > 0) {\n\t\t\t\tthis.activeRequests.set(client, remaining);\n\t\t\t} else {\n\t\t\t\tthis.activeRequests.delete(client);\n\t\t\t\tvoid this.retiringClients.get(client)?.close();\n\t\t\t}\n\t\t}\n\t}\n\n\t/** Connect again with fresh credentials, for example after signing in. */\n\tasync reconnect(): Promise<void> {\n\t\tawait this.opening?.catch(() => undefined);\n\t\tif (this.client) await this.dropClient(this.client);\n\t\tawait this.getClient();\n\t}\n\n\t/** Disconnect after the stored credentials were removed. */\n\tasync signOut(): Promise<void> {\n\t\tawait this.opening?.catch(() => undefined);\n\t\tif (this.client) await this.dropClient(this.client);\n\t\tif (!this.closed) this.markNeedsAuth();\n\t}\n\n\t/** OAuth servers that still reject the request after a refresh need the user to sign in again. */\n\tprivate needsSignIn(error: unknown): boolean {\n\t\treturn (\n\t\t\terror instanceof McpOAuthAuthorizationRequiredError ||\n\t\t\t(this.authProvider !== undefined && error instanceof McpAuthRequiredError)\n\t\t);\n\t}\n\n\tprivate markNeedsAuth(): void {\n\t\tthis.state = \"needs-auth\";\n\t\tthis.error = undefined;\n\t\tthis.changed();\n\t}\n\n\tprivate changed(): void {\n\t\tthis.onChange?.(this);\n\t}\n\n\tprivate dropClient(client: McpClient, drainRequests = false): Promise<void> {\n\t\tif (this.client === client) this.client = undefined;\n\t\tconst pending = this.retiringClients.get(client);\n\t\tif (pending) {\n\t\t\tif (!drainRequests) void pending.close();\n\t\t\treturn pending.promise;\n\t\t}\n\t\tlet resolve!: () => void;\n\t\tconst promise = new Promise<void>((done) => {\n\t\t\tresolve = done;\n\t\t});\n\t\tlet closing: Promise<void> | undefined;\n\t\tconst close = () => {\n\t\t\tclosing ??= client\n\t\t\t\t.close()\n\t\t\t\t.catch(() => undefined)\n\t\t\t\t.finally(() => {\n\t\t\t\t\tthis.retiringClients.delete(client);\n\t\t\t\t\tresolve();\n\t\t\t\t});\n\t\t\treturn closing;\n\t\t};\n\t\tthis.retiringClients.set(client, { promise, close });\n\t\tif (!drainRequests || !this.activeRequests.has(client)) void close();\n\t\treturn promise;\n\t}\n\n\tprivate async open(): Promise<McpClient> {\n\t\tthis.state = \"connecting\";\n\t\tthis.changed();\n\t\tconst retries = \"url\" in this.entry.config ? CONNECT_RETRY_DELAYS_MS : [];\n\t\tfor (let attempt = 0; ; attempt++) {\n\t\t\tthis.stderrTail = undefined;\n\t\t\ttry {\n\t\t\t\treturn await this.connectOnce();\n\t\t\t} catch (error) {\n\t\t\t\tconst delay = retries[attempt];\n\t\t\t\tif (this.closed || delay === undefined || !isTransientError(error)) {\n\t\t\t\t\tthrow this.connectFailed(error);\n\t\t\t\t}\n\t\t\t\tawait new Promise((resolve) => setTimeout(resolve, delay));\n\t\t\t\tif (this.closed) throw this.connectFailed(error);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate async connectOnce(): Promise<McpClient> {\n\t\tif (this.closed) throw new Error(\"shut down while connecting\");\n\t\tconst client = new McpClient({\n\t\t\tname: \"pi\",\n\t\t\tversion: VERSION,\n\t\t\trequestTimeoutMs: this.timeoutMs,\n\t\t\troots: [{ uri: pathToFileURL(this.cwd).href, name: basename(this.cwd) }],\n\t\t});\n\t\tthis.initializingClient = client;\n\t\tconst log = this.log;\n\t\tif (log) client.onNotification(\"notifications/message\", (params) => log.write(this.entry.name, params));\n\t\tlet transport: McpTransport | undefined;\n\t\ttry {\n\t\t\ttransport = this.createTransport(this.entry, this.cwd, this.authProvider);\n\t\t\tthis.initializingTransport = transport;\n\t\t\tif (this.closed) throw new Error(\"shut down while connecting\");\n\t\t\tawait client.connect(transport);\n\t\t\tclient.onNotification(\"notifications/tools/list_changed\", () => {\n\t\t\t\tvoid this.refreshTools(client);\n\t\t\t});\n\t\t\tclient.onNotification(\"notifications/resources/list_changed\", () => {\n\t\t\t\tvoid this.refreshResources(client);\n\t\t\t});\n\t\t\tconst stdio = transport instanceof StdioTransport ? transport : undefined;\n\t\t\tclient.onClose(() => this.handleClientClose(client, stdio));\n\t\t\t// Servers without the tools capability (prompts or resources only) do not answer tools/list.\n\t\t\tconst hasResources = client.serverCapabilities?.resources !== undefined;\n\t\t\tconst [tools, resources] = await Promise.all([\n\t\t\t\tclient.serverCapabilities?.tools ? client.listTools() : [],\n\t\t\t\thasResources ? fetchResources(client) : { resources: [], resourceTemplates: [] },\n\t\t\t]);\n\t\t\tif (this.closed) throw new Error(\"shut down while connecting\");\n\t\t\tif (client.connectionState !== \"connected\") throw new Error(\"connection closed during setup\");\n\t\t\tthis.client = client;\n\t\t\tthis.tools = tools;\n\t\t\tthis.hasResources = hasResources;\n\t\t\tthis.resources = resources.resources;\n\t\t\tthis.resourceTemplates = resources.resourceTemplates;\n\t\t\tthis.instructions = client.instructions?.trim() || undefined;\n\t\t\tthis.state = \"connected\";\n\t\t\tthis.error = undefined;\n\t\t\tthis.onTools(this);\n\t\t\tthis.changed();\n\t\t\treturn client;\n\t\t} catch (error) {\n\t\t\tawait client.close().catch(() => undefined);\n\t\t\tif (transport instanceof StdioTransport) {\n\t\t\t\tthis.stderrTail = transport.stderr.trim().slice(-STDERR_TAIL_CHARS) || undefined;\n\t\t\t}\n\t\t\tthrow error;\n\t\t} finally {\n\t\t\t// A delayed start may allocate resources after its first close. Retire them too.\n\t\t\tif (this.closed) await transport?.close().catch(() => undefined);\n\t\t\tif (this.initializingClient === client) {\n\t\t\t\tthis.initializingClient = undefined;\n\t\t\t\tthis.initializingTransport = undefined;\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate connectFailed(error: unknown): Error {\n\t\tif (this.needsSignIn(error) && !this.closed) {\n\t\t\tthis.markNeedsAuth();\n\t\t\treturn new Error(signInRequiredMessage(this.entry));\n\t\t}\n\t\tthis.state = this.closed ? \"closed\" : \"failed\";\n\t\tthis.error = this.stderrTail ? `${errorMessage(error)}\\n${this.stderrTail}` : errorMessage(error);\n\t\tthis.changed();\n\t\treturn new Error(`MCP server \"${this.entry.name}\" failed to connect: ${this.error}`);\n\t}\n\n\t/** The transport dropped. The next call reconnects; until then the status shows why. */\n\tprivate handleClientClose(client: McpClient, stdio: StdioTransport | undefined): void {\n\t\tif (this.client !== client || this.closed) return;\n\t\tthis.client = undefined;\n\t\tthis.state = \"disconnected\";\n\t\tconst stderr = stdio?.stderr.trim().slice(-STDERR_TAIL_CHARS);\n\t\tthis.error = stderr ? `Connection closed\\n${stderr}` : \"Connection closed\";\n\t\tthis.changed();\n\t}\n\n\tprivate async refreshTools(client: McpClient): Promise<void> {\n\t\ttry {\n\t\t\tconst tools = await this.runWithClient(client, (client) => client.listTools());\n\t\t\tif (this.client !== client || this.closed) return;\n\t\t\tthis.tools = tools;\n\t\t\tthis.onTools(this);\n\t\t} catch (error) {\n\t\t\tthis.error = `Failed to refresh tools: ${errorMessage(error)}`;\n\t\t}\n\t\tthis.changed();\n\t}\n\n\tprivate async refreshResources(client: McpClient): Promise<void> {\n\t\tconst { resources, resourceTemplates } = await this.runWithClient(client, fetchResources);\n\t\tif (this.client !== client || this.closed) return;\n\t\tthis.resources = resources;\n\t\tthis.resourceTemplates = resourceTemplates;\n\t\tthis.onTools(this);\n\t\tthis.changed();\n\t}\n\n\tclose(): Promise<void> {\n\t\tif (this.closing) return this.closing;\n\t\tthis.closed = true;\n\t\tthis.state = \"closed\";\n\t\tthis.changed();\n\t\tconst client = this.client;\n\t\tthis.client = undefined;\n\t\tconst opening = this.opening;\n\t\tconst initializingClient = this.initializingClient;\n\t\tconst initializingTransport = this.initializingTransport;\n\t\t// Close immediately, before waiting for setup: start itself may need close to unblock.\n\t\tconst retirement = Promise.allSettled([\n\t\t\tclient?.close(),\n\t\t\tinitializingClient?.close(),\n\t\t\tinitializingTransport?.close(),\n\t\t\topening,\n\t\t\t...[...this.retiringClients.values()].map((retirement) => retirement.close()),\n\t\t]);\n\t\tthis.closing = (async () => {\n\t\t\tawait boundedRetirement(retirement);\n\t\t\t// Preserve an already-rotated refresh token before exiting.\n\t\t\tawait this.authProvider?.settled();\n\t\t})();\n\t\treturn this.closing;\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../../src/extensions/mcp/runtime.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The part of the MCP integration that talks to servers: connections, transports, and OAuth\n * sign-in. It pulls in the MCP client, so index.ts loads it through runtime.lazy.ts only when a\n * server is configured.\n */\n\nimport { homedir } from \"node:os\";\nimport { basename, join, resolve } from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\nimport { VERSION } from \"../../config.js\";\nimport { resolveMcpServerUrl } from \"../../core/mcp-servers.ts\";\nimport { resolveConfigValueOrThrow, resolveHeadersOrThrow } from \"../../core/resolve-config-value.ts\";\nimport {\n\ttype AuthProvider,\n\ttype CallToolResult,\n\tJSON_RPC_ERROR_CODES,\n\ttype ListResourcesResult,\n\ttype ListResourceTemplatesResult,\n\tMcpAuthRequiredError,\n\tMcpClient,\n\tMcpError,\n\ttype McpFetch,\n\tMcpHttpError,\n\ttype McpRequestOptions,\n\tMcpSessionExpiredError,\n\ttype Tool as McpTool,\n\ttype McpTransport,\n\ttype ReadResourceResult,\n\ttype Resource,\n\ttype ResourceTemplate,\n\tStdioTransport,\n\tStreamableHttpTransport,\n} from \"./client/index.js\";\nimport { McpOAuthAuthorizationRequiredError, type OAuthChallenge } from \"./client/oauth/index.js\";\nimport type { McpServerEntry } from \"./config.ts\";\nimport type { McpServerLog } from \"./log.ts\";\nimport {\n\tcreateMcpAuthProvider,\n\ttype McpAuthProvider,\n\ttype McpOAuthCredentialStore,\n\ttype McpOAuthSettings,\n} from \"./oauth.ts\";\nimport { isMcpAppResource, type McpResourceServer } from \"./resources.ts\";\nimport type { McpToolCaller } from \"./tools.ts\";\n\nexport { McpServerLog } from \"./log.ts\";\nexport { McpOAuthCredentialStore, McpSignInCancelledError, signInMcpServer } from \"./oauth.ts\";\n\nconst DEFAULT_TIMEOUT_SECONDS = 60;\nconst STDERR_TAIL_CHARS = 2_000;\n/** Delays between attempts to connect to an HTTP server that failed with a transient error. */\nconst CONNECT_RETRY_DELAYS_MS = [250, 1_000];\n/** Give canceled setup time to retire, without letting a broken transport block session cleanup. */\nconst OPENING_RETIREMENT_TIMEOUT_MS = 1_000;\n\nasync function boundedRetirement(retirement: Promise<unknown>): Promise<void> {\n\tlet timer: ReturnType<typeof setTimeout> | undefined;\n\ttry {\n\t\tawait Promise.race([\n\t\t\tretirement.catch(() => undefined),\n\t\t\tnew Promise<void>((resolve) => {\n\t\t\t\ttimer = setTimeout(resolve, OPENING_RETIREMENT_TIMEOUT_MS);\n\t\t\t}),\n\t\t]);\n\t} finally {\n\t\tclearTimeout(timer);\n\t}\n}\n\n/**\n * `disconnected`: the connection dropped (for example the stdio server exited); the next call\n * reconnects.\n */\ntype ServerState = \"connecting\" | \"connected\" | \"disconnected\" | \"needs-auth\" | \"failed\" | \"closed\";\n\nexport type McpTransportFactory = (\n\tentry: McpServerEntry,\n\tcwd: string,\n\tauthProvider: AuthProvider | undefined,\n) => McpTransport;\n\nfunction errorMessage(error: unknown): string {\n\treturn error instanceof Error ? error.message : String(error);\n}\n\n/** Network failures and overloaded or restarting servers, which are worth another attempt. */\nfunction isTransientError(error: unknown): boolean {\n\tif (error instanceof McpHttpError) {\n\t\treturn error.status === 408 || error.status === 429 || (error.status >= 500 && error.status !== 501);\n\t}\n\treturn error instanceof TypeError;\n}\n\nfunction providerAuthName(entry: McpServerEntry): string | undefined {\n\treturn \"url\" in entry.config ? entry.config.auth?.provider : undefined;\n}\n\nfunction validateProviderDestination(serverUrl: string): void {\n\tconst url = new URL(serverUrl);\n\tif (\n\t\turl.protocol !== \"https:\" &&\n\t\t!(url.protocol === \"http:\" && [\"localhost\", \"127.0.0.1\", \"[::1]\"].includes(url.hostname))\n\t) {\n\t\tthrow new Error(\"MCP provider credentials require HTTPS or exact loopback HTTP\");\n\t}\n}\n\n/** A provider token is granted to this configured origin, never to a redirect destination. */\nfunction providerFetch(serverUrl: string): McpFetch {\n\tconst origin = new URL(serverUrl).origin;\n\treturn async (input, init) => {\n\t\tlet url = new URL(input);\n\t\tlet request = { ...init, redirect: \"manual\" as const };\n\t\tfor (let redirects = 0; ; redirects++) {\n\t\t\tif (url.origin !== origin) throw new Error(\"MCP provider request cannot cross origins\");\n\t\t\tconst response = await fetch(url, request);\n\t\t\tconst location = response.headers.get(\"location\");\n\t\t\tif (![301, 302, 303, 307, 308].includes(response.status) || !location) return response;\n\t\t\tawait response.body?.cancel();\n\t\t\tif (redirects >= 10) throw new Error(\"Too many MCP provider redirects\");\n\t\t\turl = new URL(location, url);\n\t\t\tconst method = request.method?.toUpperCase() ?? \"GET\";\n\t\t\tif (\n\t\t\t\t(response.status === 303 && method !== \"HEAD\") ||\n\t\t\t\t([301, 302].includes(response.status) && method === \"POST\")\n\t\t\t) {\n\t\t\t\tconst headers = new Headers(request.headers);\n\t\t\t\tfor (const header of [\n\t\t\t\t\t\"content-type\",\n\t\t\t\t\t\"content-length\",\n\t\t\t\t\t\"content-encoding\",\n\t\t\t\t\t\"content-language\",\n\t\t\t\t\t\"content-location\",\n\t\t\t\t])\n\t\t\t\t\theaders.delete(header);\n\t\t\t\trequest = { ...request, method: \"GET\", body: undefined, headers };\n\t\t\t}\n\t\t}\n\t};\n}\n\nfunction signInRequiredMessage(entry: McpServerEntry): string {\n\tconst provider = providerAuthName(entry);\n\treturn `MCP server \"${entry.name}\" requires sign-in. Run ${provider ? `/login ${provider}` : \"/mcp\"} to sign in.`;\n}\n\n/** HTTP servers authenticate with OAuth unless they supply Authorization or a provider. */\nfunction usesOAuth(entry: McpServerEntry): boolean {\n\tconst { config } = entry;\n\tif (!(\"url\" in config) || config.auth) return false;\n\treturn !Object.keys(config.headers ?? {}).some((header) => header.toLowerCase() === \"authorization\");\n}\n\n/** `~` and `~/…` (also `~\\…` on Windows) name the home directory, like in a shell. */\nfunction expandHome(value: string): string {\n\tif (value === \"~\") return homedir();\n\tif (value.startsWith(\"~/\") || (process.platform === \"win32\" && value.startsWith(\"~\\\\\"))) {\n\t\treturn join(homedir(), value.slice(2));\n\t}\n\treturn value;\n}\n\nexport function createDefaultTransport(\n\tentry: McpServerEntry,\n\tcwd: string,\n\tauthProvider: AuthProvider | undefined,\n): McpTransport {\n\tconst { config, name } = entry;\n\tif (\"url\" in config) {\n\t\tconst url = resolveMcpServerUrl(config.url);\n\t\tif (config.auth) validateProviderDestination(url);\n\t\treturn new StreamableHttpTransport({\n\t\t\turl,\n\t\t\theaders: resolveHeadersOrThrow(config.headers, `MCP server \"${name}\"`),\n\t\t\tauthProvider,\n\t\t\tfetch: config.auth ? providerFetch(url) : undefined,\n\t\t});\n\t}\n\tif (!config.command) throw new Error(`MCP server \"${name}\" has no command or url`);\n\tconst env: Record<string, string> = {};\n\tfor (const [key, value] of Object.entries(config.env ?? {})) {\n\t\tenv[key] = resolveConfigValueOrThrow(value, `MCP server \"${name}\" env \"${key}\"`);\n\t}\n\treturn new StdioTransport({\n\t\tcommand: expandHome(config.command),\n\t\targs: config.args?.map(expandHome),\n\t\tcwd: resolve(cwd, expandHome(config.cwd ?? \".\")),\n\t\tenv,\n\t\tstderr: \"pipe\",\n\t});\n}\n\n/** Servers that do not implement `resources/templates/list` have no templates. */\nasync function withoutTemplates<T>(list: () => Promise<T>, empty: T): Promise<T> {\n\ttry {\n\t\treturn await list();\n\t} catch (error) {\n\t\tif (error instanceof McpError && error.code === JSON_RPC_ERROR_CODES.methodNotFound) return empty;\n\t\tthrow error;\n\t}\n}\n\nfunction listTemplates(client: McpClient, options: McpRequestOptions = {}): Promise<ResourceTemplate[]> {\n\treturn withoutTemplates(() => client.listResourceTemplates(options), []);\n}\n\n/**\n * Resources and templates at connect time, for the counts in `/mcp` and `pi mcp list`. A server\n * whose lists fail still connects: the resource tools list and read its resources on demand.\n */\nasync function fetchResources(\n\tclient: McpClient,\n): Promise<{ resources: Resource[]; resourceTemplates: ResourceTemplate[] }> {\n\tconst [resources, resourceTemplates] = await Promise.all([\n\t\tclient.listResources().catch(() => []),\n\t\tlistTemplates(client).catch(() => []),\n\t]);\n\treturn {\n\t\tresources: resources.filter((resource) => !isMcpAppResource(resource)),\n\t\tresourceTemplates: resourceTemplates.filter((template) => !isMcpAppResource(template)),\n\t};\n}\n\n/** One configured server. Reconnects lazily when a call finds the connection gone. */\nexport class McpServerConnection implements McpToolCaller, McpResourceServer {\n\treadonly entry: McpServerEntry;\n\tstate: ServerState = \"connecting\";\n\terror: string | undefined;\n\ttools: McpTool[] = [];\n\t/**\n\t * Whether the server offers resources. The lists below are what it listed at the last connect or\n\t * change, without MCP App resources.\n\t */\n\thasResources = false;\n\tresources: Resource[] = [];\n\tresourceTemplates: ResourceTemplate[] = [];\n\t/** Server instructions from `initialize`, describing its tools as a group. */\n\tinstructions: string | undefined;\n\t/** Last OAuth challenge from the server; sign-in uses its resource metadata URL and scope. */\n\tchallenge: OAuthChallenge | undefined;\n\tprivate client: McpClient | undefined;\n\tprivate opening: Promise<McpClient> | undefined;\n\tprivate initializingClient: McpClient | undefined;\n\tprivate initializingTransport: McpTransport | undefined;\n\tprivate closing: Promise<void> | undefined;\n\tprivate readonly activeRequests = new Map<McpClient, number>();\n\tprivate readonly retiringClients = new Map<McpClient, { promise: Promise<void>; close: () => Promise<void> }>();\n\tprivate closed = false;\n\t/** Stderr of the last stdio server that failed to connect. */\n\tprivate stderrTail: string | undefined;\n\tprivate readonly cwd: string;\n\tprivate readonly createTransport: McpTransportFactory;\n\tprivate readonly authProvider: McpAuthProvider | undefined;\n\tprivate readonly onTools: (connection: McpServerConnection) => void;\n\tprivate readonly onChange: ((connection: McpServerConnection) => void) | undefined;\n\tprivate readonly log: McpServerLog | undefined;\n\n\tconstructor(options: {\n\t\tentry: McpServerEntry;\n\t\tcwd: string;\n\t\tcreateTransport: McpTransportFactory;\n\t\tcredentials: McpOAuthCredentialStore;\n\t\t/** The current token of a pi provider, for servers with `auth.provider`. */\n\t\tproviderToken?: (provider: string) => Promise<string | undefined>;\n\t\tonTools: (connection: McpServerConnection) => void;\n\t\t/** Called when `state`, `error`, or `tools` change. */\n\t\tonChange?: (connection: McpServerConnection) => void;\n\t\t/** Receives the server's log messages (`notifications/message`). */\n\t\tlog?: McpServerLog;\n\t}) {\n\t\tconst config = options.entry.config;\n\t\t// Resolve once so the credential key, destination check, and transport use the same URL.\n\t\tthis.entry =\n\t\t\t\"url\" in config\n\t\t\t\t? { ...options.entry, config: { ...config, url: resolveMcpServerUrl(config.url) } }\n\t\t\t\t: options.entry;\n\t\tthis.cwd = options.cwd;\n\t\tthis.createTransport = options.createTransport;\n\t\tthis.onTools = options.onTools;\n\t\tthis.onChange = options.onChange;\n\t\tthis.log = options.log;\n\t\tconst url = this.oauthUrl;\n\t\tconst provider = providerAuthName(this.entry);\n\t\tif (provider && \"url\" in this.entry.config) validateProviderDestination(this.entry.config.url);\n\t\tthis.authProvider = url\n\t\t\t? createMcpAuthProvider({\n\t\t\t\t\tserverUrl: url,\n\t\t\t\t\tstore: options.credentials.forServer(this.entry.name, url),\n\t\t\t\t\tsettings: () => this.oauthSettings(),\n\t\t\t\t\tonChallenge: (challenge) => {\n\t\t\t\t\t\tthis.challenge = challenge;\n\t\t\t\t\t},\n\t\t\t\t})\n\t\t\t: provider\n\t\t\t\t? // Read on every request, so the provider's refreshes apply; MCP stores no copy.\n\t\t\t\t\t{ token: async () => options.providerToken?.(provider), settled: async () => {} }\n\t\t\t\t: undefined;\n\t}\n\n\tget name(): string {\n\t\treturn this.entry.name;\n\t}\n\n\tget timeoutMs(): number {\n\t\treturn (this.entry.config.timeout ?? DEFAULT_TIMEOUT_SECONDS) * 1000;\n\t}\n\n\t/** Server URL when the server authenticates with OAuth. */\n\tget oauthUrl(): string | undefined {\n\t\treturn \"url\" in this.entry.config && usesOAuth(this.entry) ? this.entry.config.url : undefined;\n\t}\n\n\toauthSettings(): McpOAuthSettings {\n\t\tconst oauth = \"url\" in this.entry.config ? this.entry.config.oauth : undefined;\n\t\tif (!oauth) return {};\n\t\treturn {\n\t\t\tclientId: oauth.clientId,\n\t\t\tclientSecret:\n\t\t\t\toauth.clientSecret === undefined\n\t\t\t\t\t? undefined\n\t\t\t\t\t: resolveConfigValueOrThrow(oauth.clientSecret, `MCP server \"${this.entry.name}\" oauth.clientSecret`),\n\t\t\tcallbackPort: oauth.callbackPort,\n\t\t\tcallbackUrl: oauth.callbackUrl,\n\t\t\tscope: oauth.scope,\n\t\t\tclientName: oauth.clientName,\n\t\t\tauthServerMetadataUrl: oauth.authServerMetadataUrl ? new URL(oauth.authServerMetadataUrl) : undefined,\n\t\t};\n\t}\n\n\tgetClient(): Promise<McpClient> {\n\t\tif (this.closed) return Promise.reject(new Error(`MCP server \"${this.entry.name}\" is shut down`));\n\t\tif (this.client?.connectionState === \"connected\") return Promise.resolve(this.client);\n\t\tthis.opening ??= this.open().finally(() => {\n\t\t\tthis.opening = undefined;\n\t\t});\n\t\treturn this.opening;\n\t}\n\n\tcallTool(name: string, args: Record<string, unknown>, options: McpRequestOptions): Promise<CallToolResult> {\n\t\treturn this.withClient((client) => client.callTool(name, args, options));\n\t}\n\n\treadResource(uri: string, options: McpRequestOptions): Promise<ReadResourceResult> {\n\t\treturn this.withClient((client) => client.readResource(uri, options), true);\n\t}\n\n\tresourcesPage(cursor: string | undefined, options: McpRequestOptions): Promise<ListResourcesResult> {\n\t\treturn this.withClient((client) => client.listResourcesPage(cursor, options), true);\n\t}\n\n\tresourceTemplatesPage(cursor: string | undefined, options: McpRequestOptions): Promise<ListResourceTemplatesResult> {\n\t\treturn this.withClient(\n\t\t\t(client) =>\n\t\t\t\twithoutTemplates(() => client.listResourceTemplatesPage(cursor, options), { resourceTemplates: [] }),\n\t\t\ttrue,\n\t\t);\n\t}\n\n\tallResources(options: McpRequestOptions): Promise<Resource[]> {\n\t\treturn this.withClient((client) => client.listResources(options), true);\n\t}\n\n\tallResourceTemplates(options: McpRequestOptions): Promise<ResourceTemplate[]> {\n\t\treturn this.withClient((client) => listTemplates(client, options), true);\n\t}\n\n\t/**\n\t * Run a request, reconnecting when needed. `readOnly` requests are retried once after a transient\n\t * HTTP error; tool calls are not, since they may have run.\n\t */\n\tprivate async withClient<T>(run: (client: McpClient) => Promise<T>, readOnly = false): Promise<T> {\n\t\tfor (let attempt = 1; ; attempt++) {\n\t\t\tconst client = await this.getClient();\n\t\t\ttry {\n\t\t\t\treturn await this.runWithClient(client, run);\n\t\t\t} catch (error) {\n\t\t\t\tif (readOnly && attempt === 1 && error instanceof McpHttpError && isTransientError(error)) {\n\t\t\t\t\tawait new Promise((resolve) => setTimeout(resolve, CONNECT_RETRY_DELAYS_MS[0]));\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (error instanceof McpSessionExpiredError && attempt === 1) {\n\t\t\t\t\tif (this.closed) throw error;\n\t\t\t\t\tconst retirement = this.dropClient(client, true);\n\t\t\t\t\tif (!this.activeRequests.has(client)) await retirement;\n\t\t\t\t\tif (this.closed) throw error;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (!this.needsSignIn(error)) throw error;\n\t\t\t\tawait this.dropClient(client);\n\t\t\t\tthis.markNeedsAuth();\n\t\t\t\tthrow new Error(signInRequiredMessage(this.entry));\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate async runWithClient<T>(client: McpClient, run: (client: McpClient) => Promise<T>): Promise<T> {\n\t\tthis.activeRequests.set(client, (this.activeRequests.get(client) ?? 0) + 1);\n\t\ttry {\n\t\t\treturn await run(client);\n\t\t} finally {\n\t\t\tconst remaining = (this.activeRequests.get(client) ?? 1) - 1;\n\t\t\tif (remaining > 0) {\n\t\t\t\tthis.activeRequests.set(client, remaining);\n\t\t\t} else {\n\t\t\t\tthis.activeRequests.delete(client);\n\t\t\t\tvoid this.retiringClients.get(client)?.close();\n\t\t\t}\n\t\t}\n\t}\n\n\t/** Connect again with fresh credentials, for example after signing in. */\n\tasync reconnect(): Promise<void> {\n\t\tawait this.opening?.catch(() => undefined);\n\t\tif (this.client) await this.dropClient(this.client);\n\t\tawait this.getClient();\n\t}\n\n\t/** Disconnect after the stored credentials were removed. */\n\tasync signOut(): Promise<void> {\n\t\tawait this.opening?.catch(() => undefined);\n\t\tif (this.client) await this.dropClient(this.client);\n\t\tif (!this.closed) this.markNeedsAuth();\n\t}\n\n\t/** OAuth servers that still reject the request after a refresh need the user to sign in again. */\n\tprivate needsSignIn(error: unknown): boolean {\n\t\treturn (\n\t\t\terror instanceof McpOAuthAuthorizationRequiredError ||\n\t\t\t(this.authProvider !== undefined && error instanceof McpAuthRequiredError)\n\t\t);\n\t}\n\n\tprivate markNeedsAuth(): void {\n\t\tthis.state = \"needs-auth\";\n\t\tthis.error = undefined;\n\t\tthis.changed();\n\t}\n\n\tprivate changed(): void {\n\t\tthis.onChange?.(this);\n\t}\n\n\tprivate dropClient(client: McpClient, drainRequests = false): Promise<void> {\n\t\tif (this.client === client) this.client = undefined;\n\t\tconst pending = this.retiringClients.get(client);\n\t\tif (pending) {\n\t\t\tif (!drainRequests) void pending.close();\n\t\t\treturn pending.promise;\n\t\t}\n\t\tlet resolve!: () => void;\n\t\tconst promise = new Promise<void>((done) => {\n\t\t\tresolve = done;\n\t\t});\n\t\tlet closing: Promise<void> | undefined;\n\t\tconst close = () => {\n\t\t\tclosing ??= client\n\t\t\t\t.close()\n\t\t\t\t.catch(() => undefined)\n\t\t\t\t.finally(() => {\n\t\t\t\t\tthis.retiringClients.delete(client);\n\t\t\t\t\tresolve();\n\t\t\t\t});\n\t\t\treturn closing;\n\t\t};\n\t\tthis.retiringClients.set(client, { promise, close });\n\t\tif (!drainRequests || !this.activeRequests.has(client)) void close();\n\t\treturn promise;\n\t}\n\n\tprivate async open(): Promise<McpClient> {\n\t\tthis.state = \"connecting\";\n\t\tthis.changed();\n\t\tconst retries = \"url\" in this.entry.config ? CONNECT_RETRY_DELAYS_MS : [];\n\t\tfor (let attempt = 0; ; attempt++) {\n\t\t\tthis.stderrTail = undefined;\n\t\t\ttry {\n\t\t\t\treturn await this.connectOnce();\n\t\t\t} catch (error) {\n\t\t\t\tconst delay = retries[attempt];\n\t\t\t\tif (this.closed || delay === undefined || !isTransientError(error)) {\n\t\t\t\t\tthrow this.connectFailed(error);\n\t\t\t\t}\n\t\t\t\tawait new Promise((resolve) => setTimeout(resolve, delay));\n\t\t\t\tif (this.closed) throw this.connectFailed(error);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate async connectOnce(): Promise<McpClient> {\n\t\tif (this.closed) throw new Error(\"shut down while connecting\");\n\t\tconst client = new McpClient({\n\t\t\tname: \"pi\",\n\t\t\tversion: VERSION,\n\t\t\trequestTimeoutMs: this.timeoutMs,\n\t\t\troots: [{ uri: pathToFileURL(this.cwd).href, name: basename(this.cwd) }],\n\t\t});\n\t\tthis.initializingClient = client;\n\t\tconst log = this.log;\n\t\tif (log) client.onNotification(\"notifications/message\", (params) => log.write(this.entry.name, params));\n\t\tlet transport: McpTransport | undefined;\n\t\ttry {\n\t\t\ttransport = this.createTransport(this.entry, this.cwd, this.authProvider);\n\t\t\tthis.initializingTransport = transport;\n\t\t\tif (this.closed) throw new Error(\"shut down while connecting\");\n\t\t\tawait client.connect(transport);\n\t\t\tclient.onNotification(\"notifications/tools/list_changed\", () => {\n\t\t\t\tvoid this.refreshTools(client);\n\t\t\t});\n\t\t\tclient.onNotification(\"notifications/resources/list_changed\", () => {\n\t\t\t\tvoid this.refreshResources(client);\n\t\t\t});\n\t\t\tconst stdio = transport instanceof StdioTransport ? transport : undefined;\n\t\t\tclient.onClose(() => this.handleClientClose(client, stdio));\n\t\t\t// Servers without the tools capability (prompts or resources only) do not answer tools/list.\n\t\t\tconst hasResources = client.serverCapabilities?.resources !== undefined;\n\t\t\tconst [tools, resources] = await Promise.all([\n\t\t\t\tclient.serverCapabilities?.tools ? client.listTools() : [],\n\t\t\t\thasResources ? fetchResources(client) : { resources: [], resourceTemplates: [] },\n\t\t\t]);\n\t\t\tif (this.closed) throw new Error(\"shut down while connecting\");\n\t\t\tif (client.connectionState !== \"connected\") throw new Error(\"connection closed during setup\");\n\t\t\tthis.client = client;\n\t\t\tthis.tools = tools;\n\t\t\tthis.hasResources = hasResources;\n\t\t\tthis.resources = resources.resources;\n\t\t\tthis.resourceTemplates = resources.resourceTemplates;\n\t\t\tthis.instructions = client.instructions?.trim() || undefined;\n\t\t\tthis.state = \"connected\";\n\t\t\tthis.error = undefined;\n\t\t\tthis.onTools(this);\n\t\t\tthis.changed();\n\t\t\treturn client;\n\t\t} catch (error) {\n\t\t\tawait client.close().catch(() => undefined);\n\t\t\tif (transport instanceof StdioTransport) {\n\t\t\t\tthis.stderrTail = transport.stderr.trim().slice(-STDERR_TAIL_CHARS) || undefined;\n\t\t\t}\n\t\t\tthrow error;\n\t\t} finally {\n\t\t\t// A delayed start may allocate resources after its first close. Retire them too.\n\t\t\tif (this.closed) await transport?.close().catch(() => undefined);\n\t\t\tif (this.initializingClient === client) {\n\t\t\t\tthis.initializingClient = undefined;\n\t\t\t\tthis.initializingTransport = undefined;\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate connectFailed(error: unknown): Error {\n\t\tif (this.needsSignIn(error) && !this.closed) {\n\t\t\tthis.markNeedsAuth();\n\t\t\treturn new Error(signInRequiredMessage(this.entry));\n\t\t}\n\t\tthis.state = this.closed ? \"closed\" : \"failed\";\n\t\tthis.error = this.stderrTail ? `${errorMessage(error)}\\n${this.stderrTail}` : errorMessage(error);\n\t\tthis.changed();\n\t\treturn new Error(`MCP server \"${this.entry.name}\" failed to connect: ${this.error}`);\n\t}\n\n\t/** The transport dropped. The next call reconnects; until then the status shows why. */\n\tprivate handleClientClose(client: McpClient, stdio: StdioTransport | undefined): void {\n\t\tif (this.client !== client || this.closed) return;\n\t\tthis.client = undefined;\n\t\tthis.state = \"disconnected\";\n\t\tconst stderr = stdio?.stderr.trim().slice(-STDERR_TAIL_CHARS);\n\t\tthis.error = stderr ? `Connection closed\\n${stderr}` : \"Connection closed\";\n\t\tthis.changed();\n\t}\n\n\tprivate async refreshTools(client: McpClient): Promise<void> {\n\t\ttry {\n\t\t\tconst tools = await this.runWithClient(client, (client) => client.listTools());\n\t\t\tif (this.client !== client || this.closed) return;\n\t\t\tthis.tools = tools;\n\t\t\tthis.onTools(this);\n\t\t} catch (error) {\n\t\t\tthis.error = `Failed to refresh tools: ${errorMessage(error)}`;\n\t\t}\n\t\tthis.changed();\n\t}\n\n\tprivate async refreshResources(client: McpClient): Promise<void> {\n\t\tconst { resources, resourceTemplates } = await this.runWithClient(client, fetchResources);\n\t\tif (this.client !== client || this.closed) return;\n\t\tthis.resources = resources;\n\t\tthis.resourceTemplates = resourceTemplates;\n\t\tthis.onTools(this);\n\t\tthis.changed();\n\t}\n\n\tclose(): Promise<void> {\n\t\tif (this.closing) return this.closing;\n\t\tthis.closed = true;\n\t\tthis.state = \"closed\";\n\t\tthis.changed();\n\t\tconst client = this.client;\n\t\tthis.client = undefined;\n\t\tconst opening = this.opening;\n\t\tconst initializingClient = this.initializingClient;\n\t\tconst initializingTransport = this.initializingTransport;\n\t\t// Close immediately, before waiting for setup: start itself may need close to unblock.\n\t\tconst retirement = Promise.allSettled([\n\t\t\tclient?.close(),\n\t\t\tinitializingClient?.close(),\n\t\t\tinitializingTransport?.close(),\n\t\t\topening,\n\t\t\t...[...this.retiringClients.values()].map((retirement) => retirement.close()),\n\t\t]);\n\t\tthis.closing = (async () => {\n\t\t\tawait boundedRetirement(retirement);\n\t\t\t// Preserve an already-rotated refresh token before exiting.\n\t\t\tawait this.authProvider?.settled();\n\t\t})();\n\t\treturn this.closing;\n\t}\n}\n"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -56,7 +56,7 @@ export { nextRetryDecision, type RetryDecision, type RetryPolicySettings } from
|
|
|
56
56
|
export { AgentSessionRuntime, type AgentSessionRuntimeDiagnostic, type AgentSessionServices, type AtomicBuiltin, type CreateAgentSessionFromServicesOptions, type CreateAgentSessionOptions, type CreateAgentSessionResult, type CreateAgentSessionRuntimeFactory, type CreateAgentSessionRuntimeResult, type CreateAgentSessionServicesOptions, createAgentSession, createAgentSessionFromServices, createAgentSessionRuntime, createAgentSessionServices, createBashTool, createCodingTools, createEditTool, createFindTool, createLsTool, createPowerShellTool, createReadOnlyTools, createReadTool, createSearchTool, createStructuredOutputCapture, createStructuredOutputTool, createWriteTool, type JsonObject, type JsonPrimitive, type JsonValue, type MessageEndEvent, type MessageStartEvent, type MessageUpdateEvent, type PromptTemplate, STRUCTURED_OUTPUT_TOOL_NAME, type StructuredOutputCapture, type StructuredOutputFileCapture, type StructuredOutputToolOptions, type ToolExecutionEndEvent, type ToolExecutionStartEvent, type ToolExecutionUpdateEvent, } from "./core/sdk.ts";
|
|
57
57
|
export { type BranchSummaryEntry, buildContextEntries, buildSessionContext, buildSessionProjection, type CompactionEntry, type ContextEditableContent, type ContextEditEntry, CURRENT_SESSION_VERSION, type CustomEntry, type CustomMessageEntry, type FileEntry, getLatestCompactionBoundaryEntry, type ModelChangeEntry, migrateSessionEntries, type NewSessionOptions, type ProjectedSessionEntry, parseSessionEntries, type SessionContext, type SessionEntry, type SessionEntryBase, type SessionHeader, type SessionInfo, type SessionInfoEntry, SessionManager, type SessionMessageEntry, type SessionNameState, type SessionProjection, type SessionTreeNode, type SessionWorkflowMetadata, sessionEntryToContextMessages, type ThinkingLevelChangeEntry, } from "./core/session-manager.ts";
|
|
58
58
|
export { WORKFLOW_SESSION_METADATA_ENV, workflowSessionMetadataFromEnv, } from "./core/session-manager-classification.ts";
|
|
59
|
-
export type { DefaultProjectTrust } from "./core/settings-manager.ts";
|
|
59
|
+
export type { DefaultProjectTrust, QuietStartup } from "./core/settings-manager.ts";
|
|
60
60
|
export { type CompactionModelOverride, type CompactionSettings, type ImageSettings, type ModelRoutingSettings, type PackageSource, type RetrySettings, SettingsManager, type SettingsManagerCreateOptions, } from "./core/settings-manager.ts";
|
|
61
61
|
export { formatSkillsForPrompt, type LoadSkillsFromDirOptions, type LoadSkillsResult, loadSkills, loadSkillsFromDir, type Skill, type SkillFrontmatter, } from "./core/skills.ts";
|
|
62
62
|
export { createSyntheticSourceInfo } from "./core/source-info.ts";
|