@cnwenf/occ 2.1.340 → 2.1.341
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/dist/cli.js +475 -90
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
|
-
globalThis.MACRO={"VERSION":"2.1.
|
|
2
|
+
globalThis.MACRO={"VERSION":"2.1.341","BINARY_NAME":"occ","BUILD_TIME":"2026-09-18T01:06:37.948Z","FEEDBACK_CHANNEL":"","ISSUES_EXPLAINER":"","NATIVE_PACKAGE_URL":"","PACKAGE_URL":"@cnwenf/occ","VERSION_CHANGELOG":""};
|
|
3
3
|
// @bun
|
|
4
4
|
var __create = Object.create;
|
|
5
5
|
var __getProtoOf = Object.getPrototypeOf;
|
|
@@ -627164,6 +627164,52 @@ async function fetchAuthServerMetadata(serverName, serverUrl, configuredMetadata
|
|
|
627164
627164
|
...fetchFn && { fetchFn }
|
|
627165
627165
|
});
|
|
627166
627166
|
}
|
|
627167
|
+
function getOAuthCallbackSubmitter(serverName) {
|
|
627168
|
+
return oauthCallbackSubmitters.get(serverName);
|
|
627169
|
+
}
|
|
627170
|
+
function setActiveOAuthPromise(serverName, promise3) {
|
|
627171
|
+
activeOAuthFlows.set(serverName, promise3);
|
|
627172
|
+
promise3.finally(() => {
|
|
627173
|
+
if (activeOAuthFlows.get(serverName) === promise3) {
|
|
627174
|
+
activeOAuthFlows.delete(serverName);
|
|
627175
|
+
}
|
|
627176
|
+
}).catch(() => {});
|
|
627177
|
+
}
|
|
627178
|
+
function getActiveOAuthPromise(serverName) {
|
|
627179
|
+
return activeOAuthFlows.get(serverName);
|
|
627180
|
+
}
|
|
627181
|
+
function createManualCallbackSubmitter(serverName, oauthState, hooks) {
|
|
627182
|
+
return (callbackUrl) => {
|
|
627183
|
+
try {
|
|
627184
|
+
const parsed = new URL(callbackUrl);
|
|
627185
|
+
const code = parsed.searchParams.get("code");
|
|
627186
|
+
const state3 = parsed.searchParams.get("state");
|
|
627187
|
+
const error52 = parsed.searchParams.get("error");
|
|
627188
|
+
if (!code && !error52) {
|
|
627189
|
+
return false;
|
|
627190
|
+
}
|
|
627191
|
+
if (state3 !== oauthState) {
|
|
627192
|
+
logMCPDebug(serverName, "Ignoring manual callback URL whose state belongs to a different flow");
|
|
627193
|
+
return false;
|
|
627194
|
+
}
|
|
627195
|
+
if (error52) {
|
|
627196
|
+
const errorDescription = parsed.searchParams.get("error_description") || "";
|
|
627197
|
+
hooks.cleanup();
|
|
627198
|
+
hooks.rejectFlow(new Error(`OAuth error: ${error52} - ${errorDescription}`));
|
|
627199
|
+
return true;
|
|
627200
|
+
}
|
|
627201
|
+
if (!code) {
|
|
627202
|
+
return false;
|
|
627203
|
+
}
|
|
627204
|
+
logMCPDebug(serverName, "Received auth code via manual callback URL");
|
|
627205
|
+
hooks.cleanup();
|
|
627206
|
+
hooks.resolveCode(code);
|
|
627207
|
+
return true;
|
|
627208
|
+
} catch {
|
|
627209
|
+
return false;
|
|
627210
|
+
}
|
|
627211
|
+
};
|
|
627212
|
+
}
|
|
627167
627213
|
function getServerKey(serverName, serverConfig) {
|
|
627168
627214
|
const configJson = jsonStringify({
|
|
627169
627215
|
type: serverConfig.type,
|
|
@@ -627521,6 +627567,7 @@ async function performMCPOAuthFlow(serverName, serverConfig, onAuthorizationUrl,
|
|
|
627521
627567
|
let server = null;
|
|
627522
627568
|
let timeoutId = null;
|
|
627523
627569
|
let abortHandler = null;
|
|
627570
|
+
let manualSubmitter = null;
|
|
627524
627571
|
const cleanup2 = () => {
|
|
627525
627572
|
if (server) {
|
|
627526
627573
|
server.removeAllListeners();
|
|
@@ -627536,6 +627583,13 @@ async function performMCPOAuthFlow(serverName, serverConfig, onAuthorizationUrl,
|
|
|
627536
627583
|
abortSignal.removeEventListener("abort", abortHandler);
|
|
627537
627584
|
abortHandler = null;
|
|
627538
627585
|
}
|
|
627586
|
+
if (manualSubmitter && oauthCallbackSubmitters.get(serverName) === manualSubmitter) {
|
|
627587
|
+
oauthCallbackSubmitters.delete(serverName);
|
|
627588
|
+
}
|
|
627589
|
+
if (manualSubmitter && oauthFlowRecords.get(serverName)?.submitter === manualSubmitter) {
|
|
627590
|
+
oauthFlowRecords.delete(serverName);
|
|
627591
|
+
}
|
|
627592
|
+
manualSubmitter = null;
|
|
627539
627593
|
logMCPDebug(serverName, `MCP OAuth server cleaned up`);
|
|
627540
627594
|
};
|
|
627541
627595
|
const authorizationCode = await new Promise((resolve53, reject2) => {
|
|
@@ -627563,32 +627617,37 @@ async function performMCPOAuthFlow(serverName, serverConfig, onAuthorizationUrl,
|
|
|
627563
627617
|
}
|
|
627564
627618
|
abortSignal.addEventListener("abort", abortHandler);
|
|
627565
627619
|
}
|
|
627566
|
-
|
|
627567
|
-
|
|
627568
|
-
|
|
627569
|
-
|
|
627570
|
-
|
|
627571
|
-
|
|
627572
|
-
|
|
627573
|
-
|
|
627574
|
-
|
|
627575
|
-
|
|
627576
|
-
|
|
627577
|
-
|
|
627578
|
-
|
|
627579
|
-
|
|
627580
|
-
|
|
627581
|
-
|
|
627582
|
-
|
|
627583
|
-
|
|
627584
|
-
|
|
627585
|
-
|
|
627586
|
-
|
|
627587
|
-
|
|
627588
|
-
|
|
627589
|
-
|
|
627590
|
-
|
|
627591
|
-
}
|
|
627620
|
+
manualSubmitter = createManualCallbackSubmitter(serverName, oauthState, {
|
|
627621
|
+
cleanup: cleanup2,
|
|
627622
|
+
resolveCode: resolveOnce,
|
|
627623
|
+
rejectFlow: rejectOnce
|
|
627624
|
+
});
|
|
627625
|
+
const supersededFlow = oauthFlowRecords.get(serverName);
|
|
627626
|
+
if (supersededFlow) {
|
|
627627
|
+
logMCPDebug(serverName, `Cancelling superseded OAuth flow (epoch ${supersededFlow.epoch}) \u2014 a newer flow is taking over`);
|
|
627628
|
+
supersededFlow.cancel();
|
|
627629
|
+
}
|
|
627630
|
+
const flowRecord = {
|
|
627631
|
+
epoch: ++oauthFlowEpochCounter,
|
|
627632
|
+
submitter: manualSubmitter,
|
|
627633
|
+
cancel: () => {
|
|
627634
|
+
cleanup2();
|
|
627635
|
+
rejectOnce(new AuthenticationCancelledError);
|
|
627636
|
+
}
|
|
627637
|
+
};
|
|
627638
|
+
oauthFlowRecords.set(serverName, flowRecord);
|
|
627639
|
+
oauthCallbackSubmitters.set(serverName, manualSubmitter);
|
|
627640
|
+
try {
|
|
627641
|
+
options?.onWaitingForCallback?.(manualSubmitter, redirectUri, oauthState);
|
|
627642
|
+
} catch (callbackError) {
|
|
627643
|
+
if (oauthCallbackSubmitters.get(serverName) === manualSubmitter) {
|
|
627644
|
+
oauthCallbackSubmitters.delete(serverName);
|
|
627645
|
+
}
|
|
627646
|
+
if (oauthFlowRecords.get(serverName) === flowRecord) {
|
|
627647
|
+
oauthFlowRecords.delete(serverName);
|
|
627648
|
+
}
|
|
627649
|
+
manualSubmitter = null;
|
|
627650
|
+
throw callbackError;
|
|
627592
627651
|
}
|
|
627593
627652
|
server = createServer6((req, res) => {
|
|
627594
627653
|
const parsedUrl = parse14(req.url || "", true);
|
|
@@ -628428,7 +628487,7 @@ function getScopeFromMetadata(metadata) {
|
|
|
628428
628487
|
}
|
|
628429
628488
|
return;
|
|
628430
628489
|
}
|
|
628431
|
-
var import_xss2, AUTH_REQUEST_TIMEOUT_MS = 30000, MAX_LOCK_RETRIES = 5, SENSITIVE_OAUTH_PARAMS, NONSTANDARD_INVALID_GRANT_ALIASES, AuthenticationCancelledError;
|
|
628490
|
+
var import_xss2, AUTH_REQUEST_TIMEOUT_MS = 30000, MAX_LOCK_RETRIES = 5, SENSITIVE_OAUTH_PARAMS, NONSTANDARD_INVALID_GRANT_ALIASES, AuthenticationCancelledError, oauthCallbackSubmitters, activeOAuthFlows, oauthFlowRecords, oauthFlowEpochCounter = 0;
|
|
628432
628491
|
var init_auth11 = __esm(() => {
|
|
628433
628492
|
init_auth10();
|
|
628434
628493
|
init_errors12();
|
|
@@ -628468,6 +628527,9 @@ var init_auth11 = __esm(() => {
|
|
|
628468
628527
|
this.name = "AuthenticationCancelledError";
|
|
628469
628528
|
}
|
|
628470
628529
|
};
|
|
628530
|
+
oauthCallbackSubmitters = new Map;
|
|
628531
|
+
activeOAuthFlows = new Map;
|
|
628532
|
+
oauthFlowRecords = new Map;
|
|
628471
628533
|
});
|
|
628472
628534
|
|
|
628473
628535
|
// src/services/mcp/displaySanitize.ts
|
|
@@ -628532,20 +628594,205 @@ var init_displaySanitize = __esm(() => {
|
|
|
628532
628594
|
INVISIBLE_PATTERN = /[\p{Cc}\p{Cf}\p{Zl}\p{Zp}\p{Default_Ignorable_Code_Point}\u2800]|(?!\u0020)\p{Zs}/gu;
|
|
628533
628595
|
});
|
|
628534
628596
|
|
|
628597
|
+
// src/tools/McpAuthTool/mcpAuthStubShared.ts
|
|
628598
|
+
function isRemoteOAuthSession() {
|
|
628599
|
+
return env4.isSSH() || isEnvTruthy(process.env.CLAUDE_CODE_REMOTE);
|
|
628600
|
+
}
|
|
628601
|
+
function extractOAuthRedirectUri(authUrl) {
|
|
628602
|
+
try {
|
|
628603
|
+
const redirectUri = new URL(authUrl).searchParams.get("redirect_uri");
|
|
628604
|
+
if (redirectUri) {
|
|
628605
|
+
return redirectUri;
|
|
628606
|
+
}
|
|
628607
|
+
} catch {}
|
|
628608
|
+
return "http://localhost:<port>/callback";
|
|
628609
|
+
}
|
|
628610
|
+
var MCP_AUTH_TOOL_SUFFIX = "authenticate", MCP_COMPLETE_AUTH_TOOL_SUFFIX = "complete_authentication", TOOLS_BECOME_AVAILABLE_TEXT = "available automatically", TOOLS_NOW_AVAILABLE_SENTENCE = "The server's tools should now be available.";
|
|
628611
|
+
var init_mcpAuthStubShared = __esm(() => {
|
|
628612
|
+
init_env();
|
|
628613
|
+
init_envUtils();
|
|
628614
|
+
});
|
|
628615
|
+
|
|
628616
|
+
// src/tools/McpAuthTool/McpCompleteAuthTool.ts
|
|
628617
|
+
function buildMcpCompleteAuthToolDescription(serverName) {
|
|
628618
|
+
const authenticateToolName = buildMcpToolName(serverName, MCP_AUTH_TOOL_SUFFIX);
|
|
628619
|
+
return `Complete an in-progress OAuth flow for the "${sanitizeServerNameForDisplay(serverName)}" MCP server by submitting the callback URL. Call \`${authenticateToolName}\` first to start the flow and get the authorization URL. ` + "After the user authorizes in their browser, the browser is redirected to a `http://localhost:<port>/callback?code=...&state=...` URL \u2014 " + "on remote sessions that page fails to load, but the URL in the address bar is still valid. Pass that full URL here as `callback_url`.";
|
|
628620
|
+
}
|
|
628621
|
+
function createMcpCompleteAuthTool(serverName, config7, resolveUnexpanded = resolveUnexpandedMcpServers) {
|
|
628622
|
+
const description = buildMcpCompleteAuthToolDescription(serverName);
|
|
628623
|
+
return {
|
|
628624
|
+
name: buildMcpToolName(serverName, MCP_COMPLETE_AUTH_TOOL_SUFFIX),
|
|
628625
|
+
isMcp: true,
|
|
628626
|
+
mcpInfo: { serverName, toolName: MCP_COMPLETE_AUTH_TOOL_SUFFIX },
|
|
628627
|
+
isEnabled: () => true,
|
|
628628
|
+
isConcurrencySafe: () => false,
|
|
628629
|
+
isReadOnly: () => false,
|
|
628630
|
+
toAutoClassifierInput: () => serverName,
|
|
628631
|
+
userFacingName: () => `${serverName} - complete authentication (MCP)`,
|
|
628632
|
+
maxResultSizeChars: 1e4,
|
|
628633
|
+
renderToolUseMessage: () => `Complete authentication for ${serverName} MCP server`,
|
|
628634
|
+
async description() {
|
|
628635
|
+
return description;
|
|
628636
|
+
},
|
|
628637
|
+
async prompt() {
|
|
628638
|
+
return description;
|
|
628639
|
+
},
|
|
628640
|
+
get inputSchema() {
|
|
628641
|
+
return inputSchema45();
|
|
628642
|
+
},
|
|
628643
|
+
async checkPermissions(input2) {
|
|
628644
|
+
return { behavior: "allow", updatedInput: input2 };
|
|
628645
|
+
},
|
|
628646
|
+
async call(input2) {
|
|
628647
|
+
const { callback_url: callbackUrl } = input2;
|
|
628648
|
+
const displayName = sanitizeServerNameForDisplay(serverName);
|
|
628649
|
+
const authenticateToolName = buildMcpToolName(serverName, MCP_AUTH_TOOL_SUFFIX);
|
|
628650
|
+
const submitter = getOAuthCallbackSubmitter(serverName);
|
|
628651
|
+
if (!submitter) {
|
|
628652
|
+
return {
|
|
628653
|
+
data: {
|
|
628654
|
+
status: "error",
|
|
628655
|
+
message: `No OAuth flow is in progress for ${displayName}. Call \`${authenticateToolName}\` first, then retry with the callback URL.`
|
|
628656
|
+
}
|
|
628657
|
+
};
|
|
628658
|
+
}
|
|
628659
|
+
let hasCodeOrError = false;
|
|
628660
|
+
try {
|
|
628661
|
+
const parsed = new URL(callbackUrl);
|
|
628662
|
+
hasCodeOrError = parsed.searchParams.has("code") || parsed.searchParams.has("error");
|
|
628663
|
+
} catch {}
|
|
628664
|
+
if (!hasCodeOrError) {
|
|
628665
|
+
return {
|
|
628666
|
+
data: {
|
|
628667
|
+
status: "error",
|
|
628668
|
+
message: "Invalid callback URL: missing authorization code. Ask the user to paste the full redirect URL from their browser's address bar, including the `?code=...&state=...` query string."
|
|
628669
|
+
}
|
|
628670
|
+
};
|
|
628671
|
+
}
|
|
628672
|
+
if (!submitter(callbackUrl)) {
|
|
628673
|
+
return {
|
|
628674
|
+
data: {
|
|
628675
|
+
status: "error",
|
|
628676
|
+
message: `That callback URL belongs to a different sign-in attempt for ${displayName} (its state does not match the flow in progress), or carries no authorization code. The current flow is still waiting: ask the user for the URL from the page this sign-in opened, then retry.`
|
|
628677
|
+
}
|
|
628678
|
+
};
|
|
628679
|
+
}
|
|
628680
|
+
const activeFlow = getActiveOAuthPromise(serverName);
|
|
628681
|
+
if (!activeFlow) {
|
|
628682
|
+
return {
|
|
628683
|
+
data: {
|
|
628684
|
+
status: "error",
|
|
628685
|
+
message: `The callback URL was accepted by the in-progress OAuth flow for ${displayName}, but that flow was started outside this session's tool path (e.g. \`occ mcp login\` or a headless control channel), so its token exchange cannot be tracked here. The surface that started the flow will report completion \u2014 do not retry this tool.`
|
|
628686
|
+
}
|
|
628687
|
+
};
|
|
628688
|
+
}
|
|
628689
|
+
try {
|
|
628690
|
+
await activeFlow;
|
|
628691
|
+
return {
|
|
628692
|
+
data: {
|
|
628693
|
+
status: "success",
|
|
628694
|
+
message: `Authentication complete for ${displayName}. ${TOOLS_NOW_AVAILABLE_SENTENCE}`
|
|
628695
|
+
}
|
|
628696
|
+
};
|
|
628697
|
+
} catch (err2) {
|
|
628698
|
+
if (err2 instanceof AuthenticationCancelledError) {
|
|
628699
|
+
return {
|
|
628700
|
+
data: {
|
|
628701
|
+
status: "error",
|
|
628702
|
+
message: `The OAuth flow for ${displayName} was cancelled (a newer attempt may have superseded it). Call \`${authenticateToolName}\` again to restart.`
|
|
628703
|
+
}
|
|
628704
|
+
};
|
|
628705
|
+
}
|
|
628706
|
+
return {
|
|
628707
|
+
data: {
|
|
628708
|
+
status: "error",
|
|
628709
|
+
message: `Authentication failed for ${displayName}: ${sanitizeForDisplay(redactMcpErrorDetail(serverName, config7, errorMessage(err2), resolveUnexpanded))}`
|
|
628710
|
+
}
|
|
628711
|
+
};
|
|
628712
|
+
}
|
|
628713
|
+
},
|
|
628714
|
+
mapToolResultToToolResultBlockParam(data, toolUseID) {
|
|
628715
|
+
return {
|
|
628716
|
+
tool_use_id: toolUseID,
|
|
628717
|
+
type: "tool_result",
|
|
628718
|
+
content: data.message
|
|
628719
|
+
};
|
|
628720
|
+
}
|
|
628721
|
+
};
|
|
628722
|
+
}
|
|
628723
|
+
var inputSchema45;
|
|
628724
|
+
var init_McpCompleteAuthTool = __esm(() => {
|
|
628725
|
+
init_v4();
|
|
628726
|
+
init_auth11();
|
|
628727
|
+
init_displaySanitize();
|
|
628728
|
+
init_mcpStringUtils();
|
|
628729
|
+
init_redaction();
|
|
628730
|
+
init_utils9();
|
|
628731
|
+
init_errors();
|
|
628732
|
+
init_mcpAuthStubShared();
|
|
628733
|
+
inputSchema45 = lazySchema(() => exports_external.object({
|
|
628734
|
+
callback_url: exports_external.string().describe("The full callback URL from the browser address bar after authorizing, e.g. http://localhost:<port>/callback?code=...&state=...")
|
|
628735
|
+
}));
|
|
628736
|
+
});
|
|
628737
|
+
|
|
628535
628738
|
// src/tools/McpAuthTool/McpAuthTool.ts
|
|
628739
|
+
function normalizeHostnameForMatch(hostname4) {
|
|
628740
|
+
return hostname4.toLowerCase().replace(/\.$/, "");
|
|
628741
|
+
}
|
|
628742
|
+
function isAnthropicHostedMcpUrl(url3) {
|
|
628743
|
+
if (!url3) {
|
|
628744
|
+
return false;
|
|
628745
|
+
}
|
|
628746
|
+
try {
|
|
628747
|
+
const blocked = new Set(ANTHROPIC_HOSTED_OAUTH_BLOCKED_HOSTS.map(normalizeHostnameForMatch));
|
|
628748
|
+
return blocked.has(normalizeHostnameForMatch(new URL(url3).hostname));
|
|
628749
|
+
} catch {
|
|
628750
|
+
return false;
|
|
628751
|
+
}
|
|
628752
|
+
}
|
|
628753
|
+
function renderMcpRemoveCommand(serverName) {
|
|
628754
|
+
if (!COMMAND_ARG_SAFE_PATTERN.test(serverName)) {
|
|
628755
|
+
return null;
|
|
628756
|
+
}
|
|
628757
|
+
return `occ mcp remove ${serverName}`;
|
|
628758
|
+
}
|
|
628759
|
+
function buildAnthropicHostedMessage(serverName, scope) {
|
|
628760
|
+
const base2 = `"${sanitizeServerNameForDisplay(serverName)}" is Anthropic-hosted and doesn't support local OAuth. ` + "Connect it via Settings \u2192 Connectors on claude.ai (requires " + "`claude login`), then it'll be available here automatically.";
|
|
628761
|
+
const removeCommand = scope === "local" || scope === "project" || scope === "user" ? renderMcpRemoveCommand(serverName) : null;
|
|
628762
|
+
if (!removeCommand) {
|
|
628763
|
+
return base2;
|
|
628764
|
+
}
|
|
628765
|
+
const withRemove = `${base2} Remove the stale entry with: \`${removeCommand}\``;
|
|
628766
|
+
return [...withRemove].length <= 1024 ? withRemove : base2;
|
|
628767
|
+
}
|
|
628768
|
+
function classifyMcpServerAuthBlock(serverName, config7) {
|
|
628769
|
+
if (!isMcpServerAllowedByPolicy(serverName, config7)) {
|
|
628770
|
+
return "managed-policy";
|
|
628771
|
+
}
|
|
628772
|
+
if (config7.scope === "project" && getProjectMcpServerStatus(serverName) !== "approved") {
|
|
628773
|
+
return "project-approval";
|
|
628774
|
+
}
|
|
628775
|
+
return null;
|
|
628776
|
+
}
|
|
628777
|
+
function managedPolicyBlockMessage(serverName) {
|
|
628778
|
+
return `"${sanitizeServerNameForDisplay(serverName)}" is blocked by your organization's managed policy \u2014 it can't be authenticated or reconnected here`;
|
|
628779
|
+
}
|
|
628780
|
+
function projectApprovalBlockMessage(serverName) {
|
|
628781
|
+
return `"${sanitizeServerNameForDisplay(serverName)}" is a project-scope MCP server (.mcp.json) that is not approved for this project \u2014 approve it via /mcp first, then authenticate or reconnect it`;
|
|
628782
|
+
}
|
|
628536
628783
|
function buildMcpAuthToolDescription(serverName, config7, resolveUnexpanded = resolveUnexpandedMcpServers) {
|
|
628537
628784
|
const transport = config7.type ?? "stdio";
|
|
628538
628785
|
const displayOrigin = getMcpErrorEndpoint(serverName, config7, { detail: "origin" }, resolveUnexpanded);
|
|
628539
628786
|
const location = displayOrigin && displayOrigin !== transport ? `${transport} at ${sanitizeDisplayUrl(displayOrigin, 256)}` : transport;
|
|
628540
|
-
return `The "${sanitizeServerNameForDisplay(serverName)}" MCP server (${location}) is installed but requires authentication. ` + `Call this tool to start the OAuth flow \u2014 you'll receive an authorization URL to share with the user. ` + `Once the user completes authorization in their browser, the server's real tools will become
|
|
628787
|
+
return `The "${sanitizeServerNameForDisplay(serverName)}" MCP server (${location}) is installed but requires authentication. ` + `Call this tool to start the OAuth flow \u2014 you'll receive an authorization URL to share with the user. ` + `Once the user completes authorization in their browser, the server's real tools will become ${TOOLS_BECOME_AVAILABLE_TEXT}.`;
|
|
628541
628788
|
}
|
|
628542
628789
|
function createMcpAuthTool(serverName, config7, resolveUnexpanded = resolveUnexpandedMcpServers) {
|
|
628543
628790
|
const transport = config7.type ?? "stdio";
|
|
628544
628791
|
const description = buildMcpAuthToolDescription(serverName, config7, resolveUnexpanded);
|
|
628545
628792
|
return {
|
|
628546
|
-
name: buildMcpToolName(serverName,
|
|
628793
|
+
name: buildMcpToolName(serverName, MCP_AUTH_TOOL_SUFFIX),
|
|
628547
628794
|
isMcp: true,
|
|
628548
|
-
mcpInfo: { serverName, toolName:
|
|
628795
|
+
mcpInfo: { serverName, toolName: MCP_AUTH_TOOL_SUFFIX },
|
|
628549
628796
|
isEnabled: () => true,
|
|
628550
628797
|
isConcurrencySafe: () => false,
|
|
628551
628798
|
isReadOnly: () => false,
|
|
@@ -628560,17 +628807,43 @@ function createMcpAuthTool(serverName, config7, resolveUnexpanded = resolveUnexp
|
|
|
628560
628807
|
return description;
|
|
628561
628808
|
},
|
|
628562
628809
|
get inputSchema() {
|
|
628563
|
-
return
|
|
628810
|
+
return inputSchema46();
|
|
628564
628811
|
},
|
|
628565
628812
|
async checkPermissions(input2) {
|
|
628566
628813
|
return { behavior: "allow", updatedInput: input2 };
|
|
628567
628814
|
},
|
|
628568
628815
|
async call(_input, context7) {
|
|
628816
|
+
const displayName = sanitizeServerNameForDisplay(serverName);
|
|
628817
|
+
const policyBlock = classifyMcpServerAuthBlock(serverName, config7);
|
|
628818
|
+
if (policyBlock === "managed-policy") {
|
|
628819
|
+
return {
|
|
628820
|
+
data: {
|
|
628821
|
+
status: "error",
|
|
628822
|
+
message: `${managedPolicyBlockMessage(serverName)}. Only an organization admin can change this; do not retry or ask the user to enable it.`
|
|
628823
|
+
}
|
|
628824
|
+
};
|
|
628825
|
+
}
|
|
628826
|
+
if (isMcpServerDisabled(serverName)) {
|
|
628827
|
+
return {
|
|
628828
|
+
data: {
|
|
628829
|
+
status: "error",
|
|
628830
|
+
message: `MCP server ${displayName} is disabled. Ask the user to enable it in /mcp before authenticating.`
|
|
628831
|
+
}
|
|
628832
|
+
};
|
|
628833
|
+
}
|
|
628834
|
+
if (policyBlock === "project-approval") {
|
|
628835
|
+
return {
|
|
628836
|
+
data: {
|
|
628837
|
+
status: "error",
|
|
628838
|
+
message: `${projectApprovalBlockMessage(serverName)}. Ask the user to approve it; do not retry until they have.`
|
|
628839
|
+
}
|
|
628840
|
+
};
|
|
628841
|
+
}
|
|
628569
628842
|
if (config7.type === "claudeai-proxy") {
|
|
628570
628843
|
return {
|
|
628571
628844
|
data: {
|
|
628572
628845
|
status: "unsupported",
|
|
628573
|
-
message: `This is a claude.ai MCP connector. Ask the user to run /mcp and select "${
|
|
628846
|
+
message: `This is a claude.ai MCP connector. Ask the user to run /mcp and select "${displayName}" to authenticate.`
|
|
628574
628847
|
}
|
|
628575
628848
|
};
|
|
628576
628849
|
}
|
|
@@ -628578,7 +628851,15 @@ function createMcpAuthTool(serverName, config7, resolveUnexpanded = resolveUnexp
|
|
|
628578
628851
|
return {
|
|
628579
628852
|
data: {
|
|
628580
628853
|
status: "unsupported",
|
|
628581
|
-
message: `Server "${
|
|
628854
|
+
message: `Server "${displayName}" uses ${transport} transport which does not support OAuth from this tool. Ask the user to run /mcp and authenticate manually.`
|
|
628855
|
+
}
|
|
628856
|
+
};
|
|
628857
|
+
}
|
|
628858
|
+
if (isAnthropicHostedMcpUrl(config7.url)) {
|
|
628859
|
+
return {
|
|
628860
|
+
data: {
|
|
628861
|
+
status: "unsupported",
|
|
628862
|
+
message: sanitizeForDisplay(buildAnthropicHostedMessage(serverName, config7.scope), 1024, "none")
|
|
628582
628863
|
}
|
|
628583
628864
|
};
|
|
628584
628865
|
}
|
|
@@ -628587,11 +628868,15 @@ function createMcpAuthTool(serverName, config7, resolveUnexpanded = resolveUnexp
|
|
|
628587
628868
|
const authUrlPromise = new Promise((resolve53) => {
|
|
628588
628869
|
resolveAuthUrl = resolve53;
|
|
628589
628870
|
});
|
|
628590
|
-
const controller = new AbortController;
|
|
628591
628871
|
const { setAppState } = context7;
|
|
628592
|
-
const oauthPromise = performMCPOAuthFlow(serverName, sseOrHttpConfig, (u7) => resolveAuthUrl?.(u7),
|
|
628872
|
+
const oauthPromise = performMCPOAuthFlow(serverName, sseOrHttpConfig, (u7) => resolveAuthUrl?.(u7), undefined, { skipBrowserOpen: true });
|
|
628873
|
+
setActiveOAuthPromise(serverName, oauthPromise);
|
|
628593
628874
|
oauthPromise.then(async () => {
|
|
628594
628875
|
clearMcpAuthCache();
|
|
628876
|
+
if (isMcpServerDisabled(serverName) || !isMcpServerAllowedByPolicy(serverName, config7)) {
|
|
628877
|
+
logMCPDebug(serverName, "OAuth completed but the server is now disabled or policy-blocked; not reconnecting");
|
|
628878
|
+
return;
|
|
628879
|
+
}
|
|
628595
628880
|
const result = await reconnectMcpServerImpl(serverName, config7);
|
|
628596
628881
|
const prefix = getMcpPrefix(serverName);
|
|
628597
628882
|
setAppState((prev) => ({
|
|
@@ -628612,7 +628897,7 @@ function createMcpAuthTool(serverName, config7, resolveUnexpanded = resolveUnexp
|
|
|
628612
628897
|
}));
|
|
628613
628898
|
logMCPDebug(serverName, `OAuth complete, reconnected with ${result.tools.length} tool(s)`);
|
|
628614
628899
|
}).catch((err2) => {
|
|
628615
|
-
logMCPError(serverName, `OAuth flow failed after tool-triggered start: ${errorMessage(err2)}`);
|
|
628900
|
+
logMCPError(serverName, `OAuth flow failed after tool-triggered start: ${sanitizeForDisplay(redactMcpErrorDetail(serverName, config7, errorMessage(err2), resolveUnexpanded), 2000)}`);
|
|
628616
628901
|
});
|
|
628617
628902
|
try {
|
|
628618
628903
|
const authUrl = await Promise.race([
|
|
@@ -628620,29 +628905,37 @@ function createMcpAuthTool(serverName, config7, resolveUnexpanded = resolveUnexp
|
|
|
628620
628905
|
oauthPromise.then(() => null)
|
|
628621
628906
|
]);
|
|
628622
628907
|
if (authUrl) {
|
|
628908
|
+
const completeAuthToolName = buildMcpToolName(serverName, MCP_COMPLETE_AUTH_TOOL_SUFFIX);
|
|
628909
|
+
const redirectUri = extractOAuthRedirectUri(authUrl);
|
|
628910
|
+
const callbackGuidance = isRemoteOAuthSession() ? `
|
|
628911
|
+
|
|
628912
|
+
This session is remote, so after authorizing the browser will try to load \`${redirectUri}?code=...\` and show a connection error \u2014 that's expected. Ask the user to copy the full URL from the browser's address bar and paste it into chat, then call \`${completeAuthToolName}\` with that URL as \`callback_url\`.` : `
|
|
628913
|
+
|
|
628914
|
+
If the browser shows a connection error on the redirect page, ask the user to paste the full URL from the address bar and call \`${completeAuthToolName}\` with it.`;
|
|
628623
628915
|
return {
|
|
628624
628916
|
data: {
|
|
628625
628917
|
status: "auth_url",
|
|
628626
628918
|
authUrl,
|
|
628627
|
-
message: `Ask the user to open this URL in their browser to authorize the ${
|
|
628919
|
+
message: `Ask the user to open this URL in their browser to authorize the ${displayName} MCP server:
|
|
628628
628920
|
|
|
628629
628921
|
${authUrl}
|
|
628630
628922
|
|
|
628631
|
-
Once they complete the flow, the server's tools will become
|
|
628923
|
+
Once they complete the flow, the server's tools will become ${TOOLS_BECOME_AVAILABLE_TEXT}.${callbackGuidance}`
|
|
628632
628924
|
}
|
|
628633
628925
|
};
|
|
628634
628926
|
}
|
|
628635
628927
|
return {
|
|
628636
628928
|
data: {
|
|
628637
628929
|
status: "auth_url",
|
|
628638
|
-
message: `Authentication completed silently for ${
|
|
628930
|
+
message: `Authentication completed silently for ${displayName}. ${TOOLS_NOW_AVAILABLE_SENTENCE}`
|
|
628639
628931
|
}
|
|
628640
628932
|
};
|
|
628641
628933
|
} catch (err2) {
|
|
628934
|
+
const failureDetail = sanitizeForDisplay(redactMcpErrorDetail(serverName, config7, errorMessage(err2), resolveUnexpanded));
|
|
628642
628935
|
return {
|
|
628643
628936
|
data: {
|
|
628644
628937
|
status: "error",
|
|
628645
|
-
message: `Failed to start OAuth flow for ${
|
|
628938
|
+
message: `Failed to start OAuth flow for ${displayName}: ${failureDetail}. Ask the user to run /mcp and authenticate manually.`
|
|
628646
628939
|
}
|
|
628647
628940
|
};
|
|
628648
628941
|
}
|
|
@@ -628656,19 +628949,38 @@ Once they complete the flow, the server's tools will become available automatica
|
|
|
628656
628949
|
}
|
|
628657
628950
|
};
|
|
628658
628951
|
}
|
|
628659
|
-
|
|
628952
|
+
function createMcpAuthStubTools(serverName, config7, resolveUnexpanded = resolveUnexpandedMcpServers) {
|
|
628953
|
+
if (getIsNonInteractiveSession()) {
|
|
628954
|
+
return [];
|
|
628955
|
+
}
|
|
628956
|
+
return [
|
|
628957
|
+
createMcpAuthTool(serverName, config7, resolveUnexpanded),
|
|
628958
|
+
createMcpCompleteAuthTool(serverName, config7, resolveUnexpanded)
|
|
628959
|
+
];
|
|
628960
|
+
}
|
|
628961
|
+
var inputSchema46, ANTHROPIC_HOSTED_OAUTH_BLOCKED_HOSTS, COMMAND_ARG_SAFE_PATTERN;
|
|
628660
628962
|
var init_McpAuthTool = __esm(() => {
|
|
628661
628963
|
init_reject2();
|
|
628662
628964
|
init_v4();
|
|
628965
|
+
init_state();
|
|
628663
628966
|
init_auth11();
|
|
628664
628967
|
init_client12();
|
|
628968
|
+
init_config6();
|
|
628665
628969
|
init_displaySanitize();
|
|
628666
628970
|
init_mcpStringUtils();
|
|
628667
628971
|
init_redaction();
|
|
628668
628972
|
init_utils9();
|
|
628669
628973
|
init_errors();
|
|
628670
628974
|
init_log3();
|
|
628671
|
-
|
|
628975
|
+
init_McpCompleteAuthTool();
|
|
628976
|
+
init_mcpAuthStubShared();
|
|
628977
|
+
inputSchema46 = lazySchema(() => exports_external.object({}));
|
|
628978
|
+
ANTHROPIC_HOSTED_OAUTH_BLOCKED_HOSTS = [
|
|
628979
|
+
"microsoft365.mcp.claude.com",
|
|
628980
|
+
"gmail.mcp.claude.com",
|
|
628981
|
+
"gcal.mcp.claude.com"
|
|
628982
|
+
];
|
|
628983
|
+
COMMAND_ARG_SAFE_PATTERN = /^\w[\w.@-]*$/;
|
|
628672
628984
|
});
|
|
628673
628985
|
|
|
628674
628986
|
// src/utils/mcpWebSocketTransport.ts
|
|
@@ -631869,7 +632181,7 @@ async function getMcpToolsCommandsAndResources(onConnectionAttempt, mcpConfigs)
|
|
|
631869
632181
|
logMCPDebug(name3, `Skipping connection (cached needs-auth)`);
|
|
631870
632182
|
onConnectionAttempt({
|
|
631871
632183
|
client: { name: name3, type: "needs-auth", config: config7 },
|
|
631872
|
-
tools:
|
|
632184
|
+
tools: createMcpAuthStubTools(name3, config7),
|
|
631873
632185
|
commands: []
|
|
631874
632186
|
});
|
|
631875
632187
|
return;
|
|
@@ -631878,7 +632190,7 @@ async function getMcpToolsCommandsAndResources(onConnectionAttempt, mcpConfigs)
|
|
|
631878
632190
|
if (client8.type !== "connected") {
|
|
631879
632191
|
onConnectionAttempt({
|
|
631880
632192
|
client: client8,
|
|
631881
|
-
tools: client8.type === "needs-auth" ?
|
|
632193
|
+
tools: client8.type === "needs-auth" ? createMcpAuthStubTools(name3, config7) : [],
|
|
631882
632194
|
commands: []
|
|
631883
632195
|
});
|
|
631884
632196
|
return;
|
|
@@ -793589,6 +793901,7 @@ var exports_toolPool = {};
|
|
|
793589
793901
|
__export(exports_toolPool, {
|
|
793590
793902
|
mergeAndFilterTools: () => mergeAndFilterTools,
|
|
793591
793903
|
isPrActivitySubscriptionTool: () => isPrActivitySubscriptionTool,
|
|
793904
|
+
deferInitialMcpToolsToLiveState: () => deferInitialMcpToolsToLiveState,
|
|
793592
793905
|
applyCoordinatorToolFilter: () => applyCoordinatorToolFilter
|
|
793593
793906
|
});
|
|
793594
793907
|
function isPrActivitySubscriptionTool(name3) {
|
|
@@ -793608,18 +793921,48 @@ function mergeAndFilterTools(initialTools, assembled, mode) {
|
|
|
793608
793921
|
}
|
|
793609
793922
|
return tools;
|
|
793610
793923
|
}
|
|
793611
|
-
|
|
793924
|
+
function isMcpAuthStubName(name3) {
|
|
793925
|
+
return name3.endsWith(`__${MCP_AUTH_TOOL_SUFFIX}`) || name3.endsWith(`__${MCP_COMPLETE_AUTH_TOOL_SUFFIX}`);
|
|
793926
|
+
}
|
|
793927
|
+
function deferInitialMcpToolsToLiveState(initialTools, liveClients, liveTools = []) {
|
|
793928
|
+
if (liveClients.length === 0) {
|
|
793929
|
+
return initialTools;
|
|
793930
|
+
}
|
|
793931
|
+
const clientsWithPrefix = liveClients.map((client8) => ({
|
|
793932
|
+
prefix: getMcpPrefix(client8.name),
|
|
793933
|
+
type: client8.type
|
|
793934
|
+
}));
|
|
793935
|
+
const allPrefixes = clientsWithPrefix.map((entry) => entry.prefix);
|
|
793936
|
+
const prefixesWithLiveTools = new Set(clientsWithPrefix.filter(({ prefix }) => liveTools.some((t4) => t4.name?.startsWith(prefix))).map(({ prefix }) => prefix));
|
|
793937
|
+
const stubPreservingPrefixes = new Set(clientsWithPrefix.filter(({ prefix, type }) => type !== undefined && AUTH_STUB_PRESERVING_STATES.has(type) && !prefixesWithLiveTools.has(prefix)).map(({ prefix }) => prefix));
|
|
793938
|
+
return initialTools.filter((tool) => {
|
|
793939
|
+
const name3 = tool.name;
|
|
793940
|
+
if (name3 === undefined) {
|
|
793941
|
+
return true;
|
|
793942
|
+
}
|
|
793943
|
+
for (const prefix of stubPreservingPrefixes) {
|
|
793944
|
+
if (name3.startsWith(prefix) && isMcpAuthStubName(name3)) {
|
|
793945
|
+
return true;
|
|
793946
|
+
}
|
|
793947
|
+
}
|
|
793948
|
+
return !allPrefixes.some((prefix) => name3.startsWith(prefix));
|
|
793949
|
+
});
|
|
793950
|
+
}
|
|
793951
|
+
var PR_ACTIVITY_TOOL_SUFFIXES, coordinatorModeModule2, AUTH_STUB_PRESERVING_STATES;
|
|
793612
793952
|
var init_toolPool = __esm(() => {
|
|
793613
793953
|
init_featureFlags();
|
|
793614
793954
|
init_partition();
|
|
793615
793955
|
init_uniqBy();
|
|
793616
793956
|
init_tools();
|
|
793957
|
+
init_mcpStringUtils();
|
|
793617
793958
|
init_utils9();
|
|
793959
|
+
init_mcpAuthStubShared();
|
|
793618
793960
|
PR_ACTIVITY_TOOL_SUFFIXES = [
|
|
793619
793961
|
"subscribe_pr_activity",
|
|
793620
793962
|
"unsubscribe_pr_activity"
|
|
793621
793963
|
];
|
|
793622
793964
|
coordinatorModeModule2 = feature("COORDINATOR_MODE") ? (init_coordinatorMode(), __toCommonJS(exports_coordinatorMode)) : null;
|
|
793965
|
+
AUTH_STUB_PRESERVING_STATES = new Set(["failed", "disabled"]);
|
|
793623
793966
|
});
|
|
793624
793967
|
|
|
793625
793968
|
// src/hooks/useMergedTools.ts
|
|
@@ -798942,13 +799285,13 @@ function permissionPromptToolResultToPermissionDecision(result, tool, input2, to
|
|
|
798942
799285
|
decisionReason
|
|
798943
799286
|
};
|
|
798944
799287
|
}
|
|
798945
|
-
var
|
|
799288
|
+
var inputSchema47, decisionClassificationField, PermissionAllowResultSchema, PermissionDenyResultSchema, outputSchema41;
|
|
798946
799289
|
var init_PermissionPromptToolResultSchema = __esm(() => {
|
|
798947
799290
|
init_v4();
|
|
798948
799291
|
init_debug();
|
|
798949
799292
|
init_PermissionUpdate();
|
|
798950
799293
|
init_PermissionUpdateSchema();
|
|
798951
|
-
|
|
799294
|
+
inputSchema47 = lazySchema(() => v4_default.object({
|
|
798952
799295
|
tool_name: v4_default.string().describe("The name of the tool requesting permission"),
|
|
798953
799296
|
input: v4_default.record(v4_default.string(), v4_default.unknown()).describe("The input for the tool"),
|
|
798954
799297
|
tool_use_id: v4_default.string().optional().describe("The unique tool use request ID")
|
|
@@ -805689,6 +806032,7 @@ function REPL({
|
|
|
805689
806032
|
const combinedInitialTools = import_react321.useMemo(() => {
|
|
805690
806033
|
return [...localTools, ...initialTools];
|
|
805691
806034
|
}, [localTools, initialTools]);
|
|
806035
|
+
const effectiveInitialTools = import_react321.useMemo(() => deferInitialMcpToolsToLiveState(combinedInitialTools, mcp2.clients, mcp2.tools), [combinedInitialTools, mcp2.clients, mcp2.tools]);
|
|
805692
806036
|
useManagePlugins({
|
|
805693
806037
|
enabled: !isRemoteSession
|
|
805694
806038
|
});
|
|
@@ -805710,7 +806054,7 @@ function REPL({
|
|
|
805710
806054
|
useSwarmInitialization(setAppState, initialMessages, {
|
|
805711
806055
|
enabled: !isRemoteSession
|
|
805712
806056
|
});
|
|
805713
|
-
const mergedTools = useMergedTools(
|
|
806057
|
+
const mergedTools = useMergedTools(effectiveInitialTools, mcp2.tools, toolPermissionContext);
|
|
805714
806058
|
const {
|
|
805715
806059
|
tools,
|
|
805716
806060
|
allowedAgentTypes
|
|
@@ -806726,7 +807070,7 @@ Error: sandbox required but unavailable: ${reason}
|
|
|
806726
807070
|
const computeTools = () => {
|
|
806727
807071
|
const state4 = store.getState();
|
|
806728
807072
|
const assembled = assembleToolPool(state4.toolPermissionContext, state4.mcp.tools);
|
|
806729
|
-
const merged = mergeAndFilterTools(combinedInitialTools, assembled, state4.toolPermissionContext.mode);
|
|
807073
|
+
const merged = mergeAndFilterTools(deferInitialMcpToolsToLiveState(combinedInitialTools, state4.mcp.clients, state4.mcp.tools), assembled, state4.toolPermissionContext.mode);
|
|
806730
807074
|
if (!mainThreadAgentDefinition)
|
|
806731
807075
|
return merged;
|
|
806732
807076
|
return resolveAgentTools(mainThreadAgentDefinition, merged, false, true).resolvedTools;
|
|
@@ -820057,6 +820401,42 @@ var init_remoteIO = __esm(() => {
|
|
|
820057
820401
|
};
|
|
820058
820402
|
});
|
|
820059
820403
|
|
|
820404
|
+
// src/cli/mcpOAuthCallbackControl.ts
|
|
820405
|
+
async function handleOAuthCallbackUrlControl(serverName, callbackUrl, deps) {
|
|
820406
|
+
const submit = deps.getSubmitter(serverName);
|
|
820407
|
+
if (!submit) {
|
|
820408
|
+
deps.respondError(`No active OAuth flow for server: ${serverName}`);
|
|
820409
|
+
return;
|
|
820410
|
+
}
|
|
820411
|
+
let hasCodeOrError = false;
|
|
820412
|
+
try {
|
|
820413
|
+
const parsed = new URL(callbackUrl);
|
|
820414
|
+
hasCodeOrError = parsed.searchParams.has("code") || parsed.searchParams.has("error");
|
|
820415
|
+
} catch {}
|
|
820416
|
+
if (!hasCodeOrError) {
|
|
820417
|
+
deps.respondError(CALLBACK_MISSING_CODE_MESSAGE);
|
|
820418
|
+
return;
|
|
820419
|
+
}
|
|
820420
|
+
const accepted = submit(callbackUrl);
|
|
820421
|
+
if (!accepted) {
|
|
820422
|
+
deps.respondError(CALLBACK_NOT_ACCEPTED_MESSAGE);
|
|
820423
|
+
return;
|
|
820424
|
+
}
|
|
820425
|
+
deps.markManualCallbackUsed(serverName);
|
|
820426
|
+
const authPromise = deps.getAuthPromise(serverName);
|
|
820427
|
+
if (!authPromise) {
|
|
820428
|
+
deps.respondSuccess();
|
|
820429
|
+
return;
|
|
820430
|
+
}
|
|
820431
|
+
try {
|
|
820432
|
+
await authPromise;
|
|
820433
|
+
deps.respondSuccess();
|
|
820434
|
+
} catch (error52) {
|
|
820435
|
+
deps.respondError(error52 instanceof Error ? error52.message : "OAuth authentication failed");
|
|
820436
|
+
}
|
|
820437
|
+
}
|
|
820438
|
+
var CALLBACK_NOT_ACCEPTED_MESSAGE = "Callback URL was not accepted: its state does not match the flow in progress (or it carries no authorization code). The OAuth flow is still waiting \u2014 send the redirect URL from the authorization page this flow opened.", CALLBACK_MISSING_CODE_MESSAGE = "Invalid callback URL: missing authorization code. Please paste the full redirect URL including the code parameter.";
|
|
820439
|
+
|
|
820060
820440
|
// src/utils/streamlinedTransform.ts
|
|
820061
820441
|
function categorizeToolName(toolName) {
|
|
820062
820442
|
if (SEARCH_TOOLS2.some((t4) => toolName.startsWith(t4)))
|
|
@@ -822162,7 +822542,7 @@ function runHeadlessStreaming(structuredIO, mcpClients, commands7, tools, initia
|
|
|
822162
822542
|
};
|
|
822163
822543
|
const buildAllTools = (appState) => {
|
|
822164
822544
|
const assembledTools = assembleToolPool(appState.toolPermissionContext, appState.mcp.tools);
|
|
822165
|
-
let allTools = uniqBy_default(mergeAndFilterTools([...tools, ...sdkTools, ...dynamicMcpState.tools], assembledTools, appState.toolPermissionContext.mode), "name");
|
|
822545
|
+
let allTools = uniqBy_default(mergeAndFilterTools(deferInitialMcpToolsToLiveState([...tools, ...sdkTools, ...dynamicMcpState.tools], appState.mcp.clients, appState.mcp.tools), assembledTools, appState.toolPermissionContext.mode), "name");
|
|
822166
822546
|
if (options.permissionPromptToolName) {
|
|
822167
822547
|
allTools = allTools.filter((tool) => !toolMatchesName(tool, options.permissionPromptToolName));
|
|
822168
822548
|
}
|
|
@@ -822910,8 +823290,8 @@ ${m5.text}
|
|
|
822910
823290
|
}
|
|
822911
823291
|
});
|
|
822912
823292
|
});
|
|
822913
|
-
const
|
|
822914
|
-
const
|
|
823293
|
+
const activeOAuthFlows2 = new Map;
|
|
823294
|
+
const oauthCallbackSubmitters2 = new Map;
|
|
822915
823295
|
const oauthManualCallbackUsed = new Set;
|
|
822916
823296
|
const oauthAuthPromises = new Map;
|
|
822917
823297
|
let claudeOAuth = null;
|
|
@@ -823245,9 +823625,9 @@ ${m5.text}
|
|
|
823245
823625
|
sendControlResponseError(message, `Server type "${config8.type}" does not support OAuth authentication`);
|
|
823246
823626
|
} else {
|
|
823247
823627
|
try {
|
|
823248
|
-
|
|
823628
|
+
activeOAuthFlows2.get(serverName)?.abort();
|
|
823249
823629
|
const controller = new AbortController;
|
|
823250
|
-
|
|
823630
|
+
activeOAuthFlows2.set(serverName, controller);
|
|
823251
823631
|
let resolveAuthUrl;
|
|
823252
823632
|
const authUrlPromise = new Promise((resolve63) => {
|
|
823253
823633
|
resolveAuthUrl = resolve63;
|
|
@@ -823255,7 +823635,7 @@ ${m5.text}
|
|
|
823255
823635
|
const oauthPromise = performMCPOAuthFlow(serverName, config8, (url3) => resolveAuthUrl(url3), controller.signal, {
|
|
823256
823636
|
skipBrowserOpen: true,
|
|
823257
823637
|
onWaitingForCallback: (submit) => {
|
|
823258
|
-
|
|
823638
|
+
oauthCallbackSubmitters2.set(serverName, submit);
|
|
823259
823639
|
}
|
|
823260
823640
|
});
|
|
823261
823641
|
const authUrl = await Promise.race([
|
|
@@ -823315,9 +823695,9 @@ ${m5.text}
|
|
|
823315
823695
|
}).catch((error52) => {
|
|
823316
823696
|
logForDebugging(`MCP OAuth failed for ${serverName}: ${error52}`, { level: "error" });
|
|
823317
823697
|
}).finally(() => {
|
|
823318
|
-
if (
|
|
823319
|
-
|
|
823320
|
-
|
|
823698
|
+
if (activeOAuthFlows2.get(serverName) === controller) {
|
|
823699
|
+
activeOAuthFlows2.delete(serverName);
|
|
823700
|
+
oauthCallbackSubmitters2.delete(serverName);
|
|
823321
823701
|
oauthManualCallbackUsed.delete(serverName);
|
|
823322
823702
|
oauthAuthPromises.delete(serverName);
|
|
823323
823703
|
}
|
|
@@ -823328,33 +823708,15 @@ ${m5.text}
|
|
|
823328
823708
|
}
|
|
823329
823709
|
} else if (message.request.subtype === "mcp_oauth_callback_url") {
|
|
823330
823710
|
const { serverName, callbackUrl } = message.request;
|
|
823331
|
-
|
|
823332
|
-
|
|
823333
|
-
|
|
823334
|
-
|
|
823335
|
-
|
|
823336
|
-
|
|
823337
|
-
|
|
823338
|
-
|
|
823339
|
-
|
|
823340
|
-
} else {
|
|
823341
|
-
oauthManualCallbackUsed.add(serverName);
|
|
823342
|
-
submit(callbackUrl);
|
|
823343
|
-
const authPromise = oauthAuthPromises.get(serverName);
|
|
823344
|
-
if (authPromise) {
|
|
823345
|
-
try {
|
|
823346
|
-
await authPromise;
|
|
823347
|
-
sendControlResponseSuccess(message);
|
|
823348
|
-
} catch (error52) {
|
|
823349
|
-
sendControlResponseError(message, error52 instanceof Error ? error52.message : "OAuth authentication failed");
|
|
823350
|
-
}
|
|
823351
|
-
} else {
|
|
823352
|
-
sendControlResponseSuccess(message);
|
|
823353
|
-
}
|
|
823354
|
-
}
|
|
823355
|
-
} else {
|
|
823356
|
-
sendControlResponseError(message, `No active OAuth flow for server: ${serverName}`);
|
|
823357
|
-
}
|
|
823711
|
+
await handleOAuthCallbackUrlControl(serverName, callbackUrl, {
|
|
823712
|
+
getSubmitter: (name3) => oauthCallbackSubmitters2.get(name3),
|
|
823713
|
+
getAuthPromise: (name3) => oauthAuthPromises.get(name3),
|
|
823714
|
+
markManualCallbackUsed: (name3) => {
|
|
823715
|
+
oauthManualCallbackUsed.add(name3);
|
|
823716
|
+
},
|
|
823717
|
+
respondError: (errorMessageText) => sendControlResponseError(message, errorMessageText),
|
|
823718
|
+
respondSuccess: () => sendControlResponseSuccess(message)
|
|
823719
|
+
});
|
|
823358
823720
|
} else if (message.request.subtype === "claude_authenticate") {
|
|
823359
823721
|
const { loginWithClaudeAi } = message.request;
|
|
823360
823722
|
claudeOAuth?.service.cleanup();
|
|
@@ -825220,6 +825582,22 @@ var init_MCPServerDesktopImportDialog = __esm(() => {
|
|
|
825220
825582
|
jsx_runtime498 = __toESM(require_jsx_runtime(), 1);
|
|
825221
825583
|
});
|
|
825222
825584
|
|
|
825585
|
+
// src/cli/mcpOAuthPrompt.ts
|
|
825586
|
+
function promptForCallbackUrlWithRetry(io, submit) {
|
|
825587
|
+
const ask2 = () => {
|
|
825588
|
+
io.question("> ", (answer) => {
|
|
825589
|
+
if (submit(answer.trim())) {
|
|
825590
|
+
io.close();
|
|
825591
|
+
return;
|
|
825592
|
+
}
|
|
825593
|
+
io.notify(CALLBACK_REJECTED_RETRY_HINT);
|
|
825594
|
+
ask2();
|
|
825595
|
+
});
|
|
825596
|
+
};
|
|
825597
|
+
ask2();
|
|
825598
|
+
}
|
|
825599
|
+
var CALLBACK_REJECTED_RETRY_HINT = "That URL was not accepted: its state does not match the flow in progress (or it carries no authorization code). The flow is still waiting \u2014 paste the full redirect URL from the browser page this login opened:";
|
|
825600
|
+
|
|
825223
825601
|
// node_modules/.bun/@modelcontextprotocol+sdk@1.29.0/node_modules/@modelcontextprotocol/sdk/dist/esm/experimental/tasks/server.js
|
|
825224
825602
|
class ExperimentalServerTasks {
|
|
825225
825603
|
constructor(_server) {
|
|
@@ -826213,10 +826591,17 @@ ${url3}`);
|
|
|
826213
826591
|
console.log(`
|
|
826214
826592
|
After authorizing, paste the full redirect URL here and press Enter:`);
|
|
826215
826593
|
const rl = readline5.createInterface({ input: process.stdin });
|
|
826216
|
-
|
|
826217
|
-
|
|
826218
|
-
|
|
826219
|
-
|
|
826594
|
+
promptForCallbackUrlWithRetry({
|
|
826595
|
+
question: (prompt, onAnswer) => {
|
|
826596
|
+
rl.question(prompt, onAnswer);
|
|
826597
|
+
},
|
|
826598
|
+
close: () => {
|
|
826599
|
+
rl.close();
|
|
826600
|
+
},
|
|
826601
|
+
notify: (message) => {
|
|
826602
|
+
console.log(message);
|
|
826603
|
+
}
|
|
826604
|
+
}, submit);
|
|
826220
826605
|
} : undefined;
|
|
826221
826606
|
try {
|
|
826222
826607
|
await performMCPOAuthFlow(name3, server, onAuthorizationUrl, undefined, {
|