@cnwenf/occ 2.1.339 → 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 +506 -110
- 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;
|
|
@@ -9112,6 +9112,17 @@ async function appendAsync(needMkdir, dir, path2, content) {
|
|
|
9112
9112
|
updateLatestDebugLogSymlink();
|
|
9113
9113
|
}
|
|
9114
9114
|
function noop2() {}
|
|
9115
|
+
function appendFileSyncWithDirFallback(path2, content) {
|
|
9116
|
+
try {
|
|
9117
|
+
getFsImplementation().appendFileSync(path2, content);
|
|
9118
|
+
} catch (e) {
|
|
9119
|
+
if (e?.code !== "EISDIR")
|
|
9120
|
+
throw e;
|
|
9121
|
+
const fallback = join3(path2, `${getSessionId()}.txt`);
|
|
9122
|
+
dirFallbackLogPath = fallback;
|
|
9123
|
+
getFsImplementation().appendFileSync(fallback, content);
|
|
9124
|
+
}
|
|
9125
|
+
}
|
|
9115
9126
|
function getDebugWriter() {
|
|
9116
9127
|
if (!debugWriter) {
|
|
9117
9128
|
let ensuredDir = null;
|
|
@@ -9127,7 +9138,7 @@ function getDebugWriter() {
|
|
|
9127
9138
|
getFsImplementation().mkdirSync(dir);
|
|
9128
9139
|
} catch {}
|
|
9129
9140
|
}
|
|
9130
|
-
|
|
9141
|
+
appendFileSyncWithDirFallback(path2, content);
|
|
9131
9142
|
updateLatestDebugLogSymlink();
|
|
9132
9143
|
return;
|
|
9133
9144
|
}
|
|
@@ -9167,7 +9178,7 @@ function logForDebugging(message, { level } = {
|
|
|
9167
9178
|
getDebugWriter().write(output);
|
|
9168
9179
|
}
|
|
9169
9180
|
function getDebugLogPath() {
|
|
9170
|
-
return getDebugFilePath() ?? process.env.CLAUDE_CODE_DEBUG_LOGS_DIR ?? join3(getClaudeConfigHomeDir(), "debug", `${getSessionId()}.txt`);
|
|
9181
|
+
return dirFallbackLogPath ?? getDebugFilePath() ?? process.env.CLAUDE_CODE_DEBUG_LOGS_DIR ?? join3(getClaudeConfigHomeDir(), "debug", `${getSessionId()}.txt`);
|
|
9171
9182
|
}
|
|
9172
9183
|
function logAntError(context, error2) {
|
|
9173
9184
|
if (process.env.USER_TYPE !== "ant") {
|
|
@@ -9180,7 +9191,7 @@ ${error2.stack}`, {
|
|
|
9180
9191
|
});
|
|
9181
9192
|
}
|
|
9182
9193
|
}
|
|
9183
|
-
var LEVEL_ORDER, getMinDebugLogLevel, runtimeDebugEnabled = false, isDebugMode, getDebugFilter, isDebugToStdErr, getDebugFilePath, hasFormattedOutput = false, debugWriter = null, pendingWrite, updateLatestDebugLogSymlink;
|
|
9194
|
+
var LEVEL_ORDER, getMinDebugLogLevel, runtimeDebugEnabled = false, isDebugMode, getDebugFilter, isDebugToStdErr, getDebugFilePath, hasFormattedOutput = false, debugWriter = null, pendingWrite, dirFallbackLogPath = null, updateLatestDebugLogSymlink;
|
|
9184
9195
|
var init_debug = __esm(() => {
|
|
9185
9196
|
init_memoize();
|
|
9186
9197
|
init_state();
|
|
@@ -473601,8 +473612,8 @@ async function getMessagesForSlashCommand(commandName, args, setToolJSX, context
|
|
|
473601
473612
|
command4.load().then((mod2) => mod2.call(onDone, {
|
|
473602
473613
|
...context6,
|
|
473603
473614
|
canUseTool
|
|
473604
|
-
}, args)).then((
|
|
473605
|
-
if (
|
|
473615
|
+
}, args)).then((commandJsx) => {
|
|
473616
|
+
if (commandJsx == null)
|
|
473606
473617
|
return;
|
|
473607
473618
|
if (context6.options.isNonInteractiveSession) {
|
|
473608
473619
|
resolve37({
|
|
@@ -473615,7 +473626,7 @@ async function getMessagesForSlashCommand(commandName, args, setToolJSX, context
|
|
|
473615
473626
|
if (doneWasCalled)
|
|
473616
473627
|
return;
|
|
473617
473628
|
setToolJSX({
|
|
473618
|
-
jsx:
|
|
473629
|
+
jsx: commandJsx,
|
|
473619
473630
|
shouldHidePromptInput: true,
|
|
473620
473631
|
showSpinner: false,
|
|
473621
473632
|
isLocalJSXCommand: true,
|
|
@@ -627153,6 +627164,52 @@ async function fetchAuthServerMetadata(serverName, serverUrl, configuredMetadata
|
|
|
627153
627164
|
...fetchFn && { fetchFn }
|
|
627154
627165
|
});
|
|
627155
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
|
+
}
|
|
627156
627213
|
function getServerKey(serverName, serverConfig) {
|
|
627157
627214
|
const configJson = jsonStringify({
|
|
627158
627215
|
type: serverConfig.type,
|
|
@@ -627510,6 +627567,7 @@ async function performMCPOAuthFlow(serverName, serverConfig, onAuthorizationUrl,
|
|
|
627510
627567
|
let server = null;
|
|
627511
627568
|
let timeoutId = null;
|
|
627512
627569
|
let abortHandler = null;
|
|
627570
|
+
let manualSubmitter = null;
|
|
627513
627571
|
const cleanup2 = () => {
|
|
627514
627572
|
if (server) {
|
|
627515
627573
|
server.removeAllListeners();
|
|
@@ -627525,6 +627583,13 @@ async function performMCPOAuthFlow(serverName, serverConfig, onAuthorizationUrl,
|
|
|
627525
627583
|
abortSignal.removeEventListener("abort", abortHandler);
|
|
627526
627584
|
abortHandler = null;
|
|
627527
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;
|
|
627528
627593
|
logMCPDebug(serverName, `MCP OAuth server cleaned up`);
|
|
627529
627594
|
};
|
|
627530
627595
|
const authorizationCode = await new Promise((resolve53, reject2) => {
|
|
@@ -627552,32 +627617,37 @@ async function performMCPOAuthFlow(serverName, serverConfig, onAuthorizationUrl,
|
|
|
627552
627617
|
}
|
|
627553
627618
|
abortSignal.addEventListener("abort", abortHandler);
|
|
627554
627619
|
}
|
|
627555
|
-
|
|
627556
|
-
|
|
627557
|
-
|
|
627558
|
-
|
|
627559
|
-
|
|
627560
|
-
|
|
627561
|
-
|
|
627562
|
-
|
|
627563
|
-
|
|
627564
|
-
|
|
627565
|
-
|
|
627566
|
-
|
|
627567
|
-
|
|
627568
|
-
|
|
627569
|
-
|
|
627570
|
-
|
|
627571
|
-
|
|
627572
|
-
|
|
627573
|
-
|
|
627574
|
-
|
|
627575
|
-
|
|
627576
|
-
|
|
627577
|
-
|
|
627578
|
-
|
|
627579
|
-
|
|
627580
|
-
}
|
|
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;
|
|
627581
627651
|
}
|
|
627582
627652
|
server = createServer6((req, res) => {
|
|
627583
627653
|
const parsedUrl = parse14(req.url || "", true);
|
|
@@ -628417,7 +628487,7 @@ function getScopeFromMetadata(metadata) {
|
|
|
628417
628487
|
}
|
|
628418
628488
|
return;
|
|
628419
628489
|
}
|
|
628420
|
-
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;
|
|
628421
628491
|
var init_auth11 = __esm(() => {
|
|
628422
628492
|
init_auth10();
|
|
628423
628493
|
init_errors12();
|
|
@@ -628457,6 +628527,9 @@ var init_auth11 = __esm(() => {
|
|
|
628457
628527
|
this.name = "AuthenticationCancelledError";
|
|
628458
628528
|
}
|
|
628459
628529
|
};
|
|
628530
|
+
oauthCallbackSubmitters = new Map;
|
|
628531
|
+
activeOAuthFlows = new Map;
|
|
628532
|
+
oauthFlowRecords = new Map;
|
|
628460
628533
|
});
|
|
628461
628534
|
|
|
628462
628535
|
// src/services/mcp/displaySanitize.ts
|
|
@@ -628521,20 +628594,205 @@ var init_displaySanitize = __esm(() => {
|
|
|
628521
628594
|
INVISIBLE_PATTERN = /[\p{Cc}\p{Cf}\p{Zl}\p{Zp}\p{Default_Ignorable_Code_Point}\u2800]|(?!\u0020)\p{Zs}/gu;
|
|
628522
628595
|
});
|
|
628523
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
|
+
|
|
628524
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
|
+
}
|
|
628525
628783
|
function buildMcpAuthToolDescription(serverName, config7, resolveUnexpanded = resolveUnexpandedMcpServers) {
|
|
628526
628784
|
const transport = config7.type ?? "stdio";
|
|
628527
628785
|
const displayOrigin = getMcpErrorEndpoint(serverName, config7, { detail: "origin" }, resolveUnexpanded);
|
|
628528
628786
|
const location = displayOrigin && displayOrigin !== transport ? `${transport} at ${sanitizeDisplayUrl(displayOrigin, 256)}` : transport;
|
|
628529
|
-
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}.`;
|
|
628530
628788
|
}
|
|
628531
628789
|
function createMcpAuthTool(serverName, config7, resolveUnexpanded = resolveUnexpandedMcpServers) {
|
|
628532
628790
|
const transport = config7.type ?? "stdio";
|
|
628533
628791
|
const description = buildMcpAuthToolDescription(serverName, config7, resolveUnexpanded);
|
|
628534
628792
|
return {
|
|
628535
|
-
name: buildMcpToolName(serverName,
|
|
628793
|
+
name: buildMcpToolName(serverName, MCP_AUTH_TOOL_SUFFIX),
|
|
628536
628794
|
isMcp: true,
|
|
628537
|
-
mcpInfo: { serverName, toolName:
|
|
628795
|
+
mcpInfo: { serverName, toolName: MCP_AUTH_TOOL_SUFFIX },
|
|
628538
628796
|
isEnabled: () => true,
|
|
628539
628797
|
isConcurrencySafe: () => false,
|
|
628540
628798
|
isReadOnly: () => false,
|
|
@@ -628549,17 +628807,43 @@ function createMcpAuthTool(serverName, config7, resolveUnexpanded = resolveUnexp
|
|
|
628549
628807
|
return description;
|
|
628550
628808
|
},
|
|
628551
628809
|
get inputSchema() {
|
|
628552
|
-
return
|
|
628810
|
+
return inputSchema46();
|
|
628553
628811
|
},
|
|
628554
628812
|
async checkPermissions(input2) {
|
|
628555
628813
|
return { behavior: "allow", updatedInput: input2 };
|
|
628556
628814
|
},
|
|
628557
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
|
+
}
|
|
628558
628842
|
if (config7.type === "claudeai-proxy") {
|
|
628559
628843
|
return {
|
|
628560
628844
|
data: {
|
|
628561
628845
|
status: "unsupported",
|
|
628562
|
-
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.`
|
|
628563
628847
|
}
|
|
628564
628848
|
};
|
|
628565
628849
|
}
|
|
@@ -628567,7 +628851,15 @@ function createMcpAuthTool(serverName, config7, resolveUnexpanded = resolveUnexp
|
|
|
628567
628851
|
return {
|
|
628568
628852
|
data: {
|
|
628569
628853
|
status: "unsupported",
|
|
628570
|
-
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")
|
|
628571
628863
|
}
|
|
628572
628864
|
};
|
|
628573
628865
|
}
|
|
@@ -628576,11 +628868,15 @@ function createMcpAuthTool(serverName, config7, resolveUnexpanded = resolveUnexp
|
|
|
628576
628868
|
const authUrlPromise = new Promise((resolve53) => {
|
|
628577
628869
|
resolveAuthUrl = resolve53;
|
|
628578
628870
|
});
|
|
628579
|
-
const controller = new AbortController;
|
|
628580
628871
|
const { setAppState } = context7;
|
|
628581
|
-
const oauthPromise = performMCPOAuthFlow(serverName, sseOrHttpConfig, (u7) => resolveAuthUrl?.(u7),
|
|
628872
|
+
const oauthPromise = performMCPOAuthFlow(serverName, sseOrHttpConfig, (u7) => resolveAuthUrl?.(u7), undefined, { skipBrowserOpen: true });
|
|
628873
|
+
setActiveOAuthPromise(serverName, oauthPromise);
|
|
628582
628874
|
oauthPromise.then(async () => {
|
|
628583
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
|
+
}
|
|
628584
628880
|
const result = await reconnectMcpServerImpl(serverName, config7);
|
|
628585
628881
|
const prefix = getMcpPrefix(serverName);
|
|
628586
628882
|
setAppState((prev) => ({
|
|
@@ -628601,7 +628897,7 @@ function createMcpAuthTool(serverName, config7, resolveUnexpanded = resolveUnexp
|
|
|
628601
628897
|
}));
|
|
628602
628898
|
logMCPDebug(serverName, `OAuth complete, reconnected with ${result.tools.length} tool(s)`);
|
|
628603
628899
|
}).catch((err2) => {
|
|
628604
|
-
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)}`);
|
|
628605
628901
|
});
|
|
628606
628902
|
try {
|
|
628607
628903
|
const authUrl = await Promise.race([
|
|
@@ -628609,29 +628905,37 @@ function createMcpAuthTool(serverName, config7, resolveUnexpanded = resolveUnexp
|
|
|
628609
628905
|
oauthPromise.then(() => null)
|
|
628610
628906
|
]);
|
|
628611
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.`;
|
|
628612
628915
|
return {
|
|
628613
628916
|
data: {
|
|
628614
628917
|
status: "auth_url",
|
|
628615
628918
|
authUrl,
|
|
628616
|
-
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:
|
|
628617
628920
|
|
|
628618
628921
|
${authUrl}
|
|
628619
628922
|
|
|
628620
|
-
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}`
|
|
628621
628924
|
}
|
|
628622
628925
|
};
|
|
628623
628926
|
}
|
|
628624
628927
|
return {
|
|
628625
628928
|
data: {
|
|
628626
628929
|
status: "auth_url",
|
|
628627
|
-
message: `Authentication completed silently for ${
|
|
628930
|
+
message: `Authentication completed silently for ${displayName}. ${TOOLS_NOW_AVAILABLE_SENTENCE}`
|
|
628628
628931
|
}
|
|
628629
628932
|
};
|
|
628630
628933
|
} catch (err2) {
|
|
628934
|
+
const failureDetail = sanitizeForDisplay(redactMcpErrorDetail(serverName, config7, errorMessage(err2), resolveUnexpanded));
|
|
628631
628935
|
return {
|
|
628632
628936
|
data: {
|
|
628633
628937
|
status: "error",
|
|
628634
|
-
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.`
|
|
628635
628939
|
}
|
|
628636
628940
|
};
|
|
628637
628941
|
}
|
|
@@ -628645,19 +628949,38 @@ Once they complete the flow, the server's tools will become available automatica
|
|
|
628645
628949
|
}
|
|
628646
628950
|
};
|
|
628647
628951
|
}
|
|
628648
|
-
|
|
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;
|
|
628649
628962
|
var init_McpAuthTool = __esm(() => {
|
|
628650
628963
|
init_reject2();
|
|
628651
628964
|
init_v4();
|
|
628965
|
+
init_state();
|
|
628652
628966
|
init_auth11();
|
|
628653
628967
|
init_client12();
|
|
628968
|
+
init_config6();
|
|
628654
628969
|
init_displaySanitize();
|
|
628655
628970
|
init_mcpStringUtils();
|
|
628656
628971
|
init_redaction();
|
|
628657
628972
|
init_utils9();
|
|
628658
628973
|
init_errors();
|
|
628659
628974
|
init_log3();
|
|
628660
|
-
|
|
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.@-]*$/;
|
|
628661
628984
|
});
|
|
628662
628985
|
|
|
628663
628986
|
// src/utils/mcpWebSocketTransport.ts
|
|
@@ -631858,7 +632181,7 @@ async function getMcpToolsCommandsAndResources(onConnectionAttempt, mcpConfigs)
|
|
|
631858
632181
|
logMCPDebug(name3, `Skipping connection (cached needs-auth)`);
|
|
631859
632182
|
onConnectionAttempt({
|
|
631860
632183
|
client: { name: name3, type: "needs-auth", config: config7 },
|
|
631861
|
-
tools:
|
|
632184
|
+
tools: createMcpAuthStubTools(name3, config7),
|
|
631862
632185
|
commands: []
|
|
631863
632186
|
});
|
|
631864
632187
|
return;
|
|
@@ -631867,7 +632190,7 @@ async function getMcpToolsCommandsAndResources(onConnectionAttempt, mcpConfigs)
|
|
|
631867
632190
|
if (client8.type !== "connected") {
|
|
631868
632191
|
onConnectionAttempt({
|
|
631869
632192
|
client: client8,
|
|
631870
|
-
tools: client8.type === "needs-auth" ?
|
|
632193
|
+
tools: client8.type === "needs-auth" ? createMcpAuthStubTools(name3, config7) : [],
|
|
631871
632194
|
commands: []
|
|
631872
632195
|
});
|
|
631873
632196
|
return;
|
|
@@ -718166,9 +718489,9 @@ function RateLimitOptionsMenu(t0) {
|
|
|
718166
718489
|
t5 = function handleSelect2(value) {
|
|
718167
718490
|
if (value === "upgrade") {
|
|
718168
718491
|
logEvent2("tengu_rate_limit_options_menu_select_upgrade", {});
|
|
718169
|
-
call81(onDone, context8).then((
|
|
718170
|
-
if (
|
|
718171
|
-
setSubCommandJSX(
|
|
718492
|
+
call81(onDone, context8).then((upgradeJsx) => {
|
|
718493
|
+
if (upgradeJsx) {
|
|
718494
|
+
setSubCommandJSX(upgradeJsx);
|
|
718172
718495
|
}
|
|
718173
718496
|
});
|
|
718174
718497
|
} else {
|
|
@@ -776622,7 +776945,7 @@ function ModeIndicator({
|
|
|
776622
776945
|
if (mode === "bash") {
|
|
776623
776946
|
return /* @__PURE__ */ jsx_runtime432.jsx(ThemedText, {
|
|
776624
776947
|
color: "bashBorder",
|
|
776625
|
-
children: "! for
|
|
776948
|
+
children: "! for shell mode"
|
|
776626
776949
|
});
|
|
776627
776950
|
}
|
|
776628
776951
|
const currentMode = toolPermissionContext?.mode;
|
|
@@ -779123,7 +779446,7 @@ function PromptInput({
|
|
|
779123
779446
|
if (getPlatform() === "macos" && isMacosOptionChar(char)) {
|
|
779124
779447
|
const shortcut = MACOS_OPTION_SPECIAL_CHARS[char];
|
|
779125
779448
|
const terminalName = getNativeCSIuTerminalDisplayName();
|
|
779126
|
-
const
|
|
779449
|
+
const hintJsx = terminalName ? /* @__PURE__ */ jsx_runtime437.jsxs(ThemedText, {
|
|
779127
779450
|
dimColor: true,
|
|
779128
779451
|
children: [
|
|
779129
779452
|
"To enable ",
|
|
@@ -779148,7 +779471,7 @@ function PromptInput({
|
|
|
779148
779471
|
});
|
|
779149
779472
|
addNotification({
|
|
779150
779473
|
key: "option-meta-hint",
|
|
779151
|
-
jsx:
|
|
779474
|
+
jsx: hintJsx,
|
|
779152
779475
|
priority: "immediate",
|
|
779153
779476
|
timeoutMs: 5000
|
|
779154
779477
|
});
|
|
@@ -792719,9 +793042,9 @@ async function processBashCommand(inputString, precedingInputBlocks, attachmentM
|
|
|
792719
793042
|
precedingInputBlocks
|
|
792720
793043
|
})
|
|
792721
793044
|
});
|
|
792722
|
-
let
|
|
793045
|
+
let backgroundJsx;
|
|
792723
793046
|
setToolJSX({
|
|
792724
|
-
jsx: /* @__PURE__ */
|
|
793047
|
+
jsx: /* @__PURE__ */ jsx_runtime442.jsx(BashModeProgress, {
|
|
792725
793048
|
input: inputString,
|
|
792726
793049
|
progress: null,
|
|
792727
793050
|
verbose: context8.options.verbose
|
|
@@ -792732,19 +793055,19 @@ async function processBashCommand(inputString, precedingInputBlocks, attachmentM
|
|
|
792732
793055
|
const bashModeContext = {
|
|
792733
793056
|
...context8,
|
|
792734
793057
|
setToolJSX: (_4) => {
|
|
792735
|
-
|
|
793058
|
+
backgroundJsx = _4?.jsx;
|
|
792736
793059
|
}
|
|
792737
793060
|
};
|
|
792738
793061
|
const onProgress = (progress) => {
|
|
792739
793062
|
setToolJSX({
|
|
792740
793063
|
jsx: /* @__PURE__ */ jsx_runtime442.jsxs(jsx_runtime442.Fragment, {
|
|
792741
793064
|
children: [
|
|
792742
|
-
/* @__PURE__ */
|
|
793065
|
+
/* @__PURE__ */ jsx_runtime442.jsx(BashModeProgress, {
|
|
792743
793066
|
input: inputString,
|
|
792744
793067
|
progress: progress.data,
|
|
792745
793068
|
verbose: context8.options.verbose
|
|
792746
793069
|
}),
|
|
792747
|
-
|
|
793070
|
+
backgroundJsx
|
|
792748
793071
|
]
|
|
792749
793072
|
}),
|
|
792750
793073
|
shouldHidePromptInput: false,
|
|
@@ -793578,6 +793901,7 @@ var exports_toolPool = {};
|
|
|
793578
793901
|
__export(exports_toolPool, {
|
|
793579
793902
|
mergeAndFilterTools: () => mergeAndFilterTools,
|
|
793580
793903
|
isPrActivitySubscriptionTool: () => isPrActivitySubscriptionTool,
|
|
793904
|
+
deferInitialMcpToolsToLiveState: () => deferInitialMcpToolsToLiveState,
|
|
793581
793905
|
applyCoordinatorToolFilter: () => applyCoordinatorToolFilter
|
|
793582
793906
|
});
|
|
793583
793907
|
function isPrActivitySubscriptionTool(name3) {
|
|
@@ -793597,18 +793921,48 @@ function mergeAndFilterTools(initialTools, assembled, mode) {
|
|
|
793597
793921
|
}
|
|
793598
793922
|
return tools;
|
|
793599
793923
|
}
|
|
793600
|
-
|
|
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;
|
|
793601
793952
|
var init_toolPool = __esm(() => {
|
|
793602
793953
|
init_featureFlags();
|
|
793603
793954
|
init_partition();
|
|
793604
793955
|
init_uniqBy();
|
|
793605
793956
|
init_tools();
|
|
793957
|
+
init_mcpStringUtils();
|
|
793606
793958
|
init_utils9();
|
|
793959
|
+
init_mcpAuthStubShared();
|
|
793607
793960
|
PR_ACTIVITY_TOOL_SUFFIXES = [
|
|
793608
793961
|
"subscribe_pr_activity",
|
|
793609
793962
|
"unsubscribe_pr_activity"
|
|
793610
793963
|
];
|
|
793611
793964
|
coordinatorModeModule2 = feature("COORDINATOR_MODE") ? (init_coordinatorMode(), __toCommonJS(exports_coordinatorMode)) : null;
|
|
793965
|
+
AUTH_STUB_PRESERVING_STATES = new Set(["failed", "disabled"]);
|
|
793612
793966
|
});
|
|
793613
793967
|
|
|
793614
793968
|
// src/hooks/useMergedTools.ts
|
|
@@ -798931,13 +799285,13 @@ function permissionPromptToolResultToPermissionDecision(result, tool, input2, to
|
|
|
798931
799285
|
decisionReason
|
|
798932
799286
|
};
|
|
798933
799287
|
}
|
|
798934
|
-
var
|
|
799288
|
+
var inputSchema47, decisionClassificationField, PermissionAllowResultSchema, PermissionDenyResultSchema, outputSchema41;
|
|
798935
799289
|
var init_PermissionPromptToolResultSchema = __esm(() => {
|
|
798936
799290
|
init_v4();
|
|
798937
799291
|
init_debug();
|
|
798938
799292
|
init_PermissionUpdate();
|
|
798939
799293
|
init_PermissionUpdateSchema();
|
|
798940
|
-
|
|
799294
|
+
inputSchema47 = lazySchema(() => v4_default.object({
|
|
798941
799295
|
tool_name: v4_default.string().describe("The name of the tool requesting permission"),
|
|
798942
799296
|
input: v4_default.record(v4_default.string(), v4_default.unknown()).describe("The input for the tool"),
|
|
798943
799297
|
tool_use_id: v4_default.string().optional().describe("The unique tool use request ID")
|
|
@@ -805678,6 +806032,7 @@ function REPL({
|
|
|
805678
806032
|
const combinedInitialTools = import_react321.useMemo(() => {
|
|
805679
806033
|
return [...localTools, ...initialTools];
|
|
805680
806034
|
}, [localTools, initialTools]);
|
|
806035
|
+
const effectiveInitialTools = import_react321.useMemo(() => deferInitialMcpToolsToLiveState(combinedInitialTools, mcp2.clients, mcp2.tools), [combinedInitialTools, mcp2.clients, mcp2.tools]);
|
|
805681
806036
|
useManagePlugins({
|
|
805682
806037
|
enabled: !isRemoteSession
|
|
805683
806038
|
});
|
|
@@ -805699,7 +806054,7 @@ function REPL({
|
|
|
805699
806054
|
useSwarmInitialization(setAppState, initialMessages, {
|
|
805700
806055
|
enabled: !isRemoteSession
|
|
805701
806056
|
});
|
|
805702
|
-
const mergedTools = useMergedTools(
|
|
806057
|
+
const mergedTools = useMergedTools(effectiveInitialTools, mcp2.tools, toolPermissionContext);
|
|
805703
806058
|
const {
|
|
805704
806059
|
tools,
|
|
805705
806060
|
allowedAgentTypes
|
|
@@ -806715,7 +807070,7 @@ Error: sandbox required but unavailable: ${reason}
|
|
|
806715
807070
|
const computeTools = () => {
|
|
806716
807071
|
const state4 = store.getState();
|
|
806717
807072
|
const assembled = assembleToolPool(state4.toolPermissionContext, state4.mcp.tools);
|
|
806718
|
-
const merged = mergeAndFilterTools(combinedInitialTools, assembled, state4.toolPermissionContext.mode);
|
|
807073
|
+
const merged = mergeAndFilterTools(deferInitialMcpToolsToLiveState(combinedInitialTools, state4.mcp.clients, state4.mcp.tools), assembled, state4.toolPermissionContext.mode);
|
|
806719
807074
|
if (!mainThreadAgentDefinition)
|
|
806720
807075
|
return merged;
|
|
806721
807076
|
return resolveAgentTools(mainThreadAgentDefinition, merged, false, true).resolvedTools;
|
|
@@ -807284,10 +807639,10 @@ Error: sandbox required but unavailable: ${reason}
|
|
|
807284
807639
|
};
|
|
807285
807640
|
const context8 = getToolUseContext(messagesRef.current, [], createAbortController(), mainLoopModel);
|
|
807286
807641
|
const mod2 = await matchingCommand.load();
|
|
807287
|
-
const
|
|
807288
|
-
if (
|
|
807642
|
+
const commandJsx = await mod2.call(onDone, context8, commandArgs);
|
|
807643
|
+
if (commandJsx && !doneWasCalled) {
|
|
807289
807644
|
setToolJSX({
|
|
807290
|
-
jsx:
|
|
807645
|
+
jsx: commandJsx,
|
|
807291
807646
|
shouldHidePromptInput: false,
|
|
807292
807647
|
isLocalJSXCommand: true
|
|
807293
807648
|
});
|
|
@@ -820046,6 +820401,42 @@ var init_remoteIO = __esm(() => {
|
|
|
820046
820401
|
};
|
|
820047
820402
|
});
|
|
820048
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
|
+
|
|
820049
820440
|
// src/utils/streamlinedTransform.ts
|
|
820050
820441
|
function categorizeToolName(toolName) {
|
|
820051
820442
|
if (SEARCH_TOOLS2.some((t4) => toolName.startsWith(t4)))
|
|
@@ -822151,7 +822542,7 @@ function runHeadlessStreaming(structuredIO, mcpClients, commands7, tools, initia
|
|
|
822151
822542
|
};
|
|
822152
822543
|
const buildAllTools = (appState) => {
|
|
822153
822544
|
const assembledTools = assembleToolPool(appState.toolPermissionContext, appState.mcp.tools);
|
|
822154
|
-
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");
|
|
822155
822546
|
if (options.permissionPromptToolName) {
|
|
822156
822547
|
allTools = allTools.filter((tool) => !toolMatchesName(tool, options.permissionPromptToolName));
|
|
822157
822548
|
}
|
|
@@ -822899,8 +823290,8 @@ ${m5.text}
|
|
|
822899
823290
|
}
|
|
822900
823291
|
});
|
|
822901
823292
|
});
|
|
822902
|
-
const
|
|
822903
|
-
const
|
|
823293
|
+
const activeOAuthFlows2 = new Map;
|
|
823294
|
+
const oauthCallbackSubmitters2 = new Map;
|
|
822904
823295
|
const oauthManualCallbackUsed = new Set;
|
|
822905
823296
|
const oauthAuthPromises = new Map;
|
|
822906
823297
|
let claudeOAuth = null;
|
|
@@ -823234,9 +823625,9 @@ ${m5.text}
|
|
|
823234
823625
|
sendControlResponseError(message, `Server type "${config8.type}" does not support OAuth authentication`);
|
|
823235
823626
|
} else {
|
|
823236
823627
|
try {
|
|
823237
|
-
|
|
823628
|
+
activeOAuthFlows2.get(serverName)?.abort();
|
|
823238
823629
|
const controller = new AbortController;
|
|
823239
|
-
|
|
823630
|
+
activeOAuthFlows2.set(serverName, controller);
|
|
823240
823631
|
let resolveAuthUrl;
|
|
823241
823632
|
const authUrlPromise = new Promise((resolve63) => {
|
|
823242
823633
|
resolveAuthUrl = resolve63;
|
|
@@ -823244,7 +823635,7 @@ ${m5.text}
|
|
|
823244
823635
|
const oauthPromise = performMCPOAuthFlow(serverName, config8, (url3) => resolveAuthUrl(url3), controller.signal, {
|
|
823245
823636
|
skipBrowserOpen: true,
|
|
823246
823637
|
onWaitingForCallback: (submit) => {
|
|
823247
|
-
|
|
823638
|
+
oauthCallbackSubmitters2.set(serverName, submit);
|
|
823248
823639
|
}
|
|
823249
823640
|
});
|
|
823250
823641
|
const authUrl = await Promise.race([
|
|
@@ -823304,9 +823695,9 @@ ${m5.text}
|
|
|
823304
823695
|
}).catch((error52) => {
|
|
823305
823696
|
logForDebugging(`MCP OAuth failed for ${serverName}: ${error52}`, { level: "error" });
|
|
823306
823697
|
}).finally(() => {
|
|
823307
|
-
if (
|
|
823308
|
-
|
|
823309
|
-
|
|
823698
|
+
if (activeOAuthFlows2.get(serverName) === controller) {
|
|
823699
|
+
activeOAuthFlows2.delete(serverName);
|
|
823700
|
+
oauthCallbackSubmitters2.delete(serverName);
|
|
823310
823701
|
oauthManualCallbackUsed.delete(serverName);
|
|
823311
823702
|
oauthAuthPromises.delete(serverName);
|
|
823312
823703
|
}
|
|
@@ -823317,33 +823708,15 @@ ${m5.text}
|
|
|
823317
823708
|
}
|
|
823318
823709
|
} else if (message.request.subtype === "mcp_oauth_callback_url") {
|
|
823319
823710
|
const { serverName, callbackUrl } = message.request;
|
|
823320
|
-
|
|
823321
|
-
|
|
823322
|
-
|
|
823323
|
-
|
|
823324
|
-
|
|
823325
|
-
|
|
823326
|
-
|
|
823327
|
-
|
|
823328
|
-
|
|
823329
|
-
} else {
|
|
823330
|
-
oauthManualCallbackUsed.add(serverName);
|
|
823331
|
-
submit(callbackUrl);
|
|
823332
|
-
const authPromise = oauthAuthPromises.get(serverName);
|
|
823333
|
-
if (authPromise) {
|
|
823334
|
-
try {
|
|
823335
|
-
await authPromise;
|
|
823336
|
-
sendControlResponseSuccess(message);
|
|
823337
|
-
} catch (error52) {
|
|
823338
|
-
sendControlResponseError(message, error52 instanceof Error ? error52.message : "OAuth authentication failed");
|
|
823339
|
-
}
|
|
823340
|
-
} else {
|
|
823341
|
-
sendControlResponseSuccess(message);
|
|
823342
|
-
}
|
|
823343
|
-
}
|
|
823344
|
-
} else {
|
|
823345
|
-
sendControlResponseError(message, `No active OAuth flow for server: ${serverName}`);
|
|
823346
|
-
}
|
|
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
|
+
});
|
|
823347
823720
|
} else if (message.request.subtype === "claude_authenticate") {
|
|
823348
823721
|
const { loginWithClaudeAi } = message.request;
|
|
823349
823722
|
claudeOAuth?.service.cleanup();
|
|
@@ -825209,6 +825582,22 @@ var init_MCPServerDesktopImportDialog = __esm(() => {
|
|
|
825209
825582
|
jsx_runtime498 = __toESM(require_jsx_runtime(), 1);
|
|
825210
825583
|
});
|
|
825211
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
|
+
|
|
825212
825601
|
// node_modules/.bun/@modelcontextprotocol+sdk@1.29.0/node_modules/@modelcontextprotocol/sdk/dist/esm/experimental/tasks/server.js
|
|
825213
825602
|
class ExperimentalServerTasks {
|
|
825214
825603
|
constructor(_server) {
|
|
@@ -826202,10 +826591,17 @@ ${url3}`);
|
|
|
826202
826591
|
console.log(`
|
|
826203
826592
|
After authorizing, paste the full redirect URL here and press Enter:`);
|
|
826204
826593
|
const rl = readline5.createInterface({ input: process.stdin });
|
|
826205
|
-
|
|
826206
|
-
|
|
826207
|
-
|
|
826208
|
-
|
|
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);
|
|
826209
826605
|
} : undefined;
|
|
826210
826606
|
try {
|
|
826211
826607
|
await performMCPOAuthFlow(name3, server, onAuthorizationUrl, undefined, {
|