@introspection-ai/recipes 0.19.2 → 0.20.0
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/agents.d.ts +17 -1
- package/dist/agents.d.ts.map +1 -1
- package/dist/agents.js +15 -1
- package/dist/agents.js.map +1 -1
- package/dist/child-agent.d.ts +3 -1
- package/dist/child-agent.d.ts.map +1 -1
- package/dist/child-agent.js +1 -0
- package/dist/child-agent.js.map +1 -1
- package/dist/mcp-chunks/{auth-command-3K7V3VCW.js → auth-command-IQ4J332A.js} +26 -38
- package/dist/mcp-chunks/call-arguments-MCCBPJMY.js +15 -0
- package/dist/mcp-chunks/{call-command-OFPHPFM5.js → call-command-WPQ3MDOE.js} +74 -40
- package/dist/mcp-chunks/{chunk-LNSUME65.js → chunk-24FKKIXI.js} +29 -13
- package/dist/mcp-chunks/{chunk-HTZ2URXW.js → chunk-2CTVPSHF.js} +3 -3
- package/dist/mcp-chunks/{chunk-NCXEJ35U.js → chunk-3FB4ZJ4Z.js} +4 -4
- package/dist/mcp-chunks/{chunk-P3RN22HQ.js → chunk-3MIFROM7.js} +3 -2
- package/dist/mcp-chunks/{chunk-GFYTST6N.js → chunk-54UGGTOX.js} +1 -1
- package/dist/mcp-chunks/{chunk-L4VKBFYI.js → chunk-5HQYKAE7.js} +101 -16
- package/dist/mcp-chunks/{chunk-E6RVTWJY.js → chunk-5YBCGQA7.js} +1 -1
- package/dist/mcp-chunks/{chunk-6D6KPSXN.js → chunk-AJPFOQLF.js} +1 -1
- package/dist/mcp-chunks/{chunk-C2PQFLWS.js → chunk-B4XFULJ6.js} +15 -6
- package/dist/mcp-chunks/{chunk-HAO6PL7Z.js → chunk-DIIFWDZ7.js} +7 -7
- package/dist/mcp-chunks/{chunk-55JIHDU3.js → chunk-EEYUPDRX.js} +1 -1
- package/dist/mcp-chunks/{chunk-7A63PAGP.js → chunk-ETYYCEQF.js} +21 -5
- package/dist/mcp-chunks/{chunk-E6T37ED6.js → chunk-FNQV2ONG.js} +2 -2
- package/dist/mcp-chunks/{chunk-2JHHONW4.js → chunk-FW5QVG6V.js} +1 -1
- package/dist/mcp-chunks/{chunk-YCYSQA5V.js → chunk-FZ7K5EGL.js} +5 -5
- package/dist/mcp-chunks/{chunk-KSMY7PXI.js → chunk-G5C4WVDQ.js} +1 -1
- package/dist/mcp-chunks/{chunk-XRGLP3Z2.js → chunk-GPCLDF6U.js} +1 -1
- package/dist/mcp-chunks/{chunk-KSGYBW3F.js → chunk-GQHTGV5E.js} +72 -22
- package/dist/mcp-chunks/{chunk-64EP2BVO.js → chunk-HULRE4D2.js} +1 -1
- package/dist/mcp-chunks/{chunk-UENXT3NE.js → chunk-ILSK6AWI.js} +1 -1
- package/dist/mcp-chunks/{chunk-RBVYCKCD.js → chunk-ILULMM2E.js} +2 -2
- package/dist/mcp-chunks/{chunk-NZOIX6XW.js → chunk-ITJWLDF5.js} +2 -2
- package/dist/mcp-chunks/{chunk-XUF6KARU.js → chunk-IUFDFNNP.js} +1 -1
- package/dist/mcp-chunks/chunk-JJG2OEHI.js +12 -0
- package/dist/mcp-chunks/{chunk-YPJ5EHXR.js → chunk-K56RW4HB.js} +4 -4
- package/dist/mcp-chunks/{chunk-H7F5RZXS.js → chunk-KJ3CMHWS.js} +2 -1
- package/dist/mcp-chunks/{chunk-WXBPMFSN.js → chunk-LI4L4FOV.js} +91 -34
- package/dist/mcp-chunks/{chunk-ETWN4IIA.js → chunk-LYZRCACV.js} +6 -6
- package/dist/mcp-chunks/{chunk-ZBFZ5UFE.js → chunk-MDVNQ4HM.js} +3 -1
- package/dist/mcp-chunks/{chunk-3IZQW4H4.js → chunk-MNAVFYYV.js} +212 -18
- package/dist/mcp-chunks/{chunk-7DH57OKF.js → chunk-MWD5PZ4G.js} +2 -2
- package/dist/mcp-chunks/{chunk-YSPT6F7K.js → chunk-N2HVJU7X.js} +1 -1
- package/dist/mcp-chunks/{chunk-WWO5WGH5.js → chunk-NACLB5YH.js} +5 -5
- package/dist/mcp-chunks/{chunk-QJACOI2W.js → chunk-NMF5S5DC.js} +4 -2
- package/dist/mcp-chunks/{chunk-54EWGONA.js → chunk-NPU7EMGE.js} +10 -6
- package/dist/mcp-chunks/{chunk-SFREPU3D.js → chunk-NSZY5WLR.js} +1 -1
- package/dist/mcp-chunks/{chunk-7RDLPFIO.js → chunk-QK6LUI5Q.js} +2 -2
- package/dist/mcp-chunks/{chunk-XTL4MHFH.js → chunk-QONTHFPO.js} +11 -7
- package/dist/mcp-chunks/{chunk-YTKRAHO6.js → chunk-RDOD354S.js} +4 -4
- package/dist/mcp-chunks/{chunk-2MEHGB7D.js → chunk-RXSZ2W6Y.js} +1 -1
- package/dist/mcp-chunks/{chunk-UHOKCTZT.js → chunk-RYAUNXFA.js} +1 -1
- package/dist/mcp-chunks/{chunk-GIF7LOYU.js → chunk-SCD2NAX5.js} +2 -2
- package/dist/mcp-chunks/{chunk-F3LL4EBL.js → chunk-SHZVDY6Z.js} +1 -1
- package/dist/mcp-chunks/{chunk-CNDY7WB4.js → chunk-TAVMVGD5.js} +2 -2
- package/dist/mcp-chunks/{chunk-JAKI24KR.js → chunk-U23EY5DN.js} +1 -1
- package/dist/mcp-chunks/{chunk-SB2UUURE.js → chunk-UAIJZBGL.js} +10 -10
- package/dist/mcp-chunks/{chunk-PKOJCYNA.js → chunk-UDG3RHKX.js} +2 -2
- package/dist/mcp-chunks/{chunk-CA5WFJZA.js → chunk-VC6SKXTI.js} +1 -1
- package/dist/mcp-chunks/chunk-VJ2TSA5R.js +818 -0
- package/dist/mcp-chunks/{chunk-FWP4RACK.js → chunk-VREKED5H.js} +2 -2
- package/dist/mcp-chunks/{chunk-2FSDGCHW.js → chunk-WKUCIR2F.js} +374 -527
- package/dist/mcp-chunks/chunk-XRRT3SZM.js +1931 -0
- package/dist/mcp-chunks/{chunk-GSZOK5TS.js → chunk-YDJ7E2PH.js} +3 -3
- package/dist/mcp-chunks/{chunk-LICH4Q7A.js → chunk-ZI44YPFF.js} +4 -4
- package/dist/mcp-chunks/{chunk-DEUU7WSN.js → chunk-ZNKNF2BV.js} +2 -2
- package/dist/mcp-chunks/{chunk-DXPHJFSA.js → chunk-ZSKQI4TS.js} +4 -4
- package/dist/mcp-chunks/{cli-E4P6SZLQ.js → cli-Z7KV4PCE.js} +70 -69
- package/dist/mcp-chunks/client-B3FMQNGF.js +21 -0
- package/dist/mcp-chunks/{config-command-MWF3RHPQ.js → config-command-XXCDOB3M.js} +27 -27
- package/dist/mcp-chunks/daemon-command-BAREANTC.js +35 -0
- package/dist/mcp-chunks/{dist-ZIPUENTM.js → dist-V4UB7RTR.js} +547 -402
- package/dist/mcp-chunks/{emit-ts-command-GOVJJ64A.js → emit-ts-command-FEHTMXXB.js} +16 -16
- package/dist/mcp-chunks/{generate-cli-runner-L5OQIMEY.js → generate-cli-runner-OA6XL77R.js} +49 -42
- package/dist/mcp-chunks/{inspect-cli-command-7OMMREPE.js → inspect-cli-command-UQKKE5VO.js} +9 -9
- package/dist/mcp-chunks/{launch-BWXPLPB7.js → launch-KMPDJOUH.js} +1 -1
- package/dist/mcp-chunks/{lifecycle-B5UC65PT.js → lifecycle-R3IP22MJ.js} +1 -1
- package/dist/mcp-chunks/{list-command-ZO4HVFQK.js → list-command-7ENYKBF6.js} +31 -31
- package/dist/mcp-chunks/{output-utils-M3TJ2N4M.js → output-utils-N75TOWBX.js} +3 -3
- package/dist/mcp-chunks/{prompt-CH6TK0bC-C7OTKGRD.js → prompt-CH6TK0bC-NSBYYJZH.js} +1 -1
- package/dist/mcp-chunks/{record-command-VD3HUQIC.js → record-command-XHPCL7IG.js} +5 -5
- package/dist/mcp-chunks/{replay-command-AX6IN7YD.js → replay-command-CB56L3ZA.js} +6 -6
- package/dist/mcp-chunks/{resource-command-JEZ2DW2G.js → resource-command-STEBHVT7.js} +9 -9
- package/dist/mcp-chunks/{result-utils-3YHYGS45.js → result-utils-UONY2KNY.js} +3 -3
- package/dist/mcp-chunks/runtime-Z45IVD24.js +39 -0
- package/dist/mcp-chunks/{runtime-wrapper-UREU7GC3.js → runtime-wrapper-SYYAQVO6.js} +6 -6
- package/dist/mcp-chunks/{serve-command-M47YZ6JN.js → serve-command-VYSFRZFE.js} +35 -27
- package/dist/mcp-chunks/{timeouts-THZRYP4B.js → timeouts-T3JP3MUF.js} +5 -3
- package/dist/mcp-chunks/{vault-command-53P7MLCB.js → vault-command-AJ3X7GDI.js} +58 -12
- package/dist/mcp-chunks/{webapi-PHEQZQKH.js → webapi-BLTNWSB2.js} +68 -60
- package/dist/mcp-daemon.js +30 -28
- package/dist/mcp-run-worker.js +30 -28
- package/dist/mcp.d.ts.map +1 -1
- package/dist/mcp.js +2 -1
- package/dist/mcp.js.map +1 -1
- package/dist/pi-extension.d.ts +3 -0
- package/dist/pi-extension.d.ts.map +1 -1
- package/dist/pi-extension.js +27 -0
- package/dist/pi-extension.js.map +1 -1
- package/dist/run-controller.d.ts +3 -1
- package/dist/run-controller.d.ts.map +1 -1
- package/dist/run-controller.js +10 -0
- package/dist/run-controller.js.map +1 -1
- package/dist/session.d.ts +3 -1
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js +4 -1
- package/dist/session.js.map +1 -1
- package/docs/host-api.md +12 -0
- package/docs/pi-extension.md +10 -0
- package/package.json +11 -11
- package/vendor/introspection-recipe-check/win32-x64/introspection-recipe-check.exe +0 -0
- package/dist/mcp-chunks/call-arguments-TX3F2TEE.js +0 -15
- package/dist/mcp-chunks/chunk-SRZZQ6TL.js +0 -266
- package/dist/mcp-chunks/client-2EJC4PLL.js +0 -18
- package/dist/mcp-chunks/daemon-command-6CJ26MKI.js +0 -33
- package/dist/mcp-chunks/runtime-HSYVOME7.js +0 -37
|
@@ -3,48 +3,41 @@ import {
|
|
|
3
3
|
NON_INTERACTIVE_ELICITATION_HINT,
|
|
4
4
|
createNonInteractiveElicitationResponder,
|
|
5
5
|
registerElicitationHandler
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-VC6SKXTI.js";
|
|
7
7
|
import {
|
|
8
8
|
RecordTransport,
|
|
9
9
|
resolveRecordingPath
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-FNQV2ONG.js";
|
|
11
11
|
import {
|
|
12
12
|
OAuthTimeoutError,
|
|
13
13
|
connectWithAuth,
|
|
14
|
+
createOAuthSession,
|
|
14
15
|
isOAuthFlowError,
|
|
15
16
|
isPostAuthConnectError,
|
|
16
17
|
resolveOAuthTimeoutFromEnv
|
|
17
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-VJ2TSA5R.js";
|
|
18
19
|
import {
|
|
19
|
-
buildOAuthPersistence,
|
|
20
|
-
buildStaticClientInformation,
|
|
21
20
|
readCachedAccessToken
|
|
22
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-MNAVFYYV.js";
|
|
23
22
|
import {
|
|
24
23
|
isUnauthorizedError,
|
|
25
24
|
maybeEnableOAuth
|
|
26
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-MWD5PZ4G.js";
|
|
27
26
|
import {
|
|
28
27
|
STDIO_TRACE_ENABLED,
|
|
29
28
|
flushStdioLogs,
|
|
30
29
|
ignoreStdioEmitterError
|
|
31
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-RXSZ2W6Y.js";
|
|
32
31
|
import {
|
|
33
32
|
MCPORTER_VERSION
|
|
34
|
-
} from "./chunk-
|
|
33
|
+
} from "./chunk-NSZY5WLR.js";
|
|
35
34
|
import {
|
|
36
35
|
createPrefixedConsoleLogger,
|
|
37
36
|
resolveLogLevelFromEnv
|
|
38
|
-
} from "./chunk-
|
|
39
|
-
import {
|
|
40
|
-
normalizeTimeout,
|
|
41
|
-
raceWithTimeout,
|
|
42
|
-
resolveCommandArgument,
|
|
43
|
-
resolveCommandArguments
|
|
44
|
-
} from "./chunk-ETWN4IIA.js";
|
|
37
|
+
} from "./chunk-54UGGTOX.js";
|
|
45
38
|
import {
|
|
46
39
|
analyzeConnectionError
|
|
47
|
-
} from "./chunk-
|
|
40
|
+
} from "./chunk-ZNKNF2BV.js";
|
|
48
41
|
import {
|
|
49
42
|
Client,
|
|
50
43
|
DEFAULT_REQUEST_TIMEOUT_MSEC,
|
|
@@ -56,17 +49,29 @@ import {
|
|
|
56
49
|
SdkHttpError,
|
|
57
50
|
StreamableHTTPClientTransport,
|
|
58
51
|
serializeMessage,
|
|
59
|
-
specTypeSchemas
|
|
60
|
-
|
|
61
|
-
|
|
52
|
+
specTypeSchemas
|
|
53
|
+
} from "./chunk-K56RW4HB.js";
|
|
54
|
+
import {
|
|
55
|
+
ChromeDevtoolsRelayRequiredError,
|
|
56
|
+
formatChromeDevtoolsRelayDecision,
|
|
57
|
+
recordChromeDevtoolsRelayDecision,
|
|
58
|
+
resolveChromeDevtoolsAutoConnectCommand,
|
|
59
|
+
resolveChromeDevtoolsRelayEnvironment,
|
|
60
|
+
rewriteChromeDevtoolsArgsForRelay
|
|
61
|
+
} from "./chunk-XRRT3SZM.js";
|
|
62
|
+
import {
|
|
63
|
+
normalizeTimeout,
|
|
64
|
+
raceWithTimeout,
|
|
65
|
+
resolveCommandArgument,
|
|
66
|
+
resolveCommandArguments
|
|
67
|
+
} from "./chunk-LYZRCACV.js";
|
|
62
68
|
import {
|
|
63
69
|
loadServerDefinitions
|
|
64
|
-
} from "./chunk-
|
|
70
|
+
} from "./chunk-5HQYKAE7.js";
|
|
65
71
|
import {
|
|
66
72
|
resolveEnvPlaceholders,
|
|
67
|
-
resolveEnvValue,
|
|
68
73
|
withEnvOverrides
|
|
69
|
-
} from "./chunk-
|
|
74
|
+
} from "./chunk-DIIFWDZ7.js";
|
|
70
75
|
import {
|
|
71
76
|
__commonJS,
|
|
72
77
|
__require,
|
|
@@ -550,27 +555,27 @@ var require_cross_spawn = __commonJS({
|
|
|
550
555
|
var cp = __require("child_process");
|
|
551
556
|
var parse = require_parse();
|
|
552
557
|
var enoent = require_enoent();
|
|
553
|
-
function
|
|
558
|
+
function spawn2(command, args, options) {
|
|
554
559
|
const parsed = parse(command, args, options);
|
|
555
560
|
const spawned = cp.spawn(parsed.command, parsed.args, parsed.options);
|
|
556
561
|
enoent.hookChildProcess(spawned, parsed);
|
|
557
562
|
return spawned;
|
|
558
563
|
}
|
|
559
|
-
function
|
|
564
|
+
function spawnSync2(command, args, options) {
|
|
560
565
|
const parsed = parse(command, args, options);
|
|
561
566
|
const result = cp.spawnSync(parsed.command, parsed.args, parsed.options);
|
|
562
567
|
result.error = result.error || enoent.verifyENOENTSync(result.status, parsed);
|
|
563
568
|
return result;
|
|
564
569
|
}
|
|
565
|
-
module.exports =
|
|
566
|
-
module.exports.spawn =
|
|
567
|
-
module.exports.sync =
|
|
570
|
+
module.exports = spawn2;
|
|
571
|
+
module.exports.spawn = spawn2;
|
|
572
|
+
module.exports.sync = spawnSync2;
|
|
568
573
|
module.exports._parse = parse;
|
|
569
574
|
module.exports._enoent = enoent;
|
|
570
575
|
}
|
|
571
576
|
});
|
|
572
577
|
|
|
573
|
-
// node_modules/.pnpm/mcporter@0.13.
|
|
578
|
+
// node_modules/.pnpm/mcporter@0.13.6/node_modules/mcporter/dist/runtime-process-utils.js
|
|
574
579
|
import { execFile } from "node:child_process";
|
|
575
580
|
async function closeTransportAndWait(logger, transport, options = {}) {
|
|
576
581
|
const pidBeforeClose = getTransportPid(transport);
|
|
@@ -777,7 +782,7 @@ function delay(ms) {
|
|
|
777
782
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
778
783
|
}
|
|
779
784
|
|
|
780
|
-
// node_modules/.pnpm/mcporter@0.13.
|
|
785
|
+
// node_modules/.pnpm/mcporter@0.13.6/node_modules/mcporter/dist/runtime/errors.js
|
|
781
786
|
var NON_FATAL_MCP_ERROR_CODES = /* @__PURE__ */ new Set([
|
|
782
787
|
ProtocolErrorCode.InvalidRequest,
|
|
783
788
|
ProtocolErrorCode.MethodNotFound,
|
|
@@ -799,7 +804,7 @@ function protocolErrorCode(error) {
|
|
|
799
804
|
return typeof error.code === "number" ? error.code : void 0;
|
|
800
805
|
}
|
|
801
806
|
|
|
802
|
-
// node_modules/.pnpm/mcporter@0.13.
|
|
807
|
+
// node_modules/.pnpm/mcporter@0.13.6/node_modules/mcporter/dist/runtime/replay-transport.js
|
|
803
808
|
import fs from "node:fs";
|
|
804
809
|
import { isDeepStrictEqual } from "node:util";
|
|
805
810
|
var CLIENT_IDENTITY_META_KEYS = [
|
|
@@ -1021,13 +1026,13 @@ function formatReplayRemainder(server, expectedSends) {
|
|
|
1021
1026
|
return `Replay ended for server '${server}' with ${count} recorded ${requestText} still unused; next expected recv ${expectedText}.`;
|
|
1022
1027
|
}
|
|
1023
1028
|
|
|
1024
|
-
// node_modules/.pnpm/mcporter@0.13.
|
|
1029
|
+
// node_modules/.pnpm/mcporter@0.13.6/node_modules/mcporter/dist/chrome-devtools-compat.js
|
|
1025
1030
|
import fs3 from "node:fs";
|
|
1026
1031
|
import os from "node:os";
|
|
1027
1032
|
import path2 from "node:path";
|
|
1028
1033
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
1029
1034
|
|
|
1030
|
-
// node_modules/.pnpm/mcporter@0.13.
|
|
1035
|
+
// node_modules/.pnpm/mcporter@0.13.6/node_modules/mcporter/dist/chrome-devtools-auto-connect-patch.js
|
|
1031
1036
|
import fs2 from "node:fs";
|
|
1032
1037
|
import path from "node:path";
|
|
1033
1038
|
var MARKER = "MCPORTER_DEVTOOLS_TIMEOUT_PATCH";
|
|
@@ -1114,8 +1119,7 @@ ${helper}`);
|
|
|
1114
1119
|
}
|
|
1115
1120
|
}
|
|
1116
1121
|
|
|
1117
|
-
// node_modules/.pnpm/mcporter@0.13.
|
|
1118
|
-
var AUTO_CONNECT_FLAGS = /* @__PURE__ */ new Set(["--autoConnect", "--auto-connect"]);
|
|
1122
|
+
// node_modules/.pnpm/mcporter@0.13.6/node_modules/mcporter/dist/chrome-devtools-compat.js
|
|
1119
1123
|
var FALLBACK_PATCH_FILENAME = "mcporter-chrome-devtools-auto-connect-patch.js";
|
|
1120
1124
|
function applyChromeDevtoolsCompat(env, command, args) {
|
|
1121
1125
|
if (!shouldApplyChromeDevtoolsCompat(command, args, env)) {
|
|
@@ -1143,11 +1147,7 @@ function shouldApplyChromeDevtoolsCompat(command, args, env = process.env) {
|
|
|
1143
1147
|
if (env.MCPORTER_DISABLE_CHROME_DEVTOOLS_COMPAT === "1") {
|
|
1144
1148
|
return false;
|
|
1145
1149
|
}
|
|
1146
|
-
|
|
1147
|
-
return tokens.some(isChromeDevtoolsToken) && args.some((arg) => AUTO_CONNECT_FLAGS.has(arg));
|
|
1148
|
-
}
|
|
1149
|
-
function isChromeDevtoolsToken(token) {
|
|
1150
|
-
return token === "chrome-devtools-mcp" || token.startsWith("chrome-devtools-mcp@") || token.includes("/chrome-devtools-mcp");
|
|
1150
|
+
return resolveChromeDevtoolsAutoConnectCommand(command, args).enabled;
|
|
1151
1151
|
}
|
|
1152
1152
|
function resolveChromeDevtoolsCompatPatchPath(candidates = defaultChromeDevtoolsPatchCandidates(), fallbackDir = os.tmpdir()) {
|
|
1153
1153
|
const existing = candidates.find((candidate) => fs3.existsSync(candidate));
|
|
@@ -1173,88 +1173,232 @@ function writeFallbackPatch(fallbackDir) {
|
|
|
1173
1173
|
}
|
|
1174
1174
|
}
|
|
1175
1175
|
|
|
1176
|
-
// node_modules/.pnpm/mcporter@0.13.
|
|
1176
|
+
// node_modules/.pnpm/mcporter@0.13.6/node_modules/mcporter/dist/chrome-devtools-relay-handoff.js
|
|
1177
|
+
import { spawnSync } from "node:child_process";
|
|
1178
|
+
import { randomBytes } from "node:crypto";
|
|
1177
1179
|
import fs4 from "node:fs";
|
|
1178
1180
|
import os2 from "node:os";
|
|
1179
1181
|
import path3 from "node:path";
|
|
1180
|
-
|
|
1181
|
-
var
|
|
1182
|
-
var
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
function
|
|
1187
|
-
|
|
1188
|
-
let url;
|
|
1182
|
+
import { pathToFileURL as pathToFileURL2 } from "node:url";
|
|
1183
|
+
var CHROME_RELAY_HANDOFF_ENV = "MCPORTER_CHROME_RELAY_HANDOFF_PATH";
|
|
1184
|
+
var HANDOFF_DIR_PREFIX = "mcporter-chrome-relay-";
|
|
1185
|
+
var HANDOFF_FILENAME = "headers.json";
|
|
1186
|
+
var PRELOAD_FILENAME = "preload.mjs";
|
|
1187
|
+
var WINDOWS_ACL_PATH_ENV = "MCPORTER_CHROME_RELAY_ACL_PATH";
|
|
1188
|
+
function createChromeDevtoolsRelayHandoff(env, clientAuthorization) {
|
|
1189
|
+
let directory;
|
|
1189
1190
|
try {
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1191
|
+
if (process.platform === "win32")
|
|
1192
|
+
directory = createWindowsHandoffDirectory();
|
|
1193
|
+
else {
|
|
1194
|
+
directory = fs4.mkdtempSync(path3.join(os2.tmpdir(), HANDOFF_DIR_PREFIX));
|
|
1195
|
+
fs4.chmodSync(directory, 448);
|
|
1196
|
+
}
|
|
1197
|
+
assertSecurePath(directory, "directory");
|
|
1198
|
+
const handoffPath = path3.join(directory, HANDOFF_FILENAME);
|
|
1199
|
+
const preloadPath = path3.join(directory, PRELOAD_FILENAME);
|
|
1200
|
+
writeExclusiveFile(preloadPath, renderChromeDevtoolsRelayPreloadSource());
|
|
1201
|
+
writeExclusiveFile(handoffPath, JSON.stringify({ Authorization: clientAuthorization }));
|
|
1202
|
+
const importFlag = `--import=${pathToFileURL2(preloadPath).href}`;
|
|
1203
|
+
const existingOptions = env.NODE_OPTIONS?.trim();
|
|
1204
|
+
let closed = false;
|
|
1205
|
+
return {
|
|
1206
|
+
env: {
|
|
1207
|
+
...env,
|
|
1208
|
+
NODE_OPTIONS: existingOptions ? `${existingOptions} ${importFlag}` : importFlag,
|
|
1209
|
+
[CHROME_RELAY_HANDOFF_ENV]: handoffPath
|
|
1210
|
+
},
|
|
1211
|
+
handoffPath,
|
|
1212
|
+
preloadPath,
|
|
1213
|
+
async close() {
|
|
1214
|
+
if (closed)
|
|
1215
|
+
return;
|
|
1216
|
+
closed = true;
|
|
1217
|
+
cleanupHandoff(directory, handoffPath, preloadPath);
|
|
1218
|
+
}
|
|
1219
|
+
};
|
|
1220
|
+
} catch (error) {
|
|
1221
|
+
if (directory)
|
|
1222
|
+
cleanupHandoff(directory, path3.join(directory, HANDOFF_FILENAME), path3.join(directory, PRELOAD_FILENAME));
|
|
1223
|
+
const diagnostic = error instanceof Error && error.message.startsWith("Windows ACL setup failed:") ? ` ${error.message}` : "";
|
|
1224
|
+
throw new Error(`Unable to install secure Chrome relay authorization handoff.${diagnostic}`, { cause: error });
|
|
1225
|
+
}
|
|
1226
|
+
}
|
|
1227
|
+
function createWindowsHandoffDirectory() {
|
|
1228
|
+
const directory = path3.join(os2.tmpdir(), `${HANDOFF_DIR_PREFIX}${randomBytes(16).toString("hex")}`);
|
|
1229
|
+
const script = String.raw`
|
|
1230
|
+
$ErrorActionPreference = 'Stop'
|
|
1231
|
+
$stage = 'identity'
|
|
1232
|
+
try {
|
|
1233
|
+
$target = $env:${WINDOWS_ACL_PATH_ENV}
|
|
1234
|
+
if ([System.IO.Directory]::Exists($target)) { throw 'handoff path already exists' }
|
|
1235
|
+
$sid = [System.Security.Principal.WindowsIdentity]::GetCurrent().User
|
|
1236
|
+
$stage = 'descriptor'
|
|
1237
|
+
$security = New-Object System.Security.AccessControl.DirectorySecurity
|
|
1238
|
+
$sidValue = $sid.Value
|
|
1239
|
+
$security.SetSecurityDescriptorSddlForm("O:$($sidValue)G:$($sidValue)D:P(A;OICI;FA;;;$($sidValue))")
|
|
1240
|
+
$directory = New-Object System.IO.DirectoryInfo -ArgumentList @($target)
|
|
1241
|
+
$stage = 'create'
|
|
1242
|
+
$directory.Create($security)
|
|
1243
|
+
$stage = 'acl-read'
|
|
1244
|
+
$check = $directory.GetAccessControl([System.Security.AccessControl.AccessControlSections]::All)
|
|
1245
|
+
$rules = @($check.GetAccessRules($true, $true, [System.Security.Principal.SecurityIdentifier]))
|
|
1246
|
+
$ownerSid = $check.GetOwner([System.Security.Principal.SecurityIdentifier]).Value
|
|
1247
|
+
$stage = 'acl-verify'
|
|
1248
|
+
if (-not $check.AreAccessRulesProtected -or $ownerSid -ne $sid.Value -or $rules.Count -ne 1) { throw 'unsafe ACL' }
|
|
1249
|
+
$ruleSid = $rules[0].IdentityReference.Value
|
|
1250
|
+
$hasFullControl = ($rules[0].FileSystemRights -band [System.Security.AccessControl.FileSystemRights]::FullControl) -eq [System.Security.AccessControl.FileSystemRights]::FullControl
|
|
1251
|
+
if ($ruleSid -ne $sid.Value -or $rules[0].IsInherited -or -not $hasFullControl -or $rules[0].AccessControlType -ne [System.Security.AccessControl.AccessControlType]::Allow) { throw 'unsafe ACL' }
|
|
1252
|
+
} catch {
|
|
1253
|
+
$type = $_.Exception.GetType().FullName
|
|
1254
|
+
$hresult = ('0x{0:X8}' -f ($_.Exception.HResult -band 0xffffffffL))
|
|
1255
|
+
[Console]::Error.WriteLine("stage=$stage type=$type hresult=$hresult")
|
|
1256
|
+
exit 1
|
|
1198
1257
|
}
|
|
1199
|
-
|
|
1200
|
-
const
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
}
|
|
1206
|
-
|
|
1258
|
+
`;
|
|
1259
|
+
const result = spawnSync(resolveSystemPowerShellPath(), ["-NoLogo", "-NoProfile", "-NonInteractive", "-Command", script], {
|
|
1260
|
+
encoding: "utf8",
|
|
1261
|
+
env: { ...process.env, [WINDOWS_ACL_PATH_ENV]: directory },
|
|
1262
|
+
stdio: ["ignore", "ignore", "pipe"],
|
|
1263
|
+
windowsHide: true
|
|
1264
|
+
});
|
|
1265
|
+
if (result.status !== 0) {
|
|
1266
|
+
try {
|
|
1267
|
+
fs4.rmdirSync(directory);
|
|
1268
|
+
} catch {
|
|
1269
|
+
}
|
|
1270
|
+
const stderr = typeof result.stderr === "string" ? result.stderr.trim() : "";
|
|
1271
|
+
const safeDetail = /^[A-Za-z0-9_.:=\- ]{1,240}$/u.test(stderr) ? stderr : `stage=spawn type=${result.error?.code ?? "unknown"} hresult=unknown`;
|
|
1272
|
+
throw new Error(`Windows ACL setup failed: ${safeDetail}`);
|
|
1207
1273
|
}
|
|
1208
|
-
|
|
1209
|
-
|
|
1274
|
+
return directory;
|
|
1275
|
+
}
|
|
1276
|
+
function resolveSystemPowerShellPath() {
|
|
1277
|
+
const systemRoot = process.env.SystemRoot?.trim() || process.env.WINDIR?.trim();
|
|
1278
|
+
if (!systemRoot || !path3.win32.isAbsolute(systemRoot))
|
|
1279
|
+
throw new Error("unsafe Windows system root");
|
|
1280
|
+
const executable = path3.win32.join(systemRoot, "System32", "WindowsPowerShell", "v1.0", "powershell.exe");
|
|
1281
|
+
const stat = fs4.lstatSync(executable);
|
|
1282
|
+
if (!stat.isFile() || stat.isSymbolicLink())
|
|
1283
|
+
throw new Error("unsafe Windows PowerShell path");
|
|
1284
|
+
return executable;
|
|
1210
1285
|
}
|
|
1211
|
-
|
|
1212
|
-
const
|
|
1213
|
-
const timer = setTimeout(() => controller.abort(), RELAY_PROBE_TIMEOUT_MS);
|
|
1214
|
-
timer.unref?.();
|
|
1286
|
+
function writeExclusiveFile(filePath, contents) {
|
|
1287
|
+
const descriptor = fs4.openSync(filePath, fs4.constants.O_WRONLY | fs4.constants.O_CREAT | fs4.constants.O_EXCL | (fs4.constants.O_NOFOLLOW ?? 0), 384);
|
|
1215
1288
|
try {
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
});
|
|
1220
|
-
return response.status === 200;
|
|
1221
|
-
} catch {
|
|
1222
|
-
return false;
|
|
1289
|
+
if (process.platform !== "win32")
|
|
1290
|
+
fs4.fchmodSync(descriptor, 384);
|
|
1291
|
+
fs4.writeFileSync(descriptor, contents, "utf8");
|
|
1223
1292
|
} finally {
|
|
1224
|
-
|
|
1293
|
+
fs4.closeSync(descriptor);
|
|
1225
1294
|
}
|
|
1295
|
+
assertSecurePath(filePath, "file");
|
|
1226
1296
|
}
|
|
1227
|
-
function
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1297
|
+
function assertSecurePath(filePath, kind) {
|
|
1298
|
+
const stat = fs4.lstatSync(filePath);
|
|
1299
|
+
if ((kind === "directory" ? !stat.isDirectory() : !stat.isFile()) || stat.isSymbolicLink())
|
|
1300
|
+
throw new Error("unsafe");
|
|
1301
|
+
if (process.platform === "win32")
|
|
1302
|
+
return;
|
|
1303
|
+
if ((stat.mode & 63) !== 0)
|
|
1304
|
+
throw new Error("unsafe");
|
|
1305
|
+
if (typeof process.getuid === "function" && stat.uid !== process.getuid())
|
|
1306
|
+
throw new Error("unsafe");
|
|
1233
1307
|
}
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1308
|
+
function cleanupHandoff(directory, handoffPath, preloadPath) {
|
|
1309
|
+
for (const filePath of [handoffPath, preloadPath]) {
|
|
1310
|
+
try {
|
|
1311
|
+
fs4.unlinkSync(filePath);
|
|
1312
|
+
} catch {
|
|
1313
|
+
}
|
|
1314
|
+
}
|
|
1315
|
+
try {
|
|
1316
|
+
fs4.rmdirSync(directory);
|
|
1317
|
+
} catch {
|
|
1237
1318
|
}
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1319
|
+
}
|
|
1320
|
+
function renderChromeDevtoolsRelayPreloadSource() {
|
|
1321
|
+
return `import fs from 'node:fs';
|
|
1322
|
+
import path from 'node:path';
|
|
1323
|
+
|
|
1324
|
+
const targetPath = process.argv[1]?.replaceAll('\\\\', '/').toLowerCase();
|
|
1325
|
+
if (targetPath?.includes('chrome-devtools-mcp')) {
|
|
1326
|
+
const failureMessage = 'MCPorter Chrome relay authorization handoff unavailable.';
|
|
1327
|
+
const fail = () => {
|
|
1328
|
+
throw new Error(failureMessage);
|
|
1329
|
+
};
|
|
1330
|
+
const envName = ${JSON.stringify(CHROME_RELAY_HANDOFF_ENV)};
|
|
1331
|
+
const handoffPath = process.env[envName];
|
|
1332
|
+
delete process.env[envName];
|
|
1333
|
+
if (!handoffPath || !path.isAbsolute(handoffPath)) fail();
|
|
1334
|
+
|
|
1335
|
+
const directoryStat = (() => {
|
|
1336
|
+
try {
|
|
1337
|
+
return fs.lstatSync(path.dirname(handoffPath));
|
|
1338
|
+
} catch {
|
|
1339
|
+
return fail();
|
|
1340
|
+
}
|
|
1341
|
+
})();
|
|
1342
|
+
if (!directoryStat.isDirectory() || directoryStat.isSymbolicLink()) fail();
|
|
1343
|
+
if (process.platform !== 'win32') {
|
|
1344
|
+
if ((directoryStat.mode & 0o077) !== 0) fail();
|
|
1345
|
+
if (typeof process.getuid === 'function' && directoryStat.uid !== process.getuid()) fail();
|
|
1241
1346
|
}
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1347
|
+
|
|
1348
|
+
const descriptor = (() => {
|
|
1349
|
+
try {
|
|
1350
|
+
return fs.openSync(handoffPath, fs.constants.O_RDONLY | (fs.constants.O_NOFOLLOW ?? 0));
|
|
1351
|
+
} catch {
|
|
1352
|
+
return fail();
|
|
1353
|
+
}
|
|
1354
|
+
})();
|
|
1355
|
+
|
|
1356
|
+
let raw = '';
|
|
1357
|
+
let consumed = false;
|
|
1358
|
+
try {
|
|
1359
|
+
const stat = fs.fstatSync(descriptor);
|
|
1360
|
+
if (!stat.isFile() || stat.size <= 0 || stat.size > 4_096) fail();
|
|
1361
|
+
if (process.platform !== 'win32') {
|
|
1362
|
+
if ((stat.mode & 0o077) !== 0) fail();
|
|
1363
|
+
if (typeof process.getuid === 'function' && stat.uid !== process.getuid()) fail();
|
|
1364
|
+
}
|
|
1365
|
+
raw = fs.readFileSync(descriptor, 'utf8');
|
|
1366
|
+
try {
|
|
1367
|
+
fs.unlinkSync(handoffPath);
|
|
1368
|
+
consumed = true;
|
|
1369
|
+
} catch {
|
|
1370
|
+
try {
|
|
1371
|
+
fs.ftruncateSync(descriptor, 0);
|
|
1372
|
+
consumed = true;
|
|
1373
|
+
} catch {
|
|
1374
|
+
fail();
|
|
1375
|
+
}
|
|
1376
|
+
}
|
|
1377
|
+
} finally {
|
|
1378
|
+
fs.closeSync(descriptor);
|
|
1245
1379
|
}
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1380
|
+
if (!consumed) fail();
|
|
1381
|
+
|
|
1382
|
+
let parsed;
|
|
1383
|
+
try {
|
|
1384
|
+
parsed = JSON.parse(raw);
|
|
1385
|
+
} catch {
|
|
1386
|
+
fail();
|
|
1250
1387
|
}
|
|
1251
|
-
|
|
1252
|
-
const
|
|
1253
|
-
|
|
1254
|
-
|
|
1388
|
+
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) fail();
|
|
1389
|
+
const entries = Object.entries(parsed);
|
|
1390
|
+
if (entries.length !== 1 || entries[0]?.[0] !== 'Authorization') fail();
|
|
1391
|
+
const authorization = entries[0]?.[1];
|
|
1392
|
+
if (typeof authorization !== 'string' || !/^Bearer [A-Za-z0-9_-]{43}$/u.test(authorization)) fail();
|
|
1393
|
+
|
|
1394
|
+
const terminatorIndex = process.argv.indexOf('--', 2);
|
|
1395
|
+
const insertionIndex = terminatorIndex >= 0 ? terminatorIndex : process.argv.length;
|
|
1396
|
+
process.argv.splice(insertionIndex, 0, '--wsHeaders', JSON.stringify({ Authorization: authorization }));
|
|
1397
|
+
}
|
|
1398
|
+
`;
|
|
1255
1399
|
}
|
|
1256
1400
|
|
|
1257
|
-
// node_modules/.pnpm/mcporter@0.13.
|
|
1401
|
+
// node_modules/.pnpm/mcporter@0.13.6/node_modules/mcporter/dist/runtime/cached-auth.js
|
|
1258
1402
|
function hasAuthorizationHeader(headers) {
|
|
1259
1403
|
return Boolean(headers && Object.keys(headers).some((key) => key.toLowerCase() === "authorization"));
|
|
1260
1404
|
}
|
|
@@ -1317,392 +1461,7 @@ async function applyCachedAuthIfAvailable(definition, logger, allowCachedAuth) {
|
|
|
1317
1461
|
}
|
|
1318
1462
|
}
|
|
1319
1463
|
|
|
1320
|
-
// node_modules/.pnpm/mcporter@0.13.
|
|
1321
|
-
import { spawn } from "node:child_process";
|
|
1322
|
-
import { createHash, randomUUID } from "node:crypto";
|
|
1323
|
-
import http from "node:http";
|
|
1324
|
-
import { URL as URL2 } from "node:url";
|
|
1325
|
-
var CALLBACK_HOST = "127.0.0.1";
|
|
1326
|
-
var CALLBACK_PATH = "/callback";
|
|
1327
|
-
var INTERACTIVE_AUTHORIZATION_TTL_MS = 3e5;
|
|
1328
|
-
function createDeferred() {
|
|
1329
|
-
let resolve;
|
|
1330
|
-
let reject;
|
|
1331
|
-
const promise = new Promise((res, rej) => {
|
|
1332
|
-
resolve = res;
|
|
1333
|
-
reject = rej;
|
|
1334
|
-
});
|
|
1335
|
-
return { promise, resolve, reject };
|
|
1336
|
-
}
|
|
1337
|
-
function openExternal(url, platform = process.platform, launch = spawn) {
|
|
1338
|
-
const stdio = "ignore";
|
|
1339
|
-
try {
|
|
1340
|
-
if (platform === "darwin") {
|
|
1341
|
-
const child = launch("open", [url], { stdio, detached: true });
|
|
1342
|
-
child.unref();
|
|
1343
|
-
} else if (platform === "win32") {
|
|
1344
|
-
const child = launch("rundll32", ["url.dll,FileProtocolHandler", url], {
|
|
1345
|
-
stdio,
|
|
1346
|
-
detached: true,
|
|
1347
|
-
windowsHide: true
|
|
1348
|
-
});
|
|
1349
|
-
child.unref();
|
|
1350
|
-
} else {
|
|
1351
|
-
try {
|
|
1352
|
-
const child = launch("xdg-open", [url], { stdio, detached: true });
|
|
1353
|
-
child.on("error", () => {
|
|
1354
|
-
});
|
|
1355
|
-
child.unref();
|
|
1356
|
-
} catch {
|
|
1357
|
-
}
|
|
1358
|
-
}
|
|
1359
|
-
} catch {
|
|
1360
|
-
}
|
|
1361
|
-
}
|
|
1362
|
-
var PersistentOAuthClientProvider = class _PersistentOAuthClientProvider {
|
|
1363
|
-
definition;
|
|
1364
|
-
options;
|
|
1365
|
-
metadata;
|
|
1366
|
-
logger;
|
|
1367
|
-
persistence;
|
|
1368
|
-
redirectUrlValue;
|
|
1369
|
-
authorizationDeferred = null;
|
|
1370
|
-
authorizationRedirectStarted = false;
|
|
1371
|
-
// One interactive authorization transaction per provider: concurrent SDK auth() flows
|
|
1372
|
-
// (background GET reconnect + bridged POST both hitting 401) must not each open a
|
|
1373
|
-
// prompt, because only one persisted PKCE verifier can complete (issue #247).
|
|
1374
|
-
interactiveAuthorization = null;
|
|
1375
|
-
pendingVerifiersByChallenge = /* @__PURE__ */ new Map();
|
|
1376
|
-
server;
|
|
1377
|
-
constructor(definition, persistence, redirectUrl, logger, options = {}) {
|
|
1378
|
-
this.definition = definition;
|
|
1379
|
-
this.options = options;
|
|
1380
|
-
this.redirectUrlValue = redirectUrl;
|
|
1381
|
-
this.logger = logger;
|
|
1382
|
-
this.persistence = persistence;
|
|
1383
|
-
this.metadata = {
|
|
1384
|
-
client_name: definition.clientName ?? `mcporter (${definition.name})`,
|
|
1385
|
-
redirect_uris: [this.redirectUrlValue.toString()],
|
|
1386
|
-
grant_types: ["authorization_code", "refresh_token"],
|
|
1387
|
-
response_types: ["code"],
|
|
1388
|
-
token_endpoint_auth_method: "none",
|
|
1389
|
-
// Omit scope so the MCP SDK can derive it from the server's metadata
|
|
1390
|
-
// (resource metadata scopes_supported or auth server scopes_supported).
|
|
1391
|
-
// Hardcoding 'mcp:tools' breaks providers like Granola whose auth server
|
|
1392
|
-
// does not recognise that scope value.
|
|
1393
|
-
// If oauthScope is explicitly configured, prefer that exact value.
|
|
1394
|
-
...definition.oauthScope !== void 0 ? { scope: definition.oauthScope || void 0 } : {}
|
|
1395
|
-
};
|
|
1396
|
-
}
|
|
1397
|
-
static async create(definition, logger, options = {}) {
|
|
1398
|
-
validateClientMetadataUrl(definition.oauthClientMetadataUrl);
|
|
1399
|
-
const persistence = await buildOAuthPersistence(definition, logger);
|
|
1400
|
-
const server = http.createServer();
|
|
1401
|
-
const overrideRedirect = definition.oauthRedirectUrl ? new URL2(definition.oauthRedirectUrl) : null;
|
|
1402
|
-
const listenHost = overrideRedirect?.hostname ?? CALLBACK_HOST;
|
|
1403
|
-
const overridePort = overrideRedirect?.port ?? "";
|
|
1404
|
-
const usesDynamicPort = !overrideRedirect || overridePort === "" || overridePort === "0";
|
|
1405
|
-
const desiredPort = usesDynamicPort ? void 0 : Number.parseInt(overridePort, 10);
|
|
1406
|
-
const callbackPath = overrideRedirect?.pathname && overrideRedirect.pathname !== "/" ? overrideRedirect.pathname : CALLBACK_PATH;
|
|
1407
|
-
const port = await new Promise((resolve, reject) => {
|
|
1408
|
-
server.listen(desiredPort ?? 0, listenHost, () => {
|
|
1409
|
-
const address = server.address();
|
|
1410
|
-
if (typeof address === "object" && address && "port" in address) {
|
|
1411
|
-
resolve(address.port);
|
|
1412
|
-
} else {
|
|
1413
|
-
reject(new Error("Failed to determine callback port"));
|
|
1414
|
-
}
|
|
1415
|
-
});
|
|
1416
|
-
server.once("error", (error) => reject(error));
|
|
1417
|
-
});
|
|
1418
|
-
const redirectUrl = overrideRedirect ? new URL2(overrideRedirect.toString()) : new URL2(`http://${listenHost}:${port}${callbackPath}`);
|
|
1419
|
-
if (usesDynamicPort) {
|
|
1420
|
-
redirectUrl.port = String(port);
|
|
1421
|
-
}
|
|
1422
|
-
if (!overrideRedirect || overrideRedirect.pathname === "/" || overrideRedirect.pathname === "") {
|
|
1423
|
-
redirectUrl.pathname = callbackPath;
|
|
1424
|
-
}
|
|
1425
|
-
if (usesDynamicPort) {
|
|
1426
|
-
try {
|
|
1427
|
-
const cachedClient = await persistence.readClientInfo();
|
|
1428
|
-
const cachedRedirect = firstRedirectUri(cachedClient);
|
|
1429
|
-
if (cachedRedirect && cachedRedirect !== redirectUrl.toString()) {
|
|
1430
|
-
logger.info(`Redirect URI changed (${cachedRedirect} \u2192 ${redirectUrl.toString()}); clearing stale client registration.`);
|
|
1431
|
-
await persistence.clear("client");
|
|
1432
|
-
}
|
|
1433
|
-
} catch (error) {
|
|
1434
|
-
await new Promise((resolve) => {
|
|
1435
|
-
server.close(() => resolve());
|
|
1436
|
-
});
|
|
1437
|
-
throw error;
|
|
1438
|
-
}
|
|
1439
|
-
}
|
|
1440
|
-
const provider = new _PersistentOAuthClientProvider(definition, persistence, redirectUrl, logger, options);
|
|
1441
|
-
provider.attachServer(server);
|
|
1442
|
-
return {
|
|
1443
|
-
provider,
|
|
1444
|
-
close: async () => {
|
|
1445
|
-
await provider.close();
|
|
1446
|
-
}
|
|
1447
|
-
};
|
|
1448
|
-
}
|
|
1449
|
-
// attachServer listens for the OAuth redirect and resolves/rejects the deferred code promise.
|
|
1450
|
-
attachServer(server) {
|
|
1451
|
-
this.server = server;
|
|
1452
|
-
server.on("request", async (req, res) => {
|
|
1453
|
-
try {
|
|
1454
|
-
const url = req.url ?? "";
|
|
1455
|
-
const parsed = new URL2(url, this.redirectUrlValue);
|
|
1456
|
-
const expectedPath = this.redirectUrlValue.pathname || "/callback";
|
|
1457
|
-
if (parsed.pathname !== expectedPath) {
|
|
1458
|
-
res.statusCode = 404;
|
|
1459
|
-
res.end("Not found");
|
|
1460
|
-
return;
|
|
1461
|
-
}
|
|
1462
|
-
const code = parsed.searchParams.get("code");
|
|
1463
|
-
const error = parsed.searchParams.get("error");
|
|
1464
|
-
const receivedState = parsed.searchParams.get("state");
|
|
1465
|
-
const iss = parsed.searchParams.get("iss") ?? void 0;
|
|
1466
|
-
const expectedState = await this.persistence.readState();
|
|
1467
|
-
if (expectedState && receivedState !== expectedState) {
|
|
1468
|
-
res.statusCode = 400;
|
|
1469
|
-
res.setHeader("Content-Type", "text/html");
|
|
1470
|
-
res.end("<html><body><h1>Authorization failed</h1><p>Invalid OAuth state</p></body></html>");
|
|
1471
|
-
this.authorizationDeferred?.reject(new Error("Invalid OAuth state"));
|
|
1472
|
-
this.authorizationDeferred = null;
|
|
1473
|
-
this.clearInteractiveAuthorization();
|
|
1474
|
-
return;
|
|
1475
|
-
}
|
|
1476
|
-
if (code) {
|
|
1477
|
-
this.logger.info(`Received OAuth authorization code for ${this.definition.name}`);
|
|
1478
|
-
res.statusCode = 200;
|
|
1479
|
-
res.setHeader("Content-Type", "text/html");
|
|
1480
|
-
res.end("<html><body><h1>Authorization successful</h1><p>You can return to the CLI.</p></body></html>");
|
|
1481
|
-
this.authorizationDeferred?.resolve({ code, iss });
|
|
1482
|
-
this.authorizationDeferred = null;
|
|
1483
|
-
this.clearInteractiveAuthorization();
|
|
1484
|
-
} else if (error) {
|
|
1485
|
-
res.statusCode = 400;
|
|
1486
|
-
res.setHeader("Content-Type", "text/html");
|
|
1487
|
-
res.end("<html><body><h1>Authorization failed</h1><p>Return to the CLI for details.</p></body></html>");
|
|
1488
|
-
this.authorizationDeferred?.reject(new Error("OAuth authorization failed."));
|
|
1489
|
-
this.authorizationDeferred = null;
|
|
1490
|
-
this.clearInteractiveAuthorization();
|
|
1491
|
-
} else {
|
|
1492
|
-
res.statusCode = 400;
|
|
1493
|
-
res.end("Missing authorization code");
|
|
1494
|
-
this.authorizationDeferred?.reject(new Error("Missing authorization code"));
|
|
1495
|
-
this.authorizationDeferred = null;
|
|
1496
|
-
this.clearInteractiveAuthorization();
|
|
1497
|
-
}
|
|
1498
|
-
} catch (error) {
|
|
1499
|
-
this.authorizationDeferred?.reject(error);
|
|
1500
|
-
this.authorizationDeferred = null;
|
|
1501
|
-
this.clearInteractiveAuthorization();
|
|
1502
|
-
}
|
|
1503
|
-
});
|
|
1504
|
-
}
|
|
1505
|
-
get redirectUrl() {
|
|
1506
|
-
return this.redirectUrlValue;
|
|
1507
|
-
}
|
|
1508
|
-
get clientMetadata() {
|
|
1509
|
-
return this.metadata;
|
|
1510
|
-
}
|
|
1511
|
-
get clientMetadataUrl() {
|
|
1512
|
-
return this.definition.oauthClientMetadataUrl;
|
|
1513
|
-
}
|
|
1514
|
-
async state() {
|
|
1515
|
-
const existing = await this.persistence.readState();
|
|
1516
|
-
if (existing) {
|
|
1517
|
-
return existing;
|
|
1518
|
-
}
|
|
1519
|
-
const state = randomUUID();
|
|
1520
|
-
await this.persistence.saveState(state);
|
|
1521
|
-
return state;
|
|
1522
|
-
}
|
|
1523
|
-
async clientInformation(ctx) {
|
|
1524
|
-
const staticClient = buildStaticClientInformation(this.definition, { redirectUrl: this.redirectUrlValue });
|
|
1525
|
-
if (staticClient) {
|
|
1526
|
-
return { ...staticClient, ...ctx ? { issuer: ctx.issuer } : {} };
|
|
1527
|
-
}
|
|
1528
|
-
const stored = await this.persistence.readClientInfo();
|
|
1529
|
-
if (ctx && stored?.issuer && !issuersMatch(stored.issuer, ctx.issuer)) {
|
|
1530
|
-
await this.persistence.clear("client");
|
|
1531
|
-
this.logger.info(`Discarded OAuth client registration for ${this.definition.name} after issuer changed.`);
|
|
1532
|
-
return void 0;
|
|
1533
|
-
}
|
|
1534
|
-
return stored;
|
|
1535
|
-
}
|
|
1536
|
-
async saveClientInformation(clientInformation) {
|
|
1537
|
-
await this.persistence.saveClientInfo(clientInformation);
|
|
1538
|
-
}
|
|
1539
|
-
async tokens(ctx) {
|
|
1540
|
-
const stored = await this.persistence.readTokens();
|
|
1541
|
-
if (ctx && stored?.issuer && !issuersMatch(stored.issuer, ctx.issuer)) {
|
|
1542
|
-
await this.persistence.clear("tokens");
|
|
1543
|
-
this.logger.info(`Discarded OAuth tokens for ${this.definition.name} after issuer changed.`);
|
|
1544
|
-
return void 0;
|
|
1545
|
-
}
|
|
1546
|
-
return stored;
|
|
1547
|
-
}
|
|
1548
|
-
async saveTokens(tokens) {
|
|
1549
|
-
await this.persistence.saveTokens(tokens);
|
|
1550
|
-
this.logger.info(`Saved OAuth tokens for ${this.definition.name} (${this.persistence.describe()})`);
|
|
1551
|
-
}
|
|
1552
|
-
async redirectToAuthorization(authorizationUrl) {
|
|
1553
|
-
this.authorizationRedirectStarted = true;
|
|
1554
|
-
this.ensureAuthorizationDeferred();
|
|
1555
|
-
const challenge = authorizationUrl.searchParams.get("code_challenge");
|
|
1556
|
-
if (this.hasActiveInteractiveAuthorization()) {
|
|
1557
|
-
if (challenge) {
|
|
1558
|
-
this.pendingVerifiersByChallenge.delete(challenge);
|
|
1559
|
-
}
|
|
1560
|
-
this.logger.info(`Authorization already pending for ${this.definition.name}; suppressing duplicate prompt.`);
|
|
1561
|
-
return;
|
|
1562
|
-
}
|
|
1563
|
-
this.interactiveAuthorization = { challenge, claimedAt: Date.now() };
|
|
1564
|
-
const claimedVerifier = challenge ? this.pendingVerifiersByChallenge.get(challenge) : void 0;
|
|
1565
|
-
if (challenge) {
|
|
1566
|
-
this.pendingVerifiersByChallenge.delete(challenge);
|
|
1567
|
-
}
|
|
1568
|
-
if (claimedVerifier) {
|
|
1569
|
-
await this.persistence.saveCodeVerifier(claimedVerifier);
|
|
1570
|
-
}
|
|
1571
|
-
const request = {
|
|
1572
|
-
authorizationUrl: authorizationUrl.toString(),
|
|
1573
|
-
redirectUrl: this.redirectUrlValue.toString()
|
|
1574
|
-
};
|
|
1575
|
-
if (this.options.suppressBrowserLaunch) {
|
|
1576
|
-
await this.options.onAuthorizationUrl?.(request);
|
|
1577
|
-
return;
|
|
1578
|
-
}
|
|
1579
|
-
this.logger.info(`Authorization required for ${this.definition.name}. Opening browser...`);
|
|
1580
|
-
__oauthInternals.openExternal(request.authorizationUrl);
|
|
1581
|
-
this.logger.warn(`If the browser did not open, visit ${request.authorizationUrl} manually.`);
|
|
1582
|
-
}
|
|
1583
|
-
hasAuthorizationRedirectStarted() {
|
|
1584
|
-
return this.authorizationRedirectStarted;
|
|
1585
|
-
}
|
|
1586
|
-
async saveCodeVerifier(codeVerifier) {
|
|
1587
|
-
this.pendingVerifiersByChallenge.set(challengeForVerifier(codeVerifier), codeVerifier);
|
|
1588
|
-
if (this.hasActiveInteractiveAuthorization()) {
|
|
1589
|
-
return;
|
|
1590
|
-
}
|
|
1591
|
-
await this.persistence.saveCodeVerifier(codeVerifier);
|
|
1592
|
-
}
|
|
1593
|
-
async codeVerifier() {
|
|
1594
|
-
const value = await this.persistence.readCodeVerifier();
|
|
1595
|
-
if (!value) {
|
|
1596
|
-
throw new Error(`Missing PKCE code verifier for ${this.definition.name}`);
|
|
1597
|
-
}
|
|
1598
|
-
return value.trim();
|
|
1599
|
-
}
|
|
1600
|
-
// invalidateCredentials removes cached files to force the next OAuth flow.
|
|
1601
|
-
async invalidateCredentials(scope) {
|
|
1602
|
-
if (scope === "all" || scope === "verifier") {
|
|
1603
|
-
this.clearInteractiveAuthorization();
|
|
1604
|
-
}
|
|
1605
|
-
await this.persistence.clear(scope);
|
|
1606
|
-
}
|
|
1607
|
-
async saveDiscoveryState(state) {
|
|
1608
|
-
await this.persistence.saveDiscoveryState(state);
|
|
1609
|
-
}
|
|
1610
|
-
async discoveryState() {
|
|
1611
|
-
return this.persistence.readDiscoveryState();
|
|
1612
|
-
}
|
|
1613
|
-
async saveAuthorizationServerUrl(url) {
|
|
1614
|
-
await this.persistence.saveAuthorizationServerUrl(url);
|
|
1615
|
-
}
|
|
1616
|
-
async authorizationServerUrl() {
|
|
1617
|
-
return this.persistence.readAuthorizationServerUrl();
|
|
1618
|
-
}
|
|
1619
|
-
async saveResourceUrl(url) {
|
|
1620
|
-
await this.persistence.saveResourceUrl(url);
|
|
1621
|
-
}
|
|
1622
|
-
async resourceUrl() {
|
|
1623
|
-
return this.persistence.readResourceUrl();
|
|
1624
|
-
}
|
|
1625
|
-
// waitForAuthorizationCode resolves once the local callback server captures a redirect.
|
|
1626
|
-
// The same deferred is shared with redirectToAuthorization so callback resolution is stable.
|
|
1627
|
-
async waitForAuthorizationCode() {
|
|
1628
|
-
return (await this.waitForAuthorizationResponse()).code;
|
|
1629
|
-
}
|
|
1630
|
-
async waitForAuthorizationResponse() {
|
|
1631
|
-
return this.ensureAuthorizationDeferred().promise;
|
|
1632
|
-
}
|
|
1633
|
-
// close stops the temporary callback server created for the OAuth session.
|
|
1634
|
-
async close() {
|
|
1635
|
-
if (this.authorizationDeferred) {
|
|
1636
|
-
this.authorizationDeferred.reject(new Error("OAuth session closed before receiving authorization code."));
|
|
1637
|
-
this.authorizationDeferred = null;
|
|
1638
|
-
this.clearInteractiveAuthorization();
|
|
1639
|
-
}
|
|
1640
|
-
if (!this.server) {
|
|
1641
|
-
return;
|
|
1642
|
-
}
|
|
1643
|
-
this.server.closeAllConnections?.();
|
|
1644
|
-
const server = this.server;
|
|
1645
|
-
this.server = void 0;
|
|
1646
|
-
await new Promise((resolve) => {
|
|
1647
|
-
server.close(() => resolve());
|
|
1648
|
-
});
|
|
1649
|
-
}
|
|
1650
|
-
ensureAuthorizationDeferred() {
|
|
1651
|
-
if (!this.authorizationDeferred) {
|
|
1652
|
-
this.authorizationDeferred = createDeferred();
|
|
1653
|
-
}
|
|
1654
|
-
return this.authorizationDeferred;
|
|
1655
|
-
}
|
|
1656
|
-
hasActiveInteractiveAuthorization() {
|
|
1657
|
-
if (!this.interactiveAuthorization) {
|
|
1658
|
-
return false;
|
|
1659
|
-
}
|
|
1660
|
-
if (Date.now() - this.interactiveAuthorization.claimedAt > INTERACTIVE_AUTHORIZATION_TTL_MS) {
|
|
1661
|
-
this.interactiveAuthorization = null;
|
|
1662
|
-
return false;
|
|
1663
|
-
}
|
|
1664
|
-
return true;
|
|
1665
|
-
}
|
|
1666
|
-
clearInteractiveAuthorization() {
|
|
1667
|
-
this.interactiveAuthorization = null;
|
|
1668
|
-
this.pendingVerifiersByChallenge.clear();
|
|
1669
|
-
}
|
|
1670
|
-
};
|
|
1671
|
-
async function createOAuthSession(definition, logger, options = {}) {
|
|
1672
|
-
const { provider, close } = await PersistentOAuthClientProvider.create(definition, logger, options);
|
|
1673
|
-
const waitForAuthorizationCode = () => provider.waitForAuthorizationCode();
|
|
1674
|
-
const waitForAuthorizationResponse = () => provider.waitForAuthorizationResponse();
|
|
1675
|
-
const hasAuthorizationRedirectStarted = () => provider.hasAuthorizationRedirectStarted();
|
|
1676
|
-
return {
|
|
1677
|
-
provider,
|
|
1678
|
-
waitForAuthorizationCode,
|
|
1679
|
-
waitForAuthorizationResponse,
|
|
1680
|
-
hasAuthorizationRedirectStarted,
|
|
1681
|
-
close
|
|
1682
|
-
};
|
|
1683
|
-
}
|
|
1684
|
-
function challengeForVerifier(verifier) {
|
|
1685
|
-
return createHash("sha256").update(verifier).digest("base64url");
|
|
1686
|
-
}
|
|
1687
|
-
function firstRedirectUri(client) {
|
|
1688
|
-
if (!client || typeof client !== "object") {
|
|
1689
|
-
return void 0;
|
|
1690
|
-
}
|
|
1691
|
-
const redirectUris = client.redirect_uris;
|
|
1692
|
-
if (!Array.isArray(redirectUris)) {
|
|
1693
|
-
return void 0;
|
|
1694
|
-
}
|
|
1695
|
-
const [first] = redirectUris;
|
|
1696
|
-
return typeof first === "string" ? first : void 0;
|
|
1697
|
-
}
|
|
1698
|
-
function issuersMatch(first, second) {
|
|
1699
|
-
return first === second || first.endsWith("/") && first.slice(0, -1) === second || second.endsWith("/") && second.slice(0, -1) === first;
|
|
1700
|
-
}
|
|
1701
|
-
var __oauthInternals = {
|
|
1702
|
-
openExternal
|
|
1703
|
-
};
|
|
1704
|
-
|
|
1705
|
-
// node_modules/.pnpm/mcporter@0.13.0/node_modules/mcporter/dist/runtime-header-utils.js
|
|
1464
|
+
// node_modules/.pnpm/mcporter@0.13.6/node_modules/mcporter/dist/runtime-header-utils.js
|
|
1706
1465
|
function materializeHeaders(headers, serverName) {
|
|
1707
1466
|
if (!headers) {
|
|
1708
1467
|
return void 0;
|
|
@@ -1719,8 +1478,8 @@ function materializeHeaders(headers, serverName) {
|
|
|
1719
1478
|
return resolved;
|
|
1720
1479
|
}
|
|
1721
1480
|
|
|
1722
|
-
// node_modules/.pnpm/mcporter@0.13.
|
|
1723
|
-
import
|
|
1481
|
+
// node_modules/.pnpm/mcporter@0.13.6/node_modules/mcporter/dist/runtime/node-http-fetch.js
|
|
1482
|
+
import http from "node:http";
|
|
1724
1483
|
import https from "node:https";
|
|
1725
1484
|
import { Buffer as Buffer2 } from "node:buffer";
|
|
1726
1485
|
import { Readable } from "node:stream";
|
|
@@ -1755,7 +1514,7 @@ async function nodeHttp1FetchWithRedirects(input, init, redirectCount) {
|
|
|
1755
1514
|
headers["content-length"] = String(Buffer2.byteLength(body));
|
|
1756
1515
|
}
|
|
1757
1516
|
return new Promise((resolve, reject) => {
|
|
1758
|
-
const client = url.protocol === "https:" ? https :
|
|
1517
|
+
const client = url.protocol === "https:" ? https : http;
|
|
1759
1518
|
const request = client.request(url, {
|
|
1760
1519
|
method: init.method ?? "GET",
|
|
1761
1520
|
headers
|
|
@@ -1875,7 +1634,7 @@ async function materializeRequestBody(body) {
|
|
|
1875
1634
|
throw new TypeError("node-http1 fetch does not support streaming request bodies.");
|
|
1876
1635
|
}
|
|
1877
1636
|
|
|
1878
|
-
// node_modules/.pnpm/mcporter@0.13.
|
|
1637
|
+
// node_modules/.pnpm/mcporter@0.13.6/node_modules/mcporter/dist/runtime/http-transport.js
|
|
1879
1638
|
function extractTransportStatusCode(error) {
|
|
1880
1639
|
if (!error || typeof error !== "object")
|
|
1881
1640
|
return void 0;
|
|
@@ -1910,6 +1669,7 @@ function removeAuthorizationHeader(headers) {
|
|
|
1910
1669
|
return Object.keys(headers).length > 0 ? headers : void 0;
|
|
1911
1670
|
}
|
|
1912
1671
|
var NODE_HTTP1_FETCH_HOSTS = /* @__PURE__ */ new Set(["api.sunsama.com"]);
|
|
1672
|
+
var STANDALONE_SSE_START_GRACE_MS = 250;
|
|
1913
1673
|
function resolveHttpFetchOverride(definition) {
|
|
1914
1674
|
if (definition.command.kind !== "http" || definition.httpFetch === "default")
|
|
1915
1675
|
return void 0;
|
|
@@ -1954,6 +1714,26 @@ function trackStandaloneSseFetch(fetchOverride) {
|
|
|
1954
1714
|
}
|
|
1955
1715
|
};
|
|
1956
1716
|
}
|
|
1717
|
+
function waitForStandaloneSseStart(started, signal) {
|
|
1718
|
+
if (signal?.aborted)
|
|
1719
|
+
return Promise.resolve();
|
|
1720
|
+
return new Promise((resolve) => {
|
|
1721
|
+
let settled = false;
|
|
1722
|
+
const finish = () => {
|
|
1723
|
+
if (settled)
|
|
1724
|
+
return;
|
|
1725
|
+
settled = true;
|
|
1726
|
+
clearTimeout(timer);
|
|
1727
|
+
signal?.removeEventListener("abort", finish);
|
|
1728
|
+
resolve();
|
|
1729
|
+
};
|
|
1730
|
+
const timer = setTimeout(finish, STANDALONE_SSE_START_GRACE_MS);
|
|
1731
|
+
signal?.addEventListener("abort", finish, { once: true });
|
|
1732
|
+
if (signal?.aborted)
|
|
1733
|
+
finish();
|
|
1734
|
+
void started.then(finish);
|
|
1735
|
+
});
|
|
1736
|
+
}
|
|
1957
1737
|
async function closeOAuthSession(oauthSession) {
|
|
1958
1738
|
await oauthSession?.close().catch(() => {
|
|
1959
1739
|
});
|
|
@@ -1961,7 +1741,11 @@ async function closeOAuthSession(oauthSession) {
|
|
|
1961
1741
|
function shouldAbortSseFallback(error) {
|
|
1962
1742
|
if (isPostAuthConnectError(error))
|
|
1963
1743
|
return !isLegacySseTransportMismatch(error);
|
|
1964
|
-
|
|
1744
|
+
if (isOAuthFlowError(error) || error instanceof OAuthTimeoutError)
|
|
1745
|
+
return true;
|
|
1746
|
+
if (isUnauthorizedError(error))
|
|
1747
|
+
return false;
|
|
1748
|
+
return !isLegacySseTransportMismatch(error);
|
|
1965
1749
|
}
|
|
1966
1750
|
function isEraNegotiationFailure(error) {
|
|
1967
1751
|
return !!error && typeof error === "object" && "code" in error && error.code === SdkErrorCode.EraNegotiationFailed;
|
|
@@ -2042,18 +1826,20 @@ async function connectPrimaryHttpTransport(client, definition, command, transpor
|
|
|
2042
1826
|
recreateTransport: async () => createStreamableTransport()
|
|
2043
1827
|
});
|
|
2044
1828
|
if (typeof client.getProtocolEra === "function" && client.getProtocolEra() === "legacy") {
|
|
2045
|
-
await transportOptions.standaloneSseStarted;
|
|
1829
|
+
await waitForStandaloneSseStart(transportOptions.standaloneSseStarted, options.signal);
|
|
2046
1830
|
}
|
|
2047
1831
|
return { client, transport, definition, oauthSession };
|
|
2048
1832
|
}
|
|
2049
1833
|
async function connectSseFallbackTransport(client, definition, command, transportOptions, oauthSession, logger, options, wrapRecordTransport2, clientFactory) {
|
|
1834
|
+
const createSseTransport = () => wrapRecordTransport2(new SSEClientTransport(command.url, transportOptions), definition, options);
|
|
2050
1835
|
try {
|
|
2051
|
-
const transport = await connectHttpTransport(client,
|
|
1836
|
+
const transport = await connectHttpTransport(client, createSseTransport(), oauthSession, logger, {
|
|
2052
1837
|
serverName: definition.name,
|
|
2053
1838
|
serverUrl: command.url,
|
|
2054
1839
|
maxAttempts: options.maxOAuthAttempts,
|
|
2055
1840
|
oauthTimeoutMs: options.oauthTimeoutMs,
|
|
2056
|
-
signal: options.signal
|
|
1841
|
+
signal: options.signal,
|
|
1842
|
+
recreateTransport: async () => createSseTransport()
|
|
2057
1843
|
});
|
|
2058
1844
|
return { client, transport, definition, oauthSession };
|
|
2059
1845
|
} catch (sseError) {
|
|
@@ -2066,8 +1852,7 @@ async function connectSseFallbackTransport(client, definition, command, transpor
|
|
|
2066
1852
|
options.onDefinitionPromoted?.(promoted);
|
|
2067
1853
|
return createHttpClientContext(promoted, logger, options, wrapRecordTransport2, clientFactory);
|
|
2068
1854
|
}
|
|
2069
|
-
|
|
2070
|
-
throw sseError;
|
|
1855
|
+
throw sseError;
|
|
2071
1856
|
}
|
|
2072
1857
|
throw sseError;
|
|
2073
1858
|
}
|
|
@@ -2279,8 +2064,9 @@ var StdioClientTransport = class {
|
|
|
2279
2064
|
}
|
|
2280
2065
|
};
|
|
2281
2066
|
|
|
2282
|
-
// node_modules/.pnpm/mcporter@0.13.
|
|
2067
|
+
// node_modules/.pnpm/mcporter@0.13.6/node_modules/mcporter/dist/runtime/stdio-transport.js
|
|
2283
2068
|
var McporterStdioTransport = class extends StdioClientTransport {
|
|
2069
|
+
parameters;
|
|
2284
2070
|
meta;
|
|
2285
2071
|
closing = false;
|
|
2286
2072
|
closeDelegate;
|
|
@@ -2288,6 +2074,7 @@ var McporterStdioTransport = class extends StdioClientTransport {
|
|
|
2288
2074
|
closeInterceptor = () => {
|
|
2289
2075
|
this.meta.code = this.closing ? 0 : 1;
|
|
2290
2076
|
flushStdioLogs(this.meta);
|
|
2077
|
+
void this.cleanup();
|
|
2291
2078
|
this.closeDelegate?.();
|
|
2292
2079
|
};
|
|
2293
2080
|
messageInterceptor = (message) => {
|
|
@@ -2295,8 +2082,10 @@ var McporterStdioTransport = class extends StdioClientTransport {
|
|
|
2295
2082
|
this.meta.stdoutChunks?.push(JSON.stringify(message));
|
|
2296
2083
|
this.messageDelegate?.(message);
|
|
2297
2084
|
};
|
|
2085
|
+
cleanupPromise;
|
|
2298
2086
|
constructor(parameters) {
|
|
2299
2087
|
super({ ...parameters, stderr: "pipe" });
|
|
2088
|
+
this.parameters = parameters;
|
|
2300
2089
|
this.meta = {
|
|
2301
2090
|
stderrChunks: [],
|
|
2302
2091
|
stdoutChunks: STDIO_TRACE_ENABLED ? [] : void 0,
|
|
@@ -2339,8 +2128,14 @@ var McporterStdioTransport = class extends StdioClientTransport {
|
|
|
2339
2128
|
} finally {
|
|
2340
2129
|
this.meta.code ??= 0;
|
|
2341
2130
|
flushStdioLogs(this.meta);
|
|
2131
|
+
await this.cleanup();
|
|
2342
2132
|
}
|
|
2343
2133
|
}
|
|
2134
|
+
cleanup() {
|
|
2135
|
+
this.cleanupPromise ??= Promise.resolve(this.parameters.cleanup?.()).catch(() => {
|
|
2136
|
+
});
|
|
2137
|
+
return this.cleanupPromise;
|
|
2138
|
+
}
|
|
2344
2139
|
installInterceptors() {
|
|
2345
2140
|
if (this.onclose !== this.closeInterceptor) {
|
|
2346
2141
|
this.closeDelegate = this.onclose;
|
|
@@ -2353,7 +2148,7 @@ var McporterStdioTransport = class extends StdioClientTransport {
|
|
|
2353
2148
|
}
|
|
2354
2149
|
};
|
|
2355
2150
|
|
|
2356
|
-
// node_modules/.pnpm/mcporter@0.13.
|
|
2151
|
+
// node_modules/.pnpm/mcporter@0.13.6/node_modules/mcporter/dist/runtime/transport.js
|
|
2357
2152
|
function shouldUseModeForServer(definition, serverFilter) {
|
|
2358
2153
|
return !serverFilter || serverFilter === definition.name;
|
|
2359
2154
|
}
|
|
@@ -2414,33 +2209,85 @@ async function createReplayClientContext(definition, replayPath, clientInfo, opt
|
|
|
2414
2209
|
return { client, transport, definition, oauthSession: void 0 };
|
|
2415
2210
|
}
|
|
2416
2211
|
async function createStdioClientContext(client, definition, logger, options) {
|
|
2417
|
-
const
|
|
2418
|
-
const mergedEnv = resolvedEnvOverrides && Object.keys(resolvedEnvOverrides).length > 0 ? { ...process.env, ...resolvedEnvOverrides } : { ...process.env };
|
|
2212
|
+
const mergedEnv = resolveChromeDevtoolsRelayEnvironment(definition.env);
|
|
2419
2213
|
const command = resolveCommandArgument(definition.command.command);
|
|
2420
2214
|
const resolvedArgs = resolveCommandArguments(definition.command.args);
|
|
2421
|
-
const
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
}
|
|
2436
|
-
|
|
2215
|
+
const publishRelayDecision = (decision) => {
|
|
2216
|
+
if (decision.reason === "not-eligible")
|
|
2217
|
+
return;
|
|
2218
|
+
recordChromeDevtoolsRelayDecision(definition.name, decision);
|
|
2219
|
+
logger.info(`Chrome DevTools relay decision ${formatChromeDevtoolsRelayDecision(decision)}`);
|
|
2220
|
+
};
|
|
2221
|
+
let relayDecision;
|
|
2222
|
+
let relay;
|
|
2223
|
+
try {
|
|
2224
|
+
relay = await rewriteChromeDevtoolsArgsForRelay(command, resolvedArgs, mergedEnv, { onDecision: (decision) => relayDecision = decision }, definition.chromeDevtoolsRelay);
|
|
2225
|
+
} catch (error) {
|
|
2226
|
+
if (relayDecision)
|
|
2227
|
+
publishRelayDecision(relayDecision);
|
|
2228
|
+
throw error;
|
|
2229
|
+
}
|
|
2230
|
+
let commandArgs = [...relay.args];
|
|
2231
|
+
let activeProxy = relay.proxy;
|
|
2232
|
+
let handoff;
|
|
2233
|
+
let rawTransport;
|
|
2234
|
+
try {
|
|
2235
|
+
if (activeProxy) {
|
|
2236
|
+
try {
|
|
2237
|
+
handoff = createChromeDevtoolsRelayHandoff(mergedEnv, activeProxy.consumeClientAuthorization());
|
|
2238
|
+
} catch {
|
|
2239
|
+
await activeProxy.close().catch(() => {
|
|
2240
|
+
});
|
|
2241
|
+
activeProxy = void 0;
|
|
2242
|
+
relayDecision = {
|
|
2243
|
+
...relay.decision,
|
|
2244
|
+
route: relay.decision.policy === "require" ? "unavailable" : "legacy",
|
|
2245
|
+
reason: "handoff-error"
|
|
2246
|
+
};
|
|
2247
|
+
if (relay.decision.policy === "require") {
|
|
2248
|
+
publishRelayDecision(relayDecision);
|
|
2249
|
+
throw new ChromeDevtoolsRelayRequiredError(relayDecision);
|
|
2250
|
+
}
|
|
2251
|
+
commandArgs = [...resolvedArgs];
|
|
2252
|
+
}
|
|
2253
|
+
}
|
|
2254
|
+
const transportEnv = handoff?.env ?? mergedEnv;
|
|
2255
|
+
const compat = applyChromeDevtoolsCompat(transportEnv, command, commandArgs);
|
|
2256
|
+
if (compat.applied) {
|
|
2257
|
+
logger.info(`Injecting chrome-devtools-mcp --autoConnect compatibility patch from ${compat.patchPath}.`);
|
|
2258
|
+
}
|
|
2259
|
+
if (relayDecision)
|
|
2260
|
+
publishRelayDecision(relayDecision);
|
|
2261
|
+
rawTransport = new McporterStdioTransport({
|
|
2262
|
+
command,
|
|
2263
|
+
args: commandArgs,
|
|
2264
|
+
cwd: definition.command.cwd,
|
|
2265
|
+
env: compat.env,
|
|
2266
|
+
cleanup: activeProxy ? async () => {
|
|
2267
|
+
await handoff?.close();
|
|
2268
|
+
await activeProxy?.close();
|
|
2269
|
+
} : void 0
|
|
2270
|
+
});
|
|
2271
|
+
} catch (error) {
|
|
2272
|
+
await handoff?.close().catch(() => {
|
|
2273
|
+
});
|
|
2274
|
+
await activeProxy?.close().catch(() => {
|
|
2275
|
+
});
|
|
2276
|
+
throw error;
|
|
2277
|
+
}
|
|
2278
|
+
let transport;
|
|
2279
|
+
try {
|
|
2280
|
+
transport = wrapRecordTransport(rawTransport, definition, options);
|
|
2281
|
+
} catch (error) {
|
|
2282
|
+
await closeTransportAndWait(logger, rawTransport).catch(() => {
|
|
2283
|
+
});
|
|
2284
|
+
throw error;
|
|
2285
|
+
}
|
|
2437
2286
|
try {
|
|
2438
2287
|
await client.connect(transport, { signal: options.signal });
|
|
2439
2288
|
} catch (error) {
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
});
|
|
2443
|
-
}
|
|
2289
|
+
await closeTransportAndWait(logger, transport).catch(() => {
|
|
2290
|
+
});
|
|
2444
2291
|
throw error;
|
|
2445
2292
|
}
|
|
2446
2293
|
return { client, transport, definition, oauthSession: void 0 };
|
|
@@ -2477,7 +2324,7 @@ async function createClientContext(definition, logger, clientInfo, options = {})
|
|
|
2477
2324
|
});
|
|
2478
2325
|
}
|
|
2479
2326
|
|
|
2480
|
-
// node_modules/.pnpm/mcporter@0.13.
|
|
2327
|
+
// node_modules/.pnpm/mcporter@0.13.6/node_modules/mcporter/dist/runtime/connection-cache.js
|
|
2481
2328
|
var RuntimeConnectionCache = class {
|
|
2482
2329
|
definitions;
|
|
2483
2330
|
options;
|
|
@@ -3030,7 +2877,7 @@ function connectionInfoFromClient(client) {
|
|
|
3030
2877
|
};
|
|
3031
2878
|
}
|
|
3032
2879
|
|
|
3033
|
-
// node_modules/.pnpm/mcporter@0.13.
|
|
2880
|
+
// node_modules/.pnpm/mcporter@0.13.6/node_modules/mcporter/dist/tool-filters.js
|
|
3034
2881
|
function validateToolFilters(name, filter) {
|
|
3035
2882
|
if (filter.allowedTools !== void 0 && filter.blockedTools !== void 0) {
|
|
3036
2883
|
throw new Error(`Server '${name}' cannot specify both allowedTools and blockedTools.`);
|
|
@@ -3052,7 +2899,7 @@ function filterTools(tools, filter) {
|
|
|
3052
2899
|
return tools.filter((tool) => isToolAllowed(tool.name, filter));
|
|
3053
2900
|
}
|
|
3054
2901
|
|
|
3055
|
-
// node_modules/.pnpm/mcporter@0.13.
|
|
2902
|
+
// node_modules/.pnpm/mcporter@0.13.6/node_modules/mcporter/dist/runtime.js
|
|
3056
2903
|
var PACKAGE_NAME = "mcporter";
|
|
3057
2904
|
var OAUTH_CODE_TIMEOUT_MS = resolveOAuthTimeoutFromEnv();
|
|
3058
2905
|
var MAX_RESOURCE_LIST_PAGES = 100;
|