@mcp-use/client 2.1.0 → 2.1.1-canary.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/index.js CHANGED
@@ -142,6 +142,268 @@ var init_logging = __esm({
142
142
  }
143
143
  });
144
144
 
145
+ // src/auth/popup.ts
146
+ function hasStoredTokens(tokensKey) {
147
+ try {
148
+ return typeof localStorage !== "undefined" && !!localStorage.getItem(tokensKey);
149
+ } catch {
150
+ return false;
151
+ }
152
+ }
153
+ function runAuthPopup({
154
+ popup,
155
+ state,
156
+ tokensKey,
157
+ timeoutMs = 5 * 6e4,
158
+ closePollMs = 1e3,
159
+ closeGraceMs = 2e4,
160
+ expectedOrigin = typeof window !== "undefined" ? window.location.origin : ""
161
+ }) {
162
+ return new Promise((resolve) => {
163
+ let settled = false;
164
+ let closeTimer = null;
165
+ let timeoutTimer = null;
166
+ let graceTimer = null;
167
+ let broadcastChannel = null;
168
+ const cleanup = () => {
169
+ if (closeTimer) {
170
+ clearInterval(closeTimer);
171
+ closeTimer = null;
172
+ }
173
+ if (timeoutTimer) {
174
+ clearTimeout(timeoutTimer);
175
+ timeoutTimer = null;
176
+ }
177
+ if (graceTimer) {
178
+ clearTimeout(graceTimer);
179
+ graceTimer = null;
180
+ }
181
+ if (typeof window !== "undefined") {
182
+ window.removeEventListener("message", messageHandler);
183
+ window.removeEventListener("storage", storageHandler);
184
+ }
185
+ if (broadcastChannel) {
186
+ try {
187
+ broadcastChannel.removeEventListener("message", broadcastHandler);
188
+ broadcastChannel.close();
189
+ } catch {
190
+ }
191
+ broadcastChannel = null;
192
+ }
193
+ };
194
+ const settle = (result) => {
195
+ if (settled) return;
196
+ settled = true;
197
+ cleanup();
198
+ resolve(result);
199
+ };
200
+ const handlePayload = (payload) => {
201
+ if (!payload || payload.type !== MCP_AUTH_CALLBACK_MESSAGE_TYPE) return;
202
+ if (payload.state && state && payload.state !== state) return;
203
+ if (payload.success) {
204
+ settle({ kind: "success" });
205
+ } else {
206
+ settle({
207
+ kind: "error",
208
+ error: payload.error ?? "Authentication failed in callback."
209
+ });
210
+ }
211
+ };
212
+ const messageHandler = (event) => {
213
+ if (expectedOrigin && event.origin !== expectedOrigin) return;
214
+ handlePayload(event.data);
215
+ };
216
+ const broadcastHandler = (event) => {
217
+ handlePayload(event.data);
218
+ };
219
+ const storageHandler = (event) => {
220
+ if (event.key !== tokensKey) return;
221
+ if (event.newValue) settle({ kind: "success" });
222
+ };
223
+ if (typeof window !== "undefined") {
224
+ window.addEventListener("message", messageHandler);
225
+ window.addEventListener("storage", storageHandler);
226
+ }
227
+ if (typeof BroadcastChannel !== "undefined") {
228
+ try {
229
+ broadcastChannel = new BroadcastChannel(MCP_AUTH_BROADCAST_CHANNEL);
230
+ broadcastChannel.addEventListener("message", broadcastHandler);
231
+ } catch {
232
+ broadcastChannel = null;
233
+ }
234
+ }
235
+ if (popup) {
236
+ closeTimer = setInterval(() => {
237
+ if (settled) return;
238
+ let closed = false;
239
+ try {
240
+ closed = popup.closed;
241
+ } catch {
242
+ closed = false;
243
+ }
244
+ if (!closed) return;
245
+ if (closeTimer) {
246
+ clearInterval(closeTimer);
247
+ closeTimer = null;
248
+ }
249
+ if (hasStoredTokens(tokensKey)) {
250
+ settle({ kind: "success" });
251
+ return;
252
+ }
253
+ graceTimer = setTimeout(() => {
254
+ settle(
255
+ hasStoredTokens(tokensKey) ? { kind: "success" } : { kind: "cancelled" }
256
+ );
257
+ }, closeGraceMs);
258
+ }, closePollMs);
259
+ }
260
+ timeoutTimer = setTimeout(() => {
261
+ settle(
262
+ hasStoredTokens(tokensKey) ? { kind: "success" } : { kind: "timeout" }
263
+ );
264
+ }, timeoutMs);
265
+ });
266
+ }
267
+ var MCP_AUTH_BROADCAST_CHANNEL, MCP_AUTH_CALLBACK_MESSAGE_TYPE;
268
+ var init_popup = __esm({
269
+ "src/auth/popup.ts"() {
270
+ "use strict";
271
+ MCP_AUTH_BROADCAST_CHANNEL = "mcp_auth_callback";
272
+ MCP_AUTH_CALLBACK_MESSAGE_TYPE = "mcp_auth_callback";
273
+ }
274
+ });
275
+
276
+ // src/auth/flow.ts
277
+ import {
278
+ auth,
279
+ InsufficientScopeError,
280
+ UnauthorizedError
281
+ } from "@modelcontextprotocol/client";
282
+ function isUnauthorized(err, depth = 0) {
283
+ if (!err || depth > 5) return false;
284
+ if (err instanceof UnauthorizedError) return true;
285
+ if (err instanceof Error) {
286
+ const code = err.code;
287
+ if (code === 401) return true;
288
+ if (err.name === "UnauthorizedError") return true;
289
+ const message = err.message ?? "";
290
+ if (message.includes("401") || message.includes("Unauthorized")) {
291
+ return true;
292
+ }
293
+ if (err.cause && isUnauthorized(err.cause, depth + 1)) return true;
294
+ const data = err.data;
295
+ if (data?.cause && isUnauthorized(data.cause, depth + 1)) return true;
296
+ }
297
+ return false;
298
+ }
299
+ function isOAuthInteractionRequired(err, depth = 0) {
300
+ if (!err || depth > 5) return false;
301
+ if (err instanceof InsufficientScopeError || err instanceof UnauthorizedError) {
302
+ return true;
303
+ }
304
+ if (err instanceof Error) {
305
+ if (err.name === "InsufficientScopeError" || err.name === "UnauthorizedError") {
306
+ return true;
307
+ }
308
+ if (err.cause && isOAuthInteractionRequired(err.cause, depth + 1)) {
309
+ return true;
310
+ }
311
+ const data = err.data;
312
+ if (data?.cause && isOAuthInteractionRequired(data.cause, depth + 1)) {
313
+ return true;
314
+ }
315
+ }
316
+ return false;
317
+ }
318
+ async function completeOAuthFlow(provider, serverUrl, options = {}) {
319
+ const flowProvider = provider;
320
+ const timeoutMs = options.timeoutMs ?? DEFAULT_AUTH_TIMEOUT_MS;
321
+ const fetchFn = options.fetchFn ?? flowProvider.getProxyFetch?.() ?? void 0;
322
+ if (!flowProvider.hasPendingFlow) {
323
+ const result = await auth(provider, { serverUrl, fetchFn });
324
+ if (result === "AUTHORIZED") return;
325
+ if (result !== "REDIRECT") {
326
+ throw new Error(`Unexpected OAuth auth() result: ${result}`);
327
+ }
328
+ }
329
+ if (flowProvider.preventAutoAuth === true && typeof flowProvider.startAuthorization === "function") {
330
+ flowProvider.startAuthorization();
331
+ }
332
+ if (typeof flowProvider.getAuthorizationResponse === "function" || typeof flowProvider.getAuthorizationCode === "function") {
333
+ const response = typeof flowProvider.getAuthorizationResponse === "function" ? await flowProvider.getAuthorizationResponse() : { code: await flowProvider.getAuthorizationCode() };
334
+ if (options.finishAuthorization) {
335
+ await options.finishAuthorization(response.code, response.iss);
336
+ } else {
337
+ await auth(provider, {
338
+ serverUrl,
339
+ authorizationCode: response.code,
340
+ ...response.iss !== void 0 ? { iss: response.iss } : {},
341
+ fetchFn
342
+ });
343
+ }
344
+ return;
345
+ }
346
+ await waitForBrowserAuthComplete(flowProvider, timeoutMs);
347
+ }
348
+ async function waitForBrowserAuthComplete(provider, timeoutMs) {
349
+ if (typeof window === "undefined") {
350
+ throw new Error(
351
+ "OAuth redirect requires a browser environment or a provider with getAuthorizationCode()"
352
+ );
353
+ }
354
+ if (provider.useRedirectFlow) {
355
+ await new Promise(() => {
356
+ });
357
+ return;
358
+ }
359
+ const tokensKey = provider.getKey?.("tokens");
360
+ if (!tokensKey) {
361
+ throw new Error(
362
+ "Browser OAuth provider must expose getKey() for token storage"
363
+ );
364
+ }
365
+ let state = null;
366
+ const authUrl = provider.getLastAttemptedAuthUrl?.();
367
+ if (authUrl) {
368
+ try {
369
+ state = new URL(authUrl).searchParams.get("state");
370
+ } catch {
371
+ }
372
+ }
373
+ try {
374
+ const result = await runAuthPopup({
375
+ popup: null,
376
+ state,
377
+ tokensKey,
378
+ timeoutMs
379
+ });
380
+ switch (result.kind) {
381
+ case "success":
382
+ return;
383
+ case "cancelled":
384
+ throw new Error("OAuth authentication was cancelled.");
385
+ case "timeout":
386
+ throw new Error(
387
+ `OAuth callback not received within ${timeoutMs}ms. Ensure /oauth/callback calls onMcpAuthorization().`
388
+ );
389
+ case "error":
390
+ throw new Error(result.error);
391
+ default:
392
+ throw new Error("Unexpected OAuth popup result");
393
+ }
394
+ } finally {
395
+ provider.markFlowComplete?.();
396
+ }
397
+ }
398
+ var DEFAULT_AUTH_TIMEOUT_MS;
399
+ var init_flow = __esm({
400
+ "src/auth/flow.ts"() {
401
+ "use strict";
402
+ init_popup();
403
+ DEFAULT_AUTH_TIMEOUT_MS = 5 * 6e4;
404
+ }
405
+ });
406
+
145
407
  // src/utils/json-schema-validator.ts
146
408
  import {
147
409
  CfWorkerJsonSchemaValidator
@@ -190,6 +452,7 @@ var init_base = __esm({
190
452
  "src/transport/base.ts"() {
191
453
  "use strict";
192
454
  init_logging();
455
+ init_flow();
193
456
  init_connector_telemetry();
194
457
  passthroughResultSchema = {
195
458
  "~standard": {
@@ -204,6 +467,7 @@ var init_base = __esm({
204
467
  toolsCache = null;
205
468
  capabilitiesCache = null;
206
469
  serverInfoCache = null;
470
+ authorizationCache;
207
471
  connected = false;
208
472
  opts;
209
473
  notificationHandlers = [];
@@ -467,6 +731,21 @@ var init_base = __esm({
467
731
  "setupElicitationHandler: Elicitation handler registered successfully"
468
732
  );
469
733
  }
734
+ /**
735
+ * Run one logical MCP operation. HTTP connectors override this host seam to
736
+ * finish an SDK-started interactive OAuth flow and retry exactly once.
737
+ */
738
+ async executeRequest(operation) {
739
+ return operation();
740
+ }
741
+ /** OAuth state discovered for the active connection, when available. */
742
+ get authorization() {
743
+ return this.authorizationCache;
744
+ }
745
+ /** Start optional OAuth for a connected mixed-auth server. */
746
+ async authenticate() {
747
+ throw new Error("This connector does not support interactive OAuth");
748
+ }
470
749
  /**
471
750
  * Disconnects the SDK client and releases transport resources.
472
751
  *
@@ -514,13 +793,13 @@ var init_base = __esm({
514
793
  icons: serverInfo.icons
515
794
  } : null;
516
795
  try {
517
- const listToolsRes = await this.client.listTools(
518
- void 0,
519
- defaultRequestOptions
796
+ const listToolsRes = await this.executeRequest(
797
+ () => this.client.listTools(void 0, defaultRequestOptions)
520
798
  );
521
799
  this.toolsCache = listToolsRes.tools ?? [];
522
800
  logger.debug(`Fetched ${this.toolsCache.length} tools from server`);
523
801
  } catch (err) {
802
+ if (isOAuthInteractionRequired(err)) throw err;
524
803
  const error = err;
525
804
  if (error.code === -32601) {
526
805
  logger.debug("Server does not implement tools/list, assuming no tools");
@@ -594,9 +873,8 @@ var init_base = __esm({
594
873
  const progressHandler = enhancedOptions?.onprogress;
595
874
  if (progressHandler) this.activeProgressHandlers.add(progressHandler);
596
875
  try {
597
- const res = await this.client.callTool(
598
- { name, arguments: args },
599
- enhancedOptions
876
+ const res = await this.executeRequest(
877
+ () => this.client.callTool({ name, arguments: args }, enhancedOptions)
600
878
  );
601
879
  logger.debug(`Tool '${name}' returned`, res);
602
880
  return res;
@@ -616,7 +894,9 @@ var init_base = __esm({
616
894
  throw new Error("MCP client is not connected");
617
895
  }
618
896
  logger.debug("[listTools] Fetching fresh tools from server...");
619
- const result = await this.client.listTools(void 0, options);
897
+ const result = await this.executeRequest(
898
+ () => this.client.listTools(void 0, options)
899
+ );
620
900
  const tools = result.tools ? [...result.tools] : [];
621
901
  logger.debug(
622
902
  `[listTools] Returned ${tools.length} tools:`,
@@ -636,7 +916,9 @@ var init_base = __esm({
636
916
  throw new Error("MCP client is not connected");
637
917
  }
638
918
  logger.debug("Listing resources", cursor ? `with cursor: ${cursor}` : "");
639
- return await this.client.listResources({ cursor }, options);
919
+ return await this.executeRequest(
920
+ () => this.client.listResources({ cursor }, options)
921
+ );
640
922
  }
641
923
  /**
642
924
  * List all resources from the server, automatically handling pagination
@@ -654,14 +936,16 @@ var init_base = __esm({
654
936
  }
655
937
  try {
656
938
  logger.debug("Listing all resources (with auto-pagination)");
657
- const allResources = [];
658
- let cursor = void 0;
659
- do {
660
- const result = await this.client.listResources({ cursor }, options);
661
- allResources.push(...result.resources || []);
662
- cursor = result.nextCursor;
663
- } while (cursor);
664
- return { resources: allResources };
939
+ return await this.executeRequest(async () => {
940
+ const allResources = [];
941
+ let cursor = void 0;
942
+ do {
943
+ const result = await this.client.listResources({ cursor }, options);
944
+ allResources.push(...result.resources || []);
945
+ cursor = result.nextCursor;
946
+ } while (cursor);
947
+ return { resources: allResources };
948
+ });
665
949
  } catch (err) {
666
950
  const error = err;
667
951
  if (error.code === -32601) {
@@ -682,7 +966,9 @@ var init_base = __esm({
682
966
  throw new Error("MCP client is not connected");
683
967
  }
684
968
  logger.debug("Listing resource templates");
685
- return await this.client.listResourceTemplates(void 0, options);
969
+ return await this.executeRequest(
970
+ () => this.client.listResourceTemplates(void 0, options)
971
+ );
686
972
  }
687
973
  /**
688
974
  * Request completion suggestions for a prompt or resource template argument
@@ -696,7 +982,9 @@ var init_base = __esm({
696
982
  throw new Error("MCP client is not connected");
697
983
  }
698
984
  logger.debug("[complete] Requesting completions for:", params.ref);
699
- const result = await this.client.complete(params, options);
985
+ const result = await this.executeRequest(
986
+ () => this.client.complete(params, options)
987
+ );
700
988
  logger.debug(
701
989
  `[complete] Received ${result.completion.values.length} suggestions`
702
990
  );
@@ -714,7 +1002,9 @@ var init_base = __esm({
714
1002
  throw new Error("MCP client is not connected");
715
1003
  }
716
1004
  logger.debug(`Reading resource ${uri}`);
717
- const res = await this.client.readResource({ uri }, options);
1005
+ const res = await this.executeRequest(
1006
+ () => this.client.readResource({ uri }, options)
1007
+ );
718
1008
  return res;
719
1009
  }
720
1010
  /**
@@ -728,7 +1018,9 @@ var init_base = __esm({
728
1018
  throw new Error("MCP client is not connected");
729
1019
  }
730
1020
  logger.debug(`Subscribing to resource: ${uri}`);
731
- return await this.client.subscribeResource({ uri }, options);
1021
+ return await this.executeRequest(
1022
+ () => this.client.subscribeResource({ uri }, options)
1023
+ );
732
1024
  }
733
1025
  /**
734
1026
  * Unsubscribe from resource updates
@@ -741,7 +1033,9 @@ var init_base = __esm({
741
1033
  throw new Error("MCP client is not connected");
742
1034
  }
743
1035
  logger.debug(`Unsubscribing from resource: ${uri}`);
744
- return await this.client.unsubscribeResource({ uri }, options);
1036
+ return await this.executeRequest(
1037
+ () => this.client.unsubscribeResource({ uri }, options)
1038
+ );
745
1039
  }
746
1040
  /**
747
1041
  * Lists prompts exposed by the server.
@@ -758,7 +1052,7 @@ var init_base = __esm({
758
1052
  }
759
1053
  try {
760
1054
  logger.debug("Listing prompts");
761
- return await this.client.listPrompts();
1055
+ return await this.executeRequest(() => this.client.listPrompts());
762
1056
  } catch (err) {
763
1057
  const error = err;
764
1058
  if (error.code === -32601) {
@@ -780,7 +1074,9 @@ var init_base = __esm({
780
1074
  throw new Error("MCP client is not connected");
781
1075
  }
782
1076
  logger.debug(`Getting prompt ${name}`);
783
- return await this.client.getPrompt({ name, arguments: args });
1077
+ return await this.executeRequest(
1078
+ () => this.client.getPrompt({ name, arguments: args })
1079
+ );
784
1080
  }
785
1081
  /**
786
1082
  * Sends a raw, potentially non-standard request through the SDK client.
@@ -795,10 +1091,12 @@ var init_base = __esm({
795
1091
  throw new Error("MCP client is not connected");
796
1092
  }
797
1093
  logger.debug(`Sending raw request '${method}' with params`, params);
798
- return await this.client.request(
799
- { method, params: params ?? {} },
800
- passthroughResultSchema,
801
- options
1094
+ return await this.executeRequest(
1095
+ () => this.client.request(
1096
+ { method, params: params ?? {} },
1097
+ passthroughResultSchema,
1098
+ options
1099
+ )
802
1100
  );
803
1101
  }
804
1102
  /**
@@ -831,6 +1129,7 @@ var init_base = __esm({
831
1129
  }
832
1130
  }
833
1131
  this.toolsCache = null;
1132
+ this.authorizationCache = void 0;
834
1133
  if (issues.length) {
835
1134
  logger.warn(`Resource cleanup finished with ${issues.length} issue(s)`);
836
1135
  }
@@ -1219,7 +1518,7 @@ init_connector_telemetry();
1219
1518
  init_logging();
1220
1519
 
1221
1520
  // src/utils/version.ts
1222
- var VERSION = "2.1.0";
1521
+ var VERSION = "2.1.1-canary.0";
1223
1522
  function getPackageVersion() {
1224
1523
  return VERSION;
1225
1524
  }
@@ -1617,397 +1916,174 @@ var Telemetry = class _Telemetry {
1617
1916
  };
1618
1917
  const p = capturePostHog({
1619
1918
  host: HOST,
1620
- apiKey: PROJECT_API_KEY,
1621
- event: event.name,
1622
- distinctId: currentUserId,
1623
- properties
1624
- });
1625
- this._pending.add(p);
1626
- void p.finally(() => this._pending.delete(p));
1627
- }
1628
- async trackAgentExecution(data) {
1629
- if (!this.isEnabled) return;
1630
- await this.capture(new MCPAgentExecutionEvent(data));
1631
- }
1632
- async trackMCPClientInit(data) {
1633
- if (!this.isEnabled) return;
1634
- await this.capture(new MCPClientInitEvent(data));
1635
- }
1636
- async trackConnectorInit(data) {
1637
- if (!this.isEnabled) return;
1638
- await this.capture(new ConnectorInitEvent(data));
1639
- }
1640
- async trackClientAddServer(serverName, serverConfig) {
1641
- if (!this.isEnabled) return;
1642
- await this.capture(new ClientAddServerEvent({ serverName, serverConfig }));
1643
- }
1644
- async trackClientRemoveServer(serverName) {
1645
- if (!this.isEnabled) return;
1646
- await this.capture(new ClientRemoveServerEvent({ serverName }));
1647
- }
1648
- async trackUseMcpConnection(data) {
1649
- if (!this.isEnabled) return;
1650
- await this.capture({
1651
- name: "usemcp_connection",
1652
- properties: {
1653
- url_domain: new URL(data.url).hostname,
1654
- transport_type: data.transportType,
1655
- success: data.success,
1656
- error_type: data.errorType ?? null,
1657
- connection_time_ms: data.connectionTimeMs ?? null,
1658
- has_oauth: data.hasOAuth,
1659
- has_sampling: data.hasSampling,
1660
- has_elicitation: data.hasElicitation
1661
- }
1662
- });
1663
- }
1664
- async trackUseMcpToolCall(data) {
1665
- if (!this.isEnabled) return;
1666
- await this.capture({
1667
- name: "usemcp_tool_call",
1668
- properties: {
1669
- tool_name: data.toolName,
1670
- success: data.success,
1671
- error_type: data.errorType ?? null,
1672
- execution_time_ms: data.executionTimeMs ?? null
1673
- }
1674
- });
1675
- }
1676
- async trackUseMcpResourceRead(data) {
1677
- if (!this.isEnabled) return;
1678
- await this.capture({
1679
- name: "usemcp_resource_read",
1680
- properties: {
1681
- resource_uri_scheme: data.resourceUri.split(":")[0],
1682
- success: data.success,
1683
- error_type: data.errorType ?? null
1684
- }
1685
- });
1686
- }
1687
- identify(userId, properties) {
1688
- this._currUserId = userId;
1689
- this._storage?.setUserId(userId);
1690
- if (this._telemetryEnabled) {
1691
- void capturePostHog({
1692
- host: HOST,
1693
- apiKey: PROJECT_API_KEY,
1694
- event: "$identify",
1695
- distinctId: userId,
1696
- properties: { $set: properties ?? {} }
1697
- });
1698
- }
1699
- }
1700
- reset() {
1701
- this._currUserId = null;
1702
- }
1703
- flush() {
1704
- void Promise.allSettled([...this._pending]);
1705
- }
1706
- async shutdown() {
1707
- try {
1708
- await Promise.allSettled([...this._pending]);
1709
- logger.debug("Telemetry fetch captures flushed");
1710
- } catch (e) {
1711
- logger.debug(`Error flushing telemetry captures: ${e}`);
1712
- }
1713
- }
1714
- };
1715
- var Tel = Telemetry;
1716
- function setTelemetrySource(source) {
1717
- Tel.getInstance().setSource(source);
1718
- }
1719
- function setProductVersion(version) {
1720
- Tel.getInstance().setProductVersion(version);
1721
- }
1722
-
1723
- // src/telemetry/telemetry-node.ts
1724
- function getCacheHome(os, path2) {
1725
- const envVar = process.env.XDG_CACHE_HOME;
1726
- if (envVar && path2.isAbsolute(envVar)) {
1727
- return envVar;
1728
- }
1729
- const homeDir = os.homedir();
1730
- if (process.platform === "win32") {
1731
- const appdata = process.env.LOCALAPPDATA || process.env.APPDATA;
1732
- if (appdata) return appdata;
1733
- return path2.join(homeDir, "AppData", "Local");
1734
- }
1735
- if (process.platform === "darwin") {
1736
- return path2.join(homeDir, "Library", "Caches");
1737
- }
1738
- return path2.join(homeDir, ".cache");
1739
- }
1740
- function createFsStorage() {
1741
- let fs2;
1742
- let os;
1743
- let path2;
1744
- try {
1745
- fs2 = __require("fs");
1746
- os = __require("os");
1747
- path2 = __require("path");
1748
- } catch {
1749
- return {
1750
- getUserId: () => null,
1751
- setUserId: () => void 0
1752
- };
1753
- }
1754
- const cacheHome = getCacheHome(os, path2);
1755
- const userIdPath = path2.join(cacheHome, "mcp_use_3", "telemetry_user_id");
1756
- return {
1757
- getUserId() {
1758
- try {
1759
- if (!fs2.existsSync(userIdPath)) return null;
1760
- return fs2.readFileSync(userIdPath, "utf-8").trim() || null;
1761
- } catch {
1762
- return null;
1763
- }
1764
- },
1765
- setUserId(id) {
1766
- try {
1767
- fs2.mkdirSync(path2.dirname(userIdPath), { recursive: true });
1768
- fs2.writeFileSync(userIdPath, id);
1769
- } catch {
1770
- }
1771
- }
1772
- };
1773
- }
1774
- configureTelemetryStorage(createFsStorage());
1775
-
1776
- // src/telemetry/configure-node.ts
1777
- setClientTelemetryTracker({
1778
- addServer: (name, config) => Telemetry.getInstance().trackClientAddServer(name, config).catch(() => void 0),
1779
- removeServer: (name) => Telemetry.getInstance().trackClientRemoveServer(name).catch(() => void 0)
1780
- });
1781
- setConnectorTelemetryTracker(
1782
- (data) => Telemetry.getInstance().trackConnectorInit(data).catch(() => void 0)
1783
- );
1784
-
1785
- // src/index.ts
1786
- import { auth as auth2, UnauthorizedError as UnauthorizedError3 } from "@modelcontextprotocol/client";
1787
-
1788
- // src/auth/flow.ts
1789
- import {
1790
- auth,
1791
- UnauthorizedError
1792
- } from "@modelcontextprotocol/client";
1793
-
1794
- // src/auth/popup.ts
1795
- var MCP_AUTH_BROADCAST_CHANNEL = "mcp_auth_callback";
1796
- var MCP_AUTH_CALLBACK_MESSAGE_TYPE = "mcp_auth_callback";
1797
- function hasStoredTokens(tokensKey) {
1798
- try {
1799
- return typeof localStorage !== "undefined" && !!localStorage.getItem(tokensKey);
1800
- } catch {
1801
- return false;
1802
- }
1803
- }
1804
- function runAuthPopup({
1805
- popup,
1806
- state,
1807
- tokensKey,
1808
- timeoutMs = 5 * 6e4,
1809
- closePollMs = 1e3,
1810
- closeGraceMs = 2e4,
1811
- expectedOrigin = typeof window !== "undefined" ? window.location.origin : ""
1812
- }) {
1813
- return new Promise((resolve) => {
1814
- let settled = false;
1815
- let closeTimer = null;
1816
- let timeoutTimer = null;
1817
- let graceTimer = null;
1818
- let broadcastChannel = null;
1819
- const cleanup = () => {
1820
- if (closeTimer) {
1821
- clearInterval(closeTimer);
1822
- closeTimer = null;
1823
- }
1824
- if (timeoutTimer) {
1825
- clearTimeout(timeoutTimer);
1826
- timeoutTimer = null;
1827
- }
1828
- if (graceTimer) {
1829
- clearTimeout(graceTimer);
1830
- graceTimer = null;
1831
- }
1832
- if (typeof window !== "undefined") {
1833
- window.removeEventListener("message", messageHandler);
1834
- window.removeEventListener("storage", storageHandler);
1835
- }
1836
- if (broadcastChannel) {
1837
- try {
1838
- broadcastChannel.removeEventListener("message", broadcastHandler);
1839
- broadcastChannel.close();
1840
- } catch {
1841
- }
1842
- broadcastChannel = null;
1843
- }
1844
- };
1845
- const settle = (result) => {
1846
- if (settled) return;
1847
- settled = true;
1848
- cleanup();
1849
- resolve(result);
1850
- };
1851
- const handlePayload = (payload) => {
1852
- if (!payload || payload.type !== MCP_AUTH_CALLBACK_MESSAGE_TYPE) return;
1853
- if (payload.state && state && payload.state !== state) return;
1854
- if (payload.success) {
1855
- settle({ kind: "success" });
1856
- } else {
1857
- settle({
1858
- kind: "error",
1859
- error: payload.error ?? "Authentication failed in callback."
1860
- });
1861
- }
1862
- };
1863
- const messageHandler = (event) => {
1864
- if (expectedOrigin && event.origin !== expectedOrigin) return;
1865
- handlePayload(event.data);
1866
- };
1867
- const broadcastHandler = (event) => {
1868
- handlePayload(event.data);
1869
- };
1870
- const storageHandler = (event) => {
1871
- if (event.key !== tokensKey) return;
1872
- if (event.newValue) settle({ kind: "success" });
1873
- };
1874
- if (typeof window !== "undefined") {
1875
- window.addEventListener("message", messageHandler);
1876
- window.addEventListener("storage", storageHandler);
1877
- }
1878
- if (typeof BroadcastChannel !== "undefined") {
1879
- try {
1880
- broadcastChannel = new BroadcastChannel(MCP_AUTH_BROADCAST_CHANNEL);
1881
- broadcastChannel.addEventListener("message", broadcastHandler);
1882
- } catch {
1883
- broadcastChannel = null;
1884
- }
1885
- }
1886
- if (popup) {
1887
- closeTimer = setInterval(() => {
1888
- if (settled) return;
1889
- let closed = false;
1890
- try {
1891
- closed = popup.closed;
1892
- } catch {
1893
- closed = false;
1894
- }
1895
- if (!closed) return;
1896
- if (closeTimer) {
1897
- clearInterval(closeTimer);
1898
- closeTimer = null;
1899
- }
1900
- if (hasStoredTokens(tokensKey)) {
1901
- settle({ kind: "success" });
1902
- return;
1903
- }
1904
- graceTimer = setTimeout(() => {
1905
- settle(
1906
- hasStoredTokens(tokensKey) ? { kind: "success" } : { kind: "cancelled" }
1907
- );
1908
- }, closeGraceMs);
1909
- }, closePollMs);
1910
- }
1911
- timeoutTimer = setTimeout(() => {
1912
- settle(
1913
- hasStoredTokens(tokensKey) ? { kind: "success" } : { kind: "timeout" }
1914
- );
1915
- }, timeoutMs);
1916
- });
1917
- }
1918
-
1919
- // src/auth/flow.ts
1920
- var DEFAULT_AUTH_TIMEOUT_MS = 5 * 6e4;
1921
- function isUnauthorized(err, depth = 0) {
1922
- if (!err || depth > 5) return false;
1923
- if (err instanceof UnauthorizedError) return true;
1924
- if (err instanceof Error) {
1925
- const code = err.code;
1926
- if (code === 401) return true;
1927
- if (err.name === "UnauthorizedError") return true;
1928
- const message = err.message ?? "";
1929
- if (message.includes("401") || message.includes("Unauthorized")) {
1930
- return true;
1931
- }
1932
- if (err.cause && isUnauthorized(err.cause, depth + 1)) return true;
1933
- const data = err.data;
1934
- if (data?.cause && isUnauthorized(data.cause, depth + 1)) return true;
1919
+ apiKey: PROJECT_API_KEY,
1920
+ event: event.name,
1921
+ distinctId: currentUserId,
1922
+ properties
1923
+ });
1924
+ this._pending.add(p);
1925
+ void p.finally(() => this._pending.delete(p));
1935
1926
  }
1936
- return false;
1937
- }
1938
- async function completeOAuthFlow(provider, serverUrl, options = {}) {
1939
- const flowProvider = provider;
1940
- const timeoutMs = options.timeoutMs ?? DEFAULT_AUTH_TIMEOUT_MS;
1941
- const fetchFn = options.fetchFn ?? flowProvider.getProxyFetch?.() ?? void 0;
1942
- if (!flowProvider.hasPendingFlow) {
1943
- const result = await auth(provider, { serverUrl, fetchFn });
1944
- if (result === "AUTHORIZED") return;
1945
- if (result !== "REDIRECT") {
1946
- throw new Error(`Unexpected OAuth auth() result: ${result}`);
1947
- }
1927
+ async trackAgentExecution(data) {
1928
+ if (!this.isEnabled) return;
1929
+ await this.capture(new MCPAgentExecutionEvent(data));
1948
1930
  }
1949
- if (typeof flowProvider.getAuthorizationResponse === "function" || typeof flowProvider.getAuthorizationCode === "function") {
1950
- const response = typeof flowProvider.getAuthorizationResponse === "function" ? await flowProvider.getAuthorizationResponse() : { code: await flowProvider.getAuthorizationCode() };
1951
- await auth(provider, {
1952
- serverUrl,
1953
- authorizationCode: response.code,
1954
- ...response.iss !== void 0 ? { iss: response.iss } : {},
1955
- fetchFn
1931
+ async trackMCPClientInit(data) {
1932
+ if (!this.isEnabled) return;
1933
+ await this.capture(new MCPClientInitEvent(data));
1934
+ }
1935
+ async trackConnectorInit(data) {
1936
+ if (!this.isEnabled) return;
1937
+ await this.capture(new ConnectorInitEvent(data));
1938
+ }
1939
+ async trackClientAddServer(serverName, serverConfig) {
1940
+ if (!this.isEnabled) return;
1941
+ await this.capture(new ClientAddServerEvent({ serverName, serverConfig }));
1942
+ }
1943
+ async trackClientRemoveServer(serverName) {
1944
+ if (!this.isEnabled) return;
1945
+ await this.capture(new ClientRemoveServerEvent({ serverName }));
1946
+ }
1947
+ async trackUseMcpConnection(data) {
1948
+ if (!this.isEnabled) return;
1949
+ await this.capture({
1950
+ name: "usemcp_connection",
1951
+ properties: {
1952
+ url_domain: new URL(data.url).hostname,
1953
+ transport_type: data.transportType,
1954
+ success: data.success,
1955
+ error_type: data.errorType ?? null,
1956
+ connection_time_ms: data.connectionTimeMs ?? null,
1957
+ has_oauth: data.hasOAuth,
1958
+ has_sampling: data.hasSampling,
1959
+ has_elicitation: data.hasElicitation
1960
+ }
1956
1961
  });
1957
- return;
1958
1962
  }
1959
- await waitForBrowserAuthComplete(flowProvider, timeoutMs);
1960
- }
1961
- async function waitForBrowserAuthComplete(provider, timeoutMs) {
1962
- if (typeof window === "undefined") {
1963
- throw new Error(
1964
- "OAuth redirect requires a browser environment or a provider with getAuthorizationCode()"
1965
- );
1963
+ async trackUseMcpToolCall(data) {
1964
+ if (!this.isEnabled) return;
1965
+ await this.capture({
1966
+ name: "usemcp_tool_call",
1967
+ properties: {
1968
+ tool_name: data.toolName,
1969
+ success: data.success,
1970
+ error_type: data.errorType ?? null,
1971
+ execution_time_ms: data.executionTimeMs ?? null
1972
+ }
1973
+ });
1966
1974
  }
1967
- if (provider.useRedirectFlow) {
1968
- await new Promise(() => {
1975
+ async trackUseMcpResourceRead(data) {
1976
+ if (!this.isEnabled) return;
1977
+ await this.capture({
1978
+ name: "usemcp_resource_read",
1979
+ properties: {
1980
+ resource_uri_scheme: data.resourceUri.split(":")[0],
1981
+ success: data.success,
1982
+ error_type: data.errorType ?? null
1983
+ }
1969
1984
  });
1970
- return;
1971
1985
  }
1972
- const tokensKey = provider.getKey?.("tokens");
1973
- if (!tokensKey) {
1974
- throw new Error(
1975
- "Browser OAuth provider must expose getKey() for token storage"
1976
- );
1986
+ identify(userId, properties) {
1987
+ this._currUserId = userId;
1988
+ this._storage?.setUserId(userId);
1989
+ if (this._telemetryEnabled) {
1990
+ void capturePostHog({
1991
+ host: HOST,
1992
+ apiKey: PROJECT_API_KEY,
1993
+ event: "$identify",
1994
+ distinctId: userId,
1995
+ properties: { $set: properties ?? {} }
1996
+ });
1997
+ }
1977
1998
  }
1978
- let state = null;
1979
- const authUrl = provider.getLastAttemptedAuthUrl?.();
1980
- if (authUrl) {
1999
+ reset() {
2000
+ this._currUserId = null;
2001
+ }
2002
+ flush() {
2003
+ void Promise.allSettled([...this._pending]);
2004
+ }
2005
+ async shutdown() {
1981
2006
  try {
1982
- state = new URL(authUrl).searchParams.get("state");
1983
- } catch {
2007
+ await Promise.allSettled([...this._pending]);
2008
+ logger.debug("Telemetry fetch captures flushed");
2009
+ } catch (e) {
2010
+ logger.debug(`Error flushing telemetry captures: ${e}`);
1984
2011
  }
1985
2012
  }
2013
+ };
2014
+ var Tel = Telemetry;
2015
+ function setTelemetrySource(source) {
2016
+ Tel.getInstance().setSource(source);
2017
+ }
2018
+ function setProductVersion(version) {
2019
+ Tel.getInstance().setProductVersion(version);
2020
+ }
2021
+
2022
+ // src/telemetry/telemetry-node.ts
2023
+ function getCacheHome(os, path2) {
2024
+ const envVar = process.env.XDG_CACHE_HOME;
2025
+ if (envVar && path2.isAbsolute(envVar)) {
2026
+ return envVar;
2027
+ }
2028
+ const homeDir = os.homedir();
2029
+ if (process.platform === "win32") {
2030
+ const appdata = process.env.LOCALAPPDATA || process.env.APPDATA;
2031
+ if (appdata) return appdata;
2032
+ return path2.join(homeDir, "AppData", "Local");
2033
+ }
2034
+ if (process.platform === "darwin") {
2035
+ return path2.join(homeDir, "Library", "Caches");
2036
+ }
2037
+ return path2.join(homeDir, ".cache");
2038
+ }
2039
+ function createFsStorage() {
2040
+ let fs2;
2041
+ let os;
2042
+ let path2;
1986
2043
  try {
1987
- const result = await runAuthPopup({
1988
- popup: null,
1989
- state,
1990
- tokensKey,
1991
- timeoutMs
1992
- });
1993
- switch (result.kind) {
1994
- case "success":
1995
- return;
1996
- case "cancelled":
1997
- throw new Error("OAuth authentication was cancelled.");
1998
- case "timeout":
1999
- throw new Error(
2000
- `OAuth callback not received within ${timeoutMs}ms. Ensure /oauth/callback calls onMcpAuthorization().`
2001
- );
2002
- case "error":
2003
- throw new Error(result.error);
2004
- default:
2005
- throw new Error("Unexpected OAuth popup result");
2006
- }
2007
- } finally {
2008
- provider.markFlowComplete?.();
2044
+ fs2 = __require("fs");
2045
+ os = __require("os");
2046
+ path2 = __require("path");
2047
+ } catch {
2048
+ return {
2049
+ getUserId: () => null,
2050
+ setUserId: () => void 0
2051
+ };
2009
2052
  }
2053
+ const cacheHome = getCacheHome(os, path2);
2054
+ const userIdPath = path2.join(cacheHome, "mcp_use_3", "telemetry_user_id");
2055
+ return {
2056
+ getUserId() {
2057
+ try {
2058
+ if (!fs2.existsSync(userIdPath)) return null;
2059
+ return fs2.readFileSync(userIdPath, "utf-8").trim() || null;
2060
+ } catch {
2061
+ return null;
2062
+ }
2063
+ },
2064
+ setUserId(id) {
2065
+ try {
2066
+ fs2.mkdirSync(path2.dirname(userIdPath), { recursive: true });
2067
+ fs2.writeFileSync(userIdPath, id);
2068
+ } catch {
2069
+ }
2070
+ }
2071
+ };
2010
2072
  }
2073
+ configureTelemetryStorage(createFsStorage());
2074
+
2075
+ // src/telemetry/configure-node.ts
2076
+ setClientTelemetryTracker({
2077
+ addServer: (name, config) => Telemetry.getInstance().trackClientAddServer(name, config).catch(() => void 0),
2078
+ removeServer: (name) => Telemetry.getInstance().trackClientRemoveServer(name).catch(() => void 0)
2079
+ });
2080
+ setConnectorTelemetryTracker(
2081
+ (data) => Telemetry.getInstance().trackConnectorInit(data).catch(() => void 0)
2082
+ );
2083
+
2084
+ // src/index.ts
2085
+ init_flow();
2086
+ import { auth as auth2, UnauthorizedError as UnauthorizedError3 } from "@modelcontextprotocol/client";
2011
2087
 
2012
2088
  // src/auth/node.ts
2013
2089
  import { createServer as createNetServer } from "net";
@@ -2840,16 +2916,19 @@ async function createOAuthProvider(serverUrl, options = {}) {
2840
2916
  }
2841
2917
 
2842
2918
  // src/transport/http.ts
2919
+ init_flow();
2843
2920
  init_json_schema_validator();
2844
2921
  init_logging();
2845
2922
  init_base();
2846
2923
  import {
2847
2924
  Client,
2925
+ discoverOAuthProtectedResourceMetadata,
2848
2926
  SdkError,
2849
2927
  SdkHttpError,
2850
2928
  StreamableHTTPClientTransport,
2851
2929
  UnauthorizedError as UnauthorizedError2
2852
2930
  } from "@modelcontextprotocol/client";
2931
+ var MIXED_AUTH_DISCOVERY_TIMEOUT_MS = 2e3;
2853
2932
  function detectUnauthorized(err, depth = 0) {
2854
2933
  if (!err || depth > 5) return false;
2855
2934
  if (err instanceof UnauthorizedError2) return true;
@@ -2863,6 +2942,11 @@ function detectUnauthorized(err, depth = 0) {
2863
2942
  }
2864
2943
  return false;
2865
2944
  }
2945
+ function isOAuthClientProvider(provider) {
2946
+ return Boolean(
2947
+ provider && "redirectToAuthorization" in provider && typeof provider.redirectToAuthorization === "function" && "tokens" in provider && typeof provider.tokens === "function"
2948
+ );
2949
+ }
2866
2950
  function createMcpProxyFetch(logicalServerUrl, proxyUrl, baseFetch, serverId) {
2867
2951
  const logical = new URL(logicalServerUrl);
2868
2952
  const proxy = proxyUrl.replace(/\/$/, "");
@@ -2888,6 +2972,31 @@ function createMcpProxyFetch(logicalServerUrl, proxyUrl, baseFetch, serverId) {
2888
2972
  );
2889
2973
  };
2890
2974
  }
2975
+ function createDeadlineFetch(baseFetch, deadlineSignal) {
2976
+ return async (input, init) => {
2977
+ const requestSignal = init?.signal;
2978
+ if (!requestSignal) {
2979
+ return baseFetch(input, { ...init, signal: deadlineSignal });
2980
+ }
2981
+ const controller = new AbortController();
2982
+ const abortFromRequest = () => controller.abort(requestSignal.reason);
2983
+ const abortFromDeadline = () => controller.abort(deadlineSignal.reason);
2984
+ if (requestSignal.aborted) abortFromRequest();
2985
+ else
2986
+ requestSignal.addEventListener("abort", abortFromRequest, { once: true });
2987
+ if (deadlineSignal.aborted) abortFromDeadline();
2988
+ else
2989
+ deadlineSignal.addEventListener("abort", abortFromDeadline, {
2990
+ once: true
2991
+ });
2992
+ try {
2993
+ return await baseFetch(input, { ...init, signal: controller.signal });
2994
+ } finally {
2995
+ requestSignal.removeEventListener("abort", abortFromRequest);
2996
+ deadlineSignal.removeEventListener("abort", abortFromDeadline);
2997
+ }
2998
+ };
2999
+ }
2891
3000
  var HttpConnector = class extends BaseConnector {
2892
3001
  baseUrl;
2893
3002
  headers;
@@ -2898,8 +3007,11 @@ var HttpConnector = class extends BaseConnector {
2898
3007
  gatewayUrl;
2899
3008
  serverId;
2900
3009
  reconnectionOptions;
3010
+ detectMixedAuth;
2901
3011
  transportType = null;
2902
3012
  streamableTransport = null;
3013
+ hadAccessTokenAtConnect = false;
3014
+ pendingOAuthCompletion = null;
2903
3015
  /**
2904
3016
  * Creates an HTTP connector.
2905
3017
  *
@@ -2930,6 +3042,99 @@ var HttpConnector = class extends BaseConnector {
2930
3042
  };
2931
3043
  this.protocolNegotiation = opts.protocolNegotiation ?? "auto";
2932
3044
  this.reconnectionOptions = opts.reconnectionOptions;
3045
+ this.detectMixedAuth = opts.detectMixedAuth ?? true;
3046
+ }
3047
+ get oauthProvider() {
3048
+ return isOAuthClientProvider(this.opts.authProvider) ? this.opts.authProvider : void 0;
3049
+ }
3050
+ async completeInteractiveAuthorization() {
3051
+ const provider = this.oauthProvider;
3052
+ if (!provider) {
3053
+ throw new Error("No OAuth client provider is configured");
3054
+ }
3055
+ if (!this.pendingOAuthCompletion) {
3056
+ this.pendingOAuthCompletion = completeOAuthFlow(provider, this.baseUrl, {
3057
+ fetchFn: this.customFetch,
3058
+ finishAuthorization: async (code, iss) => {
3059
+ const transport = this.streamableTransport;
3060
+ if (!transport) {
3061
+ throw new Error("OAuth transport is no longer connected");
3062
+ }
3063
+ await transport.finishAuth(code, iss);
3064
+ }
3065
+ }).then(() => {
3066
+ if (this.authorizationCache) {
3067
+ this.authorizationCache = {
3068
+ ...this.authorizationCache,
3069
+ authenticated: true
3070
+ };
3071
+ }
3072
+ }).finally(() => {
3073
+ this.pendingOAuthCompletion = null;
3074
+ });
3075
+ }
3076
+ await this.pendingOAuthCompletion;
3077
+ }
3078
+ async executeRequest(operation) {
3079
+ try {
3080
+ return await operation();
3081
+ } catch (error) {
3082
+ const provider = this.oauthProvider;
3083
+ if (!provider || provider.preventAutoAuth === true || !isOAuthInteractionRequired(error)) {
3084
+ throw error;
3085
+ }
3086
+ await this.completeInteractiveAuthorization();
3087
+ return operation();
3088
+ }
3089
+ }
3090
+ /** Authenticate an already-connected server without requiring a 401 first. */
3091
+ async authenticate() {
3092
+ if (!this.connected || !this.streamableTransport) {
3093
+ throw new Error("MCP client is not connected");
3094
+ }
3095
+ await this.completeInteractiveAuthorization();
3096
+ }
3097
+ async initialize(defaultRequestOptions = this.opts.defaultRequestOptions ?? {}) {
3098
+ const capabilities = await super.initialize(defaultRequestOptions);
3099
+ if (!this.detectMixedAuth || !this.oauthProvider || this.hadAccessTokenAtConnect) {
3100
+ return capabilities;
3101
+ }
3102
+ const controller = new AbortController();
3103
+ let timeout;
3104
+ const discoveryTimeout = new Promise((_, reject) => {
3105
+ timeout = setTimeout(() => {
3106
+ const error = new Error(
3107
+ `Mixed-auth metadata discovery timed out after ${MIXED_AUTH_DISCOVERY_TIMEOUT_MS}ms`
3108
+ );
3109
+ controller.abort(error);
3110
+ reject(error);
3111
+ }, MIXED_AUTH_DISCOVERY_TIMEOUT_MS);
3112
+ });
3113
+ const baseFetch = this.customFetch ?? globalThis.fetch.bind(globalThis);
3114
+ try {
3115
+ const metadata = await Promise.race([
3116
+ discoverOAuthProtectedResourceMetadata(
3117
+ this.baseUrl,
3118
+ { protocolVersion: this.negotiatedProtocolVersion },
3119
+ createDeadlineFetch(baseFetch, controller.signal)
3120
+ ),
3121
+ discoveryTimeout
3122
+ ]);
3123
+ this.authorizationCache = {
3124
+ mode: "mixed",
3125
+ authenticated: false,
3126
+ ...metadata.resource ? { resource: metadata.resource } : {},
3127
+ ...metadata.scopes_supported ? { scopesSupported: [...metadata.scopes_supported] } : {}
3128
+ };
3129
+ logger.info(
3130
+ "OAuth protected-resource metadata found after anonymous connection; server uses mixed auth"
3131
+ );
3132
+ } catch (error) {
3133
+ logger.debug("Mixed-auth metadata was not discovered:", error);
3134
+ } finally {
3135
+ if (timeout) clearTimeout(timeout);
3136
+ }
3137
+ return capabilities;
2933
3138
  }
2934
3139
  buildClientOptions() {
2935
3140
  return {
@@ -3036,6 +3241,16 @@ var HttpConnector = class extends BaseConnector {
3036
3241
  }
3037
3242
  const baseUrl = this.baseUrl;
3038
3243
  logger.debug(`Connecting to MCP implementation via HTTP: ${baseUrl}`);
3244
+ const oauthProvider = this.oauthProvider;
3245
+ if (oauthProvider) {
3246
+ try {
3247
+ this.hadAccessTokenAtConnect = Boolean(
3248
+ (await oauthProvider.tokens())?.access_token
3249
+ );
3250
+ } catch {
3251
+ this.hadAccessTokenAtConnect = false;
3252
+ }
3253
+ }
3039
3254
  try {
3040
3255
  await this.connectWithStreamableHttp(baseUrl);
3041
3256
  logger.debug("\u2705 Successfully connected via streamable HTTP");
@@ -3387,6 +3602,7 @@ function createConnectorFromConfig(serverConfig, connectorOptions) {
3387
3602
  fetch: serverConfig.fetch,
3388
3603
  authToken: serverConfig.authToken,
3389
3604
  authProvider: serverConfig.authProvider,
3605
+ detectMixedAuth: serverConfig.detectMixedAuth,
3390
3606
  protocolNegotiation: serverConfig.protocolNegotiation,
3391
3607
  timeout: serverConfig.timeout,
3392
3608
  roots: serverConfig.roots,
@@ -3404,6 +3620,7 @@ import fs from "fs";
3404
3620
  import path from "path";
3405
3621
 
3406
3622
  // src/core/base.ts
3623
+ init_flow();
3407
3624
  init_logging();
3408
3625
 
3409
3626
  // src/core/skills.ts
@@ -3636,6 +3853,14 @@ var MCPConnection = class {
3636
3853
  get serverInfo() {
3637
3854
  return this.connector.serverInfo;
3638
3855
  }
3856
+ /** OAuth state discovered for this connection, when available. */
3857
+ get authorization() {
3858
+ return this.connector.authorization;
3859
+ }
3860
+ /** Authenticate an already-connected mixed-auth server. */
3861
+ async authenticate() {
3862
+ await this.connector.authenticate();
3863
+ }
3639
3864
  /**
3640
3865
  * The negotiated protocol era for this session's connection:
3641
3866
  * `"legacy"` (2025-era) or `"modern"` (2026-07-28-era).
@@ -3668,7 +3893,8 @@ var MCPConnection = class {
3668
3893
  ...server ? { server } : {},
3669
3894
  capabilities,
3670
3895
  instructions: this.connector.instructions,
3671
- extensions
3896
+ extensions,
3897
+ ...this.authorization ? { authorization: this.authorization } : {}
3672
3898
  };
3673
3899
  }
3674
3900
  /**
@@ -3899,7 +4125,7 @@ var MCPConnection = class {
3899
4125
  };
3900
4126
 
3901
4127
  // src/core/base.ts
3902
- function isOAuthClientProvider(provider) {
4128
+ function isOAuthClientProvider2(provider) {
3903
4129
  return !!provider && typeof provider === "object" && "redirectUrl" in provider && "clientMetadata" in provider;
3904
4130
  }
3905
4131
  var BaseMCPClient = class {
@@ -4132,7 +4358,7 @@ var BaseMCPClient = class {
4132
4358
  ...serverConfig,
4133
4359
  authProvider: oauthProvider
4134
4360
  };
4135
- } else if ("authProvider" in serverConfig && serverConfig.authProvider && isOAuthClientProvider(serverConfig.authProvider)) {
4361
+ } else if ("authProvider" in serverConfig && serverConfig.authProvider && isOAuthClientProvider2(serverConfig.authProvider)) {
4136
4362
  oauthProvider = serverConfig.authProvider;
4137
4363
  }
4138
4364
  const openSession = async () => {
@@ -5818,6 +6044,7 @@ export {
5818
6044
  createOAuthProvider,
5819
6045
  decline,
5820
6046
  getDefaults,
6047
+ isOAuthInteractionRequired,
5821
6048
  isUnauthorized,
5822
6049
  isVMAvailable,
5823
6050
  loadConfigFile,