mcp-remote 0.1.24 → 0.1.25
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/{chunk-PXT7ZCDC.js → chunk-RUKVRRRN.js} +127 -151
- package/dist/client.js +1 -1
- package/dist/proxy.js +1 -1
- package/package.json +1 -1
|
@@ -11872,7 +11872,7 @@ var Client = class extends Protocol {
|
|
|
11872
11872
|
};
|
|
11873
11873
|
|
|
11874
11874
|
// package.json
|
|
11875
|
-
var version = "0.1.
|
|
11875
|
+
var version = "0.1.25";
|
|
11876
11876
|
|
|
11877
11877
|
// node_modules/.pnpm/pkce-challenge@5.0.0/node_modules/pkce-challenge/dist/index.node.js
|
|
11878
11878
|
var crypto;
|
|
@@ -13675,9 +13675,7 @@ function debugLog(message, ...args) {
|
|
|
13675
13675
|
}
|
|
13676
13676
|
function log(str, ...rest) {
|
|
13677
13677
|
console.error(`[${pid}] ${str}`, ...rest);
|
|
13678
|
-
|
|
13679
|
-
debugLog(str, ...rest);
|
|
13680
|
-
}
|
|
13678
|
+
debugLog(str, ...rest);
|
|
13681
13679
|
}
|
|
13682
13680
|
var MESSAGE_BLOCKED = Symbol("MessageBlocked");
|
|
13683
13681
|
var isMessageBlocked = (value) => value === MESSAGE_BLOCKED;
|
|
@@ -13749,34 +13747,28 @@ function mcpProxy({
|
|
|
13749
13747
|
return;
|
|
13750
13748
|
}
|
|
13751
13749
|
log("[Local\u2192Remote]", message.method || message.id);
|
|
13752
|
-
|
|
13753
|
-
|
|
13754
|
-
|
|
13755
|
-
|
|
13756
|
-
|
|
13757
|
-
});
|
|
13758
|
-
}
|
|
13750
|
+
debugLog("Local \u2192 Remote message", {
|
|
13751
|
+
method: message.method,
|
|
13752
|
+
id: message.id,
|
|
13753
|
+
params: message.params ? JSON.stringify(message.params).substring(0, 500) : void 0
|
|
13754
|
+
});
|
|
13759
13755
|
if (message.method === "initialize") {
|
|
13760
13756
|
const { clientInfo } = message.params;
|
|
13761
13757
|
if (clientInfo) clientInfo.name = `${clientInfo.name} (via mcp-remote ${version})`;
|
|
13762
13758
|
log(JSON.stringify(message, null, 2));
|
|
13763
|
-
|
|
13764
|
-
debugLog("Initialize message with modified client info", { clientInfo });
|
|
13765
|
-
}
|
|
13759
|
+
debugLog("Initialize message with modified client info", { clientInfo });
|
|
13766
13760
|
}
|
|
13767
13761
|
transportToServer.send(message).catch(onServerError);
|
|
13768
13762
|
};
|
|
13769
13763
|
transportToServer.onmessage = (_message) => {
|
|
13770
13764
|
const message = messageTransformer.interceptResponse(_message);
|
|
13771
13765
|
log("[Remote\u2192Local]", message.method || message.id);
|
|
13772
|
-
|
|
13773
|
-
|
|
13774
|
-
|
|
13775
|
-
|
|
13776
|
-
|
|
13777
|
-
|
|
13778
|
-
});
|
|
13779
|
-
}
|
|
13766
|
+
debugLog("Remote \u2192 Local message", {
|
|
13767
|
+
method: message.method,
|
|
13768
|
+
id: message.id,
|
|
13769
|
+
result: message.result ? "result-present" : void 0,
|
|
13770
|
+
error: message.error
|
|
13771
|
+
});
|
|
13780
13772
|
transportToClient.send(message).catch(onClientError);
|
|
13781
13773
|
};
|
|
13782
13774
|
transportToClient.onclose = () => {
|
|
@@ -13784,7 +13776,7 @@ function mcpProxy({
|
|
|
13784
13776
|
return;
|
|
13785
13777
|
}
|
|
13786
13778
|
transportToClientClosed = true;
|
|
13787
|
-
|
|
13779
|
+
debugLog("Local transport closed, closing remote transport");
|
|
13788
13780
|
transportToServer.close().catch(onServerError);
|
|
13789
13781
|
};
|
|
13790
13782
|
transportToServer.onclose = () => {
|
|
@@ -13792,18 +13784,18 @@ function mcpProxy({
|
|
|
13792
13784
|
return;
|
|
13793
13785
|
}
|
|
13794
13786
|
transportToServerClosed = true;
|
|
13795
|
-
|
|
13787
|
+
debugLog("Remote transport closed, closing local transport");
|
|
13796
13788
|
transportToClient.close().catch(onClientError);
|
|
13797
13789
|
};
|
|
13798
13790
|
transportToClient.onerror = onClientError;
|
|
13799
13791
|
transportToServer.onerror = onServerError;
|
|
13800
13792
|
function onClientError(error) {
|
|
13801
13793
|
log("Error from local client:", error);
|
|
13802
|
-
|
|
13794
|
+
debugLog("Error from local client", { stack: error.stack });
|
|
13803
13795
|
}
|
|
13804
13796
|
function onServerError(error) {
|
|
13805
13797
|
log("Error from remote server:", error);
|
|
13806
|
-
|
|
13798
|
+
debugLog("Error from remote server", { stack: error.stack });
|
|
13807
13799
|
}
|
|
13808
13800
|
}
|
|
13809
13801
|
async function connectToRemoteServer(client, serverUrl, authProvider, headers, authInitializer, transportStrategy = "http-first", recursionReasons = /* @__PURE__ */ new Set()) {
|
|
@@ -13836,15 +13828,15 @@ async function connectToRemoteServer(client, serverUrl, authProvider, headers, a
|
|
|
13836
13828
|
requestInit: { headers }
|
|
13837
13829
|
});
|
|
13838
13830
|
try {
|
|
13839
|
-
|
|
13831
|
+
debugLog("Attempting to connect to remote server", { sseTransport });
|
|
13840
13832
|
if (client) {
|
|
13841
|
-
|
|
13833
|
+
debugLog("Connecting client to transport");
|
|
13842
13834
|
await client.connect(transport);
|
|
13843
13835
|
} else {
|
|
13844
|
-
|
|
13836
|
+
debugLog("Starting transport directly");
|
|
13845
13837
|
await transport.start();
|
|
13846
13838
|
if (!sseTransport) {
|
|
13847
|
-
|
|
13839
|
+
debugLog("Creating test transport for HTTP-only connection test");
|
|
13848
13840
|
const testTransport = new StreamableHTTPClientTransport(url, { authProvider, requestInit: { headers } });
|
|
13849
13841
|
const testClient = new Client({ name: "mcp-remote-fallback-test", version: "0.0.0" }, { capabilities: {} });
|
|
13850
13842
|
await testClient.connect(testTransport);
|
|
@@ -13873,57 +13865,52 @@ async function connectToRemoteServer(client, serverUrl, authProvider, headers, a
|
|
|
13873
13865
|
);
|
|
13874
13866
|
} else if (error instanceof UnauthorizedError || error instanceof Error && error.message.includes("Unauthorized")) {
|
|
13875
13867
|
log("Authentication required. Initializing auth...");
|
|
13876
|
-
|
|
13877
|
-
|
|
13878
|
-
|
|
13879
|
-
|
|
13880
|
-
|
|
13881
|
-
|
|
13882
|
-
}
|
|
13883
|
-
if (DEBUG) debugLog("Calling authInitializer to start auth flow");
|
|
13868
|
+
debugLog("Authentication error detected", {
|
|
13869
|
+
errorCode: error instanceof OAuthError ? error.errorCode : void 0,
|
|
13870
|
+
errorMessage: error.message,
|
|
13871
|
+
stack: error.stack
|
|
13872
|
+
});
|
|
13873
|
+
debugLog("Calling authInitializer to start auth flow");
|
|
13884
13874
|
const { waitForAuthCode, skipBrowserAuth } = await authInitializer();
|
|
13885
13875
|
if (skipBrowserAuth) {
|
|
13886
13876
|
log("Authentication required but skipping browser auth - using shared auth");
|
|
13887
13877
|
} else {
|
|
13888
13878
|
log("Authentication required. Waiting for authorization...");
|
|
13889
13879
|
}
|
|
13890
|
-
|
|
13880
|
+
debugLog("Waiting for auth code from callback server");
|
|
13891
13881
|
const code = await waitForAuthCode();
|
|
13892
|
-
|
|
13882
|
+
debugLog("Received auth code from callback server");
|
|
13893
13883
|
try {
|
|
13894
13884
|
log("Completing authorization...");
|
|
13895
13885
|
await transport.finishAuth(code);
|
|
13896
|
-
|
|
13886
|
+
debugLog("Authorization completed successfully");
|
|
13897
13887
|
if (recursionReasons.has(REASON_AUTH_NEEDED)) {
|
|
13898
13888
|
const errorMessage = `Already attempted reconnection for reason: ${REASON_AUTH_NEEDED}. Giving up.`;
|
|
13899
13889
|
log(errorMessage);
|
|
13900
|
-
|
|
13901
|
-
|
|
13902
|
-
|
|
13903
|
-
});
|
|
13890
|
+
debugLog("Already attempted auth reconnection, giving up", {
|
|
13891
|
+
recursionReasons: Array.from(recursionReasons)
|
|
13892
|
+
});
|
|
13904
13893
|
throw new Error(errorMessage);
|
|
13905
13894
|
}
|
|
13906
13895
|
recursionReasons.add(REASON_AUTH_NEEDED);
|
|
13907
13896
|
log(`Recursively reconnecting for reason: ${REASON_AUTH_NEEDED}`);
|
|
13908
|
-
|
|
13897
|
+
debugLog("Recursively reconnecting after auth", { recursionReasons: Array.from(recursionReasons) });
|
|
13909
13898
|
return connectToRemoteServer(client, serverUrl, authProvider, headers, authInitializer, transportStrategy, recursionReasons);
|
|
13910
13899
|
} catch (authError) {
|
|
13911
13900
|
log("Authorization error:", authError);
|
|
13912
|
-
|
|
13913
|
-
|
|
13914
|
-
|
|
13915
|
-
|
|
13916
|
-
});
|
|
13901
|
+
debugLog("Authorization error during finishAuth", {
|
|
13902
|
+
errorMessage: authError.message,
|
|
13903
|
+
stack: authError.stack
|
|
13904
|
+
});
|
|
13917
13905
|
throw authError;
|
|
13918
13906
|
}
|
|
13919
13907
|
} else {
|
|
13920
13908
|
log("Connection error:", error);
|
|
13921
|
-
|
|
13922
|
-
|
|
13923
|
-
|
|
13924
|
-
|
|
13925
|
-
|
|
13926
|
-
});
|
|
13909
|
+
debugLog("Connection error", {
|
|
13910
|
+
errorMessage: error.message,
|
|
13911
|
+
stack: error.stack,
|
|
13912
|
+
transportType: transport.constructor.name
|
|
13913
|
+
});
|
|
13927
13914
|
throw error;
|
|
13928
13915
|
}
|
|
13929
13916
|
}
|
|
@@ -14145,9 +14132,7 @@ async function parseCommandLineArgs(args, usage) {
|
|
|
14145
14132
|
}
|
|
14146
14133
|
const serverUrlHash = getServerUrlHash(serverUrl);
|
|
14147
14134
|
global.currentServerUrlHash = serverUrlHash;
|
|
14148
|
-
|
|
14149
|
-
debugLog(`Starting mcp-remote with server URL: ${serverUrl}`);
|
|
14150
|
-
}
|
|
14135
|
+
debugLog(`Starting mcp-remote with server URL: ${serverUrl}`);
|
|
14151
14136
|
const defaultPort = calculateDefaultPort(serverUrlHash);
|
|
14152
14137
|
const [existingClientPort, availablePort] = await Promise.all([findExistingClientPort(serverUrlHash), findAvailablePort(defaultPort)]);
|
|
14153
14138
|
let callbackPort;
|
|
@@ -14290,9 +14275,9 @@ var NodeOAuthClientProvider = class {
|
|
|
14290
14275
|
* @returns The client information or undefined
|
|
14291
14276
|
*/
|
|
14292
14277
|
async clientInformation() {
|
|
14293
|
-
|
|
14278
|
+
debugLog("Reading client info");
|
|
14294
14279
|
if (this.staticOAuthClientInfo) {
|
|
14295
|
-
|
|
14280
|
+
debugLog("Returning static client info");
|
|
14296
14281
|
return this.staticOAuthClientInfo;
|
|
14297
14282
|
}
|
|
14298
14283
|
const clientInfo = await readJsonFile(
|
|
@@ -14306,10 +14291,10 @@ var NodeOAuthClientProvider = class {
|
|
|
14306
14291
|
});
|
|
14307
14292
|
if (scopesData?.scopes) {
|
|
14308
14293
|
this._scopes = scopesData.scopes;
|
|
14309
|
-
|
|
14294
|
+
debugLog("Loaded stored scopes from registration", { scopes: this._scopes });
|
|
14310
14295
|
}
|
|
14311
14296
|
}
|
|
14312
|
-
|
|
14297
|
+
debugLog("Client info result:", clientInfo ? "Found" : "Not found");
|
|
14313
14298
|
return clientInfo;
|
|
14314
14299
|
}
|
|
14315
14300
|
/**
|
|
@@ -14329,9 +14314,9 @@ var NodeOAuthClientProvider = class {
|
|
|
14329
14314
|
* @param clientInformation The client information to save
|
|
14330
14315
|
*/
|
|
14331
14316
|
async saveClientInformation(clientInformation) {
|
|
14332
|
-
|
|
14317
|
+
debugLog("Saving client info", { client_id: clientInformation.client_id });
|
|
14333
14318
|
const scopes = this.extractScopesFromRegistration(clientInformation);
|
|
14334
|
-
|
|
14319
|
+
debugLog("Extracted scopes from registration response", { scopes });
|
|
14335
14320
|
this._scopes = scopes;
|
|
14336
14321
|
await writeJsonFile(this.serverUrlHash, "client_info.json", clientInformation);
|
|
14337
14322
|
await writeJsonFile(this.serverUrlHash, "scopes.json", { scopes });
|
|
@@ -14341,56 +14326,50 @@ var NodeOAuthClientProvider = class {
|
|
|
14341
14326
|
* @returns The OAuth tokens or undefined
|
|
14342
14327
|
*/
|
|
14343
14328
|
async tokens() {
|
|
14344
|
-
|
|
14345
|
-
|
|
14346
|
-
debugLog("Token request stack trace:", new Error().stack);
|
|
14347
|
-
}
|
|
14329
|
+
debugLog("Reading OAuth tokens");
|
|
14330
|
+
debugLog("Token request stack trace:", new Error().stack);
|
|
14348
14331
|
const tokens = await readJsonFile(this.serverUrlHash, "tokens.json", OAuthTokensSchema);
|
|
14349
|
-
if (
|
|
14350
|
-
if (tokens) {
|
|
14351
|
-
const timeLeft = tokens.expires_in || 0;
|
|
14352
|
-
if (typeof tokens.expires_in !== "number" || tokens.expires_in < 0) {
|
|
14353
|
-
debugLog("\u26A0\uFE0F WARNING: Invalid expires_in detected while reading tokens \u26A0\uFE0F", {
|
|
14354
|
-
expiresIn: tokens.expires_in,
|
|
14355
|
-
tokenObject: JSON.stringify(tokens),
|
|
14356
|
-
stack: new Error("Invalid expires_in value").stack
|
|
14357
|
-
});
|
|
14358
|
-
}
|
|
14359
|
-
debugLog("Token result:", {
|
|
14360
|
-
found: true,
|
|
14361
|
-
hasAccessToken: !!tokens.access_token,
|
|
14362
|
-
hasRefreshToken: !!tokens.refresh_token,
|
|
14363
|
-
expiresIn: `${timeLeft} seconds`,
|
|
14364
|
-
isExpired: timeLeft <= 0,
|
|
14365
|
-
expiresInValue: tokens.expires_in
|
|
14366
|
-
});
|
|
14367
|
-
} else {
|
|
14368
|
-
debugLog("Token result: Not found");
|
|
14369
|
-
}
|
|
14370
|
-
}
|
|
14371
|
-
return tokens;
|
|
14372
|
-
}
|
|
14373
|
-
/**
|
|
14374
|
-
* Saves OAuth tokens
|
|
14375
|
-
* @param tokens The tokens to save
|
|
14376
|
-
*/
|
|
14377
|
-
async saveTokens(tokens) {
|
|
14378
|
-
if (DEBUG) {
|
|
14332
|
+
if (tokens) {
|
|
14379
14333
|
const timeLeft = tokens.expires_in || 0;
|
|
14380
14334
|
if (typeof tokens.expires_in !== "number" || tokens.expires_in < 0) {
|
|
14381
|
-
debugLog("\u26A0\uFE0F WARNING: Invalid expires_in detected
|
|
14335
|
+
debugLog("\u26A0\uFE0F WARNING: Invalid expires_in detected while reading tokens \u26A0\uFE0F", {
|
|
14382
14336
|
expiresIn: tokens.expires_in,
|
|
14383
14337
|
tokenObject: JSON.stringify(tokens),
|
|
14384
14338
|
stack: new Error("Invalid expires_in value").stack
|
|
14385
14339
|
});
|
|
14386
14340
|
}
|
|
14387
|
-
debugLog("
|
|
14341
|
+
debugLog("Token result:", {
|
|
14342
|
+
found: true,
|
|
14388
14343
|
hasAccessToken: !!tokens.access_token,
|
|
14389
14344
|
hasRefreshToken: !!tokens.refresh_token,
|
|
14390
14345
|
expiresIn: `${timeLeft} seconds`,
|
|
14346
|
+
isExpired: timeLeft <= 0,
|
|
14391
14347
|
expiresInValue: tokens.expires_in
|
|
14392
14348
|
});
|
|
14349
|
+
} else {
|
|
14350
|
+
debugLog("Token result: Not found");
|
|
14351
|
+
}
|
|
14352
|
+
return tokens;
|
|
14353
|
+
}
|
|
14354
|
+
/**
|
|
14355
|
+
* Saves OAuth tokens
|
|
14356
|
+
* @param tokens The tokens to save
|
|
14357
|
+
*/
|
|
14358
|
+
async saveTokens(tokens) {
|
|
14359
|
+
const timeLeft = tokens.expires_in || 0;
|
|
14360
|
+
if (typeof tokens.expires_in !== "number" || tokens.expires_in < 0) {
|
|
14361
|
+
debugLog("\u26A0\uFE0F WARNING: Invalid expires_in detected in tokens \u26A0\uFE0F", {
|
|
14362
|
+
expiresIn: tokens.expires_in,
|
|
14363
|
+
tokenObject: JSON.stringify(tokens),
|
|
14364
|
+
stack: new Error("Invalid expires_in value").stack
|
|
14365
|
+
});
|
|
14393
14366
|
}
|
|
14367
|
+
debugLog("Saving tokens", {
|
|
14368
|
+
hasAccessToken: !!tokens.access_token,
|
|
14369
|
+
hasRefreshToken: !!tokens.refresh_token,
|
|
14370
|
+
expiresIn: `${timeLeft} seconds`,
|
|
14371
|
+
expiresInValue: tokens.expires_in
|
|
14372
|
+
});
|
|
14394
14373
|
await writeJsonFile(this.serverUrlHash, "tokens.json", tokens);
|
|
14395
14374
|
}
|
|
14396
14375
|
/**
|
|
@@ -14403,19 +14382,19 @@ var NodeOAuthClientProvider = class {
|
|
|
14403
14382
|
}
|
|
14404
14383
|
if (this._scopes) {
|
|
14405
14384
|
authorizationUrl.searchParams.set("scope", this._scopes);
|
|
14406
|
-
|
|
14385
|
+
debugLog("Added scope parameter to authorization URL", { scopes: this._scopes });
|
|
14407
14386
|
}
|
|
14408
14387
|
log(`
|
|
14409
14388
|
Please authorize this client by visiting:
|
|
14410
14389
|
${authorizationUrl.toString()}
|
|
14411
14390
|
`);
|
|
14412
|
-
|
|
14391
|
+
debugLog("Redirecting to authorization URL", authorizationUrl.toString());
|
|
14413
14392
|
try {
|
|
14414
14393
|
await open(sanitizeUrl(authorizationUrl.toString()));
|
|
14415
14394
|
log("Browser opened automatically.");
|
|
14416
14395
|
} catch (error) {
|
|
14417
14396
|
log("Could not open browser automatically. Please copy and paste the URL above into your browser.");
|
|
14418
|
-
|
|
14397
|
+
debugLog("Failed to open browser", error);
|
|
14419
14398
|
}
|
|
14420
14399
|
}
|
|
14421
14400
|
/**
|
|
@@ -14423,7 +14402,7 @@ ${authorizationUrl.toString()}
|
|
|
14423
14402
|
* @param codeVerifier The code verifier to save
|
|
14424
14403
|
*/
|
|
14425
14404
|
async saveCodeVerifier(codeVerifier) {
|
|
14426
|
-
|
|
14405
|
+
debugLog("Saving code verifier");
|
|
14427
14406
|
await writeTextFile(this.serverUrlHash, "code_verifier.txt", codeVerifier);
|
|
14428
14407
|
}
|
|
14429
14408
|
/**
|
|
@@ -14431,9 +14410,9 @@ ${authorizationUrl.toString()}
|
|
|
14431
14410
|
* @returns The code verifier
|
|
14432
14411
|
*/
|
|
14433
14412
|
async codeVerifier() {
|
|
14434
|
-
|
|
14413
|
+
debugLog("Reading code verifier");
|
|
14435
14414
|
const verifier = await readTextFile(this.serverUrlHash, "code_verifier.txt", "No code verifier saved for session");
|
|
14436
|
-
|
|
14415
|
+
debugLog("Code verifier found:", !!verifier);
|
|
14437
14416
|
return verifier;
|
|
14438
14417
|
}
|
|
14439
14418
|
/**
|
|
@@ -14441,7 +14420,7 @@ ${authorizationUrl.toString()}
|
|
|
14441
14420
|
* @param scope The scope of credentials to invalidate
|
|
14442
14421
|
*/
|
|
14443
14422
|
async invalidateCredentials(scope) {
|
|
14444
|
-
|
|
14423
|
+
debugLog(`Invalidating credentials: ${scope}`);
|
|
14445
14424
|
switch (scope) {
|
|
14446
14425
|
case "all":
|
|
14447
14426
|
await Promise.all([
|
|
@@ -14450,20 +14429,20 @@ ${authorizationUrl.toString()}
|
|
|
14450
14429
|
deleteConfigFile(this.serverUrlHash, "code_verifier.txt"),
|
|
14451
14430
|
deleteConfigFile(this.serverUrlHash, "scopes.json")
|
|
14452
14431
|
]);
|
|
14453
|
-
|
|
14432
|
+
debugLog("All credentials invalidated");
|
|
14454
14433
|
break;
|
|
14455
14434
|
case "client":
|
|
14456
14435
|
await Promise.all([deleteConfigFile(this.serverUrlHash, "client_info.json"), deleteConfigFile(this.serverUrlHash, "scopes.json")]);
|
|
14457
14436
|
this._scopes = this.options.scopes || "openid email profile";
|
|
14458
|
-
|
|
14437
|
+
debugLog("Client information invalidated");
|
|
14459
14438
|
break;
|
|
14460
14439
|
case "tokens":
|
|
14461
14440
|
await deleteConfigFile(this.serverUrlHash, "tokens.json");
|
|
14462
|
-
|
|
14441
|
+
debugLog("OAuth tokens invalidated");
|
|
14463
14442
|
break;
|
|
14464
14443
|
case "verifier":
|
|
14465
14444
|
await deleteConfigFile(this.serverUrlHash, "code_verifier.txt");
|
|
14466
|
-
|
|
14445
|
+
debugLog("Code verifier invalidated");
|
|
14467
14446
|
break;
|
|
14468
14447
|
default:
|
|
14469
14448
|
throw new Error(`Unknown credential scope: ${scope}`);
|
|
@@ -14477,32 +14456,31 @@ import { unlinkSync } from "fs";
|
|
|
14477
14456
|
async function isPidRunning(pid2) {
|
|
14478
14457
|
try {
|
|
14479
14458
|
process.kill(pid2, 0);
|
|
14480
|
-
|
|
14459
|
+
debugLog(`Process ${pid2} is running`);
|
|
14481
14460
|
return true;
|
|
14482
14461
|
} catch (err) {
|
|
14483
|
-
|
|
14462
|
+
debugLog(`Process ${pid2} is not running`, err);
|
|
14484
14463
|
return false;
|
|
14485
14464
|
}
|
|
14486
14465
|
}
|
|
14487
14466
|
async function isLockValid(lockData) {
|
|
14488
|
-
|
|
14467
|
+
debugLog("Checking if lockfile is valid", lockData);
|
|
14489
14468
|
const MAX_LOCK_AGE = 30 * 60 * 1e3;
|
|
14490
14469
|
if (Date.now() - lockData.timestamp > MAX_LOCK_AGE) {
|
|
14491
14470
|
log("Lockfile is too old");
|
|
14492
|
-
|
|
14493
|
-
|
|
14494
|
-
|
|
14495
|
-
|
|
14496
|
-
});
|
|
14471
|
+
debugLog("Lockfile is too old", {
|
|
14472
|
+
age: Date.now() - lockData.timestamp,
|
|
14473
|
+
maxAge: MAX_LOCK_AGE
|
|
14474
|
+
});
|
|
14497
14475
|
return false;
|
|
14498
14476
|
}
|
|
14499
14477
|
if (!await isPidRunning(lockData.pid)) {
|
|
14500
14478
|
log("Process from lockfile is not running");
|
|
14501
|
-
|
|
14479
|
+
debugLog("Process from lockfile is not running", { pid: lockData.pid });
|
|
14502
14480
|
return false;
|
|
14503
14481
|
}
|
|
14504
14482
|
try {
|
|
14505
|
-
|
|
14483
|
+
debugLog("Checking if endpoint is accessible", { port: lockData.port });
|
|
14506
14484
|
const controller = new AbortController();
|
|
14507
14485
|
const timeout = setTimeout(() => controller.abort(), 1e3);
|
|
14508
14486
|
const response = await fetch(`http://127.0.0.1:${lockData.port}/wait-for-auth?poll=false`, {
|
|
@@ -14510,11 +14488,11 @@ async function isLockValid(lockData) {
|
|
|
14510
14488
|
});
|
|
14511
14489
|
clearTimeout(timeout);
|
|
14512
14490
|
const isValid2 = response.status === 200 || response.status === 202;
|
|
14513
|
-
|
|
14491
|
+
debugLog(`Endpoint check result: ${isValid2 ? "valid" : "invalid"}`, { status: response.status });
|
|
14514
14492
|
return isValid2;
|
|
14515
14493
|
} catch (error) {
|
|
14516
14494
|
log(`Error connecting to auth server: ${error.message}`);
|
|
14517
|
-
|
|
14495
|
+
debugLog("Error connecting to auth server", error);
|
|
14518
14496
|
return false;
|
|
14519
14497
|
}
|
|
14520
14498
|
}
|
|
@@ -14526,29 +14504,29 @@ async function waitForAuthentication(port) {
|
|
|
14526
14504
|
attempts++;
|
|
14527
14505
|
const url = `http://127.0.0.1:${port}/wait-for-auth`;
|
|
14528
14506
|
log(`Querying: ${url}`);
|
|
14529
|
-
|
|
14507
|
+
debugLog(`Poll attempt ${attempts}`);
|
|
14530
14508
|
try {
|
|
14531
14509
|
const response = await fetch(url);
|
|
14532
|
-
|
|
14510
|
+
debugLog(`Poll response status: ${response.status}`);
|
|
14533
14511
|
if (response.status === 200) {
|
|
14534
14512
|
log(`Authentication completed by other instance`);
|
|
14535
14513
|
return true;
|
|
14536
14514
|
} else if (response.status === 202) {
|
|
14537
14515
|
log(`Authentication still in progress`);
|
|
14538
|
-
|
|
14516
|
+
debugLog(`Will retry in 1s`);
|
|
14539
14517
|
await new Promise((resolve) => setTimeout(resolve, 1e3));
|
|
14540
14518
|
} else {
|
|
14541
14519
|
log(`Unexpected response status: ${response.status}`);
|
|
14542
14520
|
return false;
|
|
14543
14521
|
}
|
|
14544
14522
|
} catch (fetchError) {
|
|
14545
|
-
|
|
14523
|
+
debugLog(`Fetch error during poll`, fetchError);
|
|
14546
14524
|
await new Promise((resolve) => setTimeout(resolve, 2e3));
|
|
14547
14525
|
}
|
|
14548
14526
|
}
|
|
14549
14527
|
} catch (error) {
|
|
14550
14528
|
log(`Error waiting for authentication: ${error.message}`);
|
|
14551
|
-
|
|
14529
|
+
debugLog(`Error waiting for authentication`, error);
|
|
14552
14530
|
return false;
|
|
14553
14531
|
}
|
|
14554
14532
|
}
|
|
@@ -14557,37 +14535,35 @@ function createLazyAuthCoordinator(serverUrlHash, callbackPort, events, authTime
|
|
|
14557
14535
|
return {
|
|
14558
14536
|
initializeAuth: async () => {
|
|
14559
14537
|
if (authState) {
|
|
14560
|
-
|
|
14538
|
+
debugLog("Auth already initialized, reusing existing state");
|
|
14561
14539
|
return authState;
|
|
14562
14540
|
}
|
|
14563
14541
|
log("Initializing auth coordination on-demand");
|
|
14564
|
-
|
|
14542
|
+
debugLog("Initializing auth coordination on-demand", { serverUrlHash, callbackPort });
|
|
14565
14543
|
authState = await coordinateAuth(serverUrlHash, callbackPort, events, authTimeoutMs);
|
|
14566
|
-
|
|
14544
|
+
debugLog("Auth coordination completed", { skipBrowserAuth: authState.skipBrowserAuth });
|
|
14567
14545
|
return authState;
|
|
14568
14546
|
}
|
|
14569
14547
|
};
|
|
14570
14548
|
}
|
|
14571
14549
|
async function coordinateAuth(serverUrlHash, callbackPort, events, authTimeoutMs) {
|
|
14572
|
-
|
|
14550
|
+
debugLog("Coordinating authentication", { serverUrlHash, callbackPort });
|
|
14573
14551
|
const lockData = process.platform === "win32" ? null : await checkLockfile(serverUrlHash);
|
|
14574
|
-
if (
|
|
14575
|
-
|
|
14576
|
-
|
|
14577
|
-
|
|
14578
|
-
debugLog("Lockfile check result", { found: !!lockData, lockData });
|
|
14579
|
-
}
|
|
14552
|
+
if (process.platform === "win32") {
|
|
14553
|
+
debugLog("Skipping lockfile check on Windows");
|
|
14554
|
+
} else {
|
|
14555
|
+
debugLog("Lockfile check result", { found: !!lockData, lockData });
|
|
14580
14556
|
}
|
|
14581
14557
|
if (lockData && await isLockValid(lockData)) {
|
|
14582
14558
|
log(`Another instance is handling authentication on port ${lockData.port} (pid: ${lockData.pid})`);
|
|
14583
14559
|
try {
|
|
14584
|
-
|
|
14560
|
+
debugLog("Waiting for authentication from other instance");
|
|
14585
14561
|
const authCompleted = await waitForAuthentication(lockData.port);
|
|
14586
14562
|
if (authCompleted) {
|
|
14587
14563
|
log("Authentication completed by another instance. Using tokens from disk");
|
|
14588
14564
|
const dummyServer = express2().listen(0);
|
|
14589
14565
|
const dummyPort = dummyServer.address().port;
|
|
14590
|
-
|
|
14566
|
+
debugLog("Started dummy server", { port: dummyPort });
|
|
14591
14567
|
const dummyWaitForAuthCode = () => {
|
|
14592
14568
|
log("WARNING: waitForAuthCode called in secondary instance - this is unexpected");
|
|
14593
14569
|
return new Promise(() => {
|
|
@@ -14603,15 +14579,15 @@ async function coordinateAuth(serverUrlHash, callbackPort, events, authTimeoutMs
|
|
|
14603
14579
|
}
|
|
14604
14580
|
} catch (error) {
|
|
14605
14581
|
log(`Error waiting for authentication: ${error}`);
|
|
14606
|
-
|
|
14582
|
+
debugLog("Error waiting for authentication", error);
|
|
14607
14583
|
}
|
|
14608
|
-
|
|
14584
|
+
debugLog("Other instance did not complete auth successfully, deleting lockfile");
|
|
14609
14585
|
await deleteLockfile(serverUrlHash);
|
|
14610
14586
|
} else if (lockData) {
|
|
14611
14587
|
log("Found invalid lockfile, deleting it");
|
|
14612
14588
|
await deleteLockfile(serverUrlHash);
|
|
14613
14589
|
}
|
|
14614
|
-
|
|
14590
|
+
debugLog("Setting up OAuth callback server", { port: callbackPort });
|
|
14615
14591
|
const { server, waitForAuthCode, authCompletedPromise } = setupOAuthCallbackServerWithLongPoll({
|
|
14616
14592
|
port: callbackPort,
|
|
14617
14593
|
path: "/oauth/callback",
|
|
@@ -14620,7 +14596,7 @@ async function coordinateAuth(serverUrlHash, callbackPort, events, authTimeoutMs
|
|
|
14620
14596
|
});
|
|
14621
14597
|
const address = server.address();
|
|
14622
14598
|
const actualPort = address.port;
|
|
14623
|
-
|
|
14599
|
+
debugLog("OAuth callback server running", { port: actualPort });
|
|
14624
14600
|
log(`Creating lockfile for server ${serverUrlHash} with process ${process.pid} on port ${actualPort}`);
|
|
14625
14601
|
await createLockfile(serverUrlHash, process.pid, actualPort);
|
|
14626
14602
|
const cleanupHandler = async () => {
|
|
@@ -14629,23 +14605,23 @@ async function coordinateAuth(serverUrlHash, callbackPort, events, authTimeoutMs
|
|
|
14629
14605
|
await deleteLockfile(serverUrlHash);
|
|
14630
14606
|
} catch (error) {
|
|
14631
14607
|
log(`Error cleaning up lockfile: ${error}`);
|
|
14632
|
-
|
|
14608
|
+
debugLog("Error cleaning up lockfile", error);
|
|
14633
14609
|
}
|
|
14634
14610
|
};
|
|
14635
14611
|
process.once("exit", () => {
|
|
14636
14612
|
try {
|
|
14637
14613
|
const configPath = getConfigFilePath(serverUrlHash, "lock.json");
|
|
14638
14614
|
unlinkSync(configPath);
|
|
14639
|
-
|
|
14615
|
+
debugLog(`Removed lockfile on exit: ${configPath}`);
|
|
14640
14616
|
} catch (error) {
|
|
14641
|
-
|
|
14617
|
+
debugLog(`Error removing lockfile on exit:`, error);
|
|
14642
14618
|
}
|
|
14643
14619
|
});
|
|
14644
14620
|
process.once("SIGINT", async () => {
|
|
14645
|
-
|
|
14621
|
+
debugLog("Received SIGINT signal, cleaning up");
|
|
14646
14622
|
await cleanupHandler();
|
|
14647
14623
|
});
|
|
14648
|
-
|
|
14624
|
+
debugLog("Auth coordination complete, returning primary instance handlers");
|
|
14649
14625
|
return {
|
|
14650
14626
|
server,
|
|
14651
14627
|
waitForAuthCode,
|
package/dist/client.js
CHANGED
package/dist/proxy.js
CHANGED