@mcp-use/client 2.1.0 → 2.1.1-canary.1

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.
@@ -128,7 +128,7 @@ var Logger = class {
128
128
  var logger = Logger.get();
129
129
 
130
130
  // src/utils/version.ts
131
- var VERSION = "2.1.0";
131
+ var VERSION = "2.1.1-canary.1";
132
132
  function getPackageVersion() {
133
133
  return VERSION;
134
134
  }
@@ -1530,29 +1530,43 @@ var BrowserOAuthClientProvider = class {
1530
1530
  * @param authorizationUrl - The fully constructed authorization URL from the SDK.
1531
1531
  */
1532
1532
  async redirectToAuthorization(authorizationUrl) {
1533
- const sanitizedAuthUrl = await this.prepareAuthorizationUrl(authorizationUrl);
1533
+ await this.prepareAuthorizationUrl(authorizationUrl);
1534
1534
  if (this.preventAutoAuth) {
1535
1535
  console.info(
1536
1536
  `[${this.storageKeyPrefix}] Auto-auth prevented. Authorization URL stored for manual trigger.`
1537
1537
  );
1538
1538
  return;
1539
1539
  }
1540
+ this.startAuthorization();
1541
+ }
1542
+ /**
1543
+ * Open the authorization URL prepared by the official SDK.
1544
+ *
1545
+ * This is the explicit-user-action counterpart to `preventAutoAuth`: the
1546
+ * provider still lets the SDK own discovery and PKCE state, while a host can
1547
+ * launch the stored authorization request later from an Authenticate button.
1548
+ */
1549
+ startAuthorization() {
1550
+ const authorizationUrl = this.lastAttemptedAuthUrl;
1551
+ if (!authorizationUrl) {
1552
+ throw new Error("No prepared OAuth authorization is available");
1553
+ }
1540
1554
  if (this.useRedirectFlow) {
1541
1555
  console.info(
1542
1556
  `[${this.storageKeyPrefix}] Redirecting to authorization URL (full-page redirect).`
1543
1557
  );
1544
- window.location.href = sanitizedAuthUrl;
1558
+ window.location.href = authorizationUrl;
1545
1559
  return;
1546
1560
  }
1547
1561
  const popupFeatures = "width=600,height=700,resizable=yes,scrollbars=yes,status=yes";
1548
1562
  try {
1549
1563
  const popup = window.open(
1550
- sanitizedAuthUrl,
1564
+ authorizationUrl,
1551
1565
  `mcp_auth_${this.serverUrlHash}`,
1552
1566
  popupFeatures
1553
1567
  );
1554
1568
  if (this.onPopupWindow) {
1555
- this.onPopupWindow(sanitizedAuthUrl, popupFeatures, popup);
1569
+ this.onPopupWindow(authorizationUrl, popupFeatures, popup);
1556
1570
  }
1557
1571
  if (!popup || popup.closed || typeof popup.closed === "undefined") {
1558
1572
  console.warn(
@@ -1931,6 +1945,7 @@ async function completeAuthorization() {
1931
1945
  // src/auth/flow.ts
1932
1946
  import {
1933
1947
  auth,
1948
+ InsufficientScopeError,
1934
1949
  UnauthorizedError
1935
1950
  } from "@modelcontextprotocol/client";
1936
1951
  var DEFAULT_AUTH_TIMEOUT_MS = 5 * 6e4;
@@ -1951,6 +1966,25 @@ function isUnauthorized(err, depth = 0) {
1951
1966
  }
1952
1967
  return false;
1953
1968
  }
1969
+ function isOAuthInteractionRequired(err, depth = 0) {
1970
+ if (!err || depth > 5) return false;
1971
+ if (err instanceof InsufficientScopeError || err instanceof UnauthorizedError) {
1972
+ return true;
1973
+ }
1974
+ if (err instanceof Error) {
1975
+ if (err.name === "InsufficientScopeError" || err.name === "UnauthorizedError") {
1976
+ return true;
1977
+ }
1978
+ if (err.cause && isOAuthInteractionRequired(err.cause, depth + 1)) {
1979
+ return true;
1980
+ }
1981
+ const data = err.data;
1982
+ if (data?.cause && isOAuthInteractionRequired(data.cause, depth + 1)) {
1983
+ return true;
1984
+ }
1985
+ }
1986
+ return false;
1987
+ }
1954
1988
  async function completeOAuthFlow(provider, serverUrl, options = {}) {
1955
1989
  const flowProvider = provider;
1956
1990
  const timeoutMs = options.timeoutMs ?? DEFAULT_AUTH_TIMEOUT_MS;
@@ -1962,14 +1996,21 @@ async function completeOAuthFlow(provider, serverUrl, options = {}) {
1962
1996
  throw new Error(`Unexpected OAuth auth() result: ${result}`);
1963
1997
  }
1964
1998
  }
1999
+ if (flowProvider.preventAutoAuth === true && typeof flowProvider.startAuthorization === "function") {
2000
+ flowProvider.startAuthorization();
2001
+ }
1965
2002
  if (typeof flowProvider.getAuthorizationResponse === "function" || typeof flowProvider.getAuthorizationCode === "function") {
1966
2003
  const response = typeof flowProvider.getAuthorizationResponse === "function" ? await flowProvider.getAuthorizationResponse() : { code: await flowProvider.getAuthorizationCode() };
1967
- await auth(provider, {
1968
- serverUrl,
1969
- authorizationCode: response.code,
1970
- ...response.iss !== void 0 ? { iss: response.iss } : {},
1971
- fetchFn
1972
- });
2004
+ if (options.finishAuthorization) {
2005
+ await options.finishAuthorization(response.code, response.iss);
2006
+ } else {
2007
+ await auth(provider, {
2008
+ serverUrl,
2009
+ authorizationCode: response.code,
2010
+ ...response.iss !== void 0 ? { iss: response.iss } : {},
2011
+ fetchFn
2012
+ });
2013
+ }
1973
2014
  return;
1974
2015
  }
1975
2016
  await waitForBrowserAuthComplete(flowProvider, timeoutMs);
@@ -2031,6 +2072,7 @@ import { auth as auth2, UnauthorizedError as UnauthorizedError3 } from "@modelco
2031
2072
  // src/transport/http.ts
2032
2073
  import {
2033
2074
  Client,
2075
+ discoverOAuthProtectedResourceMetadata,
2034
2076
  SdkError,
2035
2077
  SdkHttpError,
2036
2078
  StreamableHTTPClientTransport as StreamableHTTPClientTransport2,
@@ -2087,6 +2129,7 @@ var BaseConnector = class {
2087
2129
  toolsCache = null;
2088
2130
  capabilitiesCache = null;
2089
2131
  serverInfoCache = null;
2132
+ authorizationCache;
2090
2133
  connected = false;
2091
2134
  opts;
2092
2135
  notificationHandlers = [];
@@ -2350,6 +2393,28 @@ var BaseConnector = class {
2350
2393
  "setupElicitationHandler: Elicitation handler registered successfully"
2351
2394
  );
2352
2395
  }
2396
+ /**
2397
+ * Run one logical MCP operation. HTTP connectors override this host seam to
2398
+ * finish an SDK-started interactive OAuth flow and retry exactly once.
2399
+ */
2400
+ async executeRequest(operation) {
2401
+ return operation();
2402
+ }
2403
+ /** OAuth state discovered for the active connection, when available. */
2404
+ get authorization() {
2405
+ return this.authorizationCache;
2406
+ }
2407
+ /**
2408
+ * Discover optional authorization metadata without delaying connection
2409
+ * readiness. HTTP connectors override this with RFC 9728 discovery.
2410
+ */
2411
+ async discoverAuthorization() {
2412
+ return this.authorization;
2413
+ }
2414
+ /** Start optional OAuth for a connected mixed-auth server. */
2415
+ async authenticate() {
2416
+ throw new Error("This connector does not support interactive OAuth");
2417
+ }
2353
2418
  /**
2354
2419
  * Disconnects the SDK client and releases transport resources.
2355
2420
  *
@@ -2397,13 +2462,13 @@ var BaseConnector = class {
2397
2462
  icons: serverInfo.icons
2398
2463
  } : null;
2399
2464
  try {
2400
- const listToolsRes = await this.client.listTools(
2401
- void 0,
2402
- defaultRequestOptions
2465
+ const listToolsRes = await this.executeRequest(
2466
+ () => this.client.listTools(void 0, defaultRequestOptions)
2403
2467
  );
2404
2468
  this.toolsCache = listToolsRes.tools ?? [];
2405
2469
  logger.debug(`Fetched ${this.toolsCache.length} tools from server`);
2406
2470
  } catch (err) {
2471
+ if (isOAuthInteractionRequired(err)) throw err;
2407
2472
  const error = err;
2408
2473
  if (error.code === -32601) {
2409
2474
  logger.debug("Server does not implement tools/list, assuming no tools");
@@ -2477,9 +2542,8 @@ var BaseConnector = class {
2477
2542
  const progressHandler = enhancedOptions?.onprogress;
2478
2543
  if (progressHandler) this.activeProgressHandlers.add(progressHandler);
2479
2544
  try {
2480
- const res = await this.client.callTool(
2481
- { name, arguments: args },
2482
- enhancedOptions
2545
+ const res = await this.executeRequest(
2546
+ () => this.client.callTool({ name, arguments: args }, enhancedOptions)
2483
2547
  );
2484
2548
  logger.debug(`Tool '${name}' returned`, res);
2485
2549
  return res;
@@ -2499,7 +2563,9 @@ var BaseConnector = class {
2499
2563
  throw new Error("MCP client is not connected");
2500
2564
  }
2501
2565
  logger.debug("[listTools] Fetching fresh tools from server...");
2502
- const result = await this.client.listTools(void 0, options);
2566
+ const result = await this.executeRequest(
2567
+ () => this.client.listTools(void 0, options)
2568
+ );
2503
2569
  const tools = result.tools ? [...result.tools] : [];
2504
2570
  logger.debug(
2505
2571
  `[listTools] Returned ${tools.length} tools:`,
@@ -2519,7 +2585,9 @@ var BaseConnector = class {
2519
2585
  throw new Error("MCP client is not connected");
2520
2586
  }
2521
2587
  logger.debug("Listing resources", cursor ? `with cursor: ${cursor}` : "");
2522
- return await this.client.listResources({ cursor }, options);
2588
+ return await this.executeRequest(
2589
+ () => this.client.listResources({ cursor }, options)
2590
+ );
2523
2591
  }
2524
2592
  /**
2525
2593
  * List all resources from the server, automatically handling pagination
@@ -2537,14 +2605,16 @@ var BaseConnector = class {
2537
2605
  }
2538
2606
  try {
2539
2607
  logger.debug("Listing all resources (with auto-pagination)");
2540
- const allResources = [];
2541
- let cursor = void 0;
2542
- do {
2543
- const result = await this.client.listResources({ cursor }, options);
2544
- allResources.push(...result.resources || []);
2545
- cursor = result.nextCursor;
2546
- } while (cursor);
2547
- return { resources: allResources };
2608
+ return await this.executeRequest(async () => {
2609
+ const allResources = [];
2610
+ let cursor = void 0;
2611
+ do {
2612
+ const result = await this.client.listResources({ cursor }, options);
2613
+ allResources.push(...result.resources || []);
2614
+ cursor = result.nextCursor;
2615
+ } while (cursor);
2616
+ return { resources: allResources };
2617
+ });
2548
2618
  } catch (err) {
2549
2619
  const error = err;
2550
2620
  if (error.code === -32601) {
@@ -2565,7 +2635,9 @@ var BaseConnector = class {
2565
2635
  throw new Error("MCP client is not connected");
2566
2636
  }
2567
2637
  logger.debug("Listing resource templates");
2568
- return await this.client.listResourceTemplates(void 0, options);
2638
+ return await this.executeRequest(
2639
+ () => this.client.listResourceTemplates(void 0, options)
2640
+ );
2569
2641
  }
2570
2642
  /**
2571
2643
  * Request completion suggestions for a prompt or resource template argument
@@ -2579,7 +2651,9 @@ var BaseConnector = class {
2579
2651
  throw new Error("MCP client is not connected");
2580
2652
  }
2581
2653
  logger.debug("[complete] Requesting completions for:", params.ref);
2582
- const result = await this.client.complete(params, options);
2654
+ const result = await this.executeRequest(
2655
+ () => this.client.complete(params, options)
2656
+ );
2583
2657
  logger.debug(
2584
2658
  `[complete] Received ${result.completion.values.length} suggestions`
2585
2659
  );
@@ -2597,7 +2671,9 @@ var BaseConnector = class {
2597
2671
  throw new Error("MCP client is not connected");
2598
2672
  }
2599
2673
  logger.debug(`Reading resource ${uri}`);
2600
- const res = await this.client.readResource({ uri }, options);
2674
+ const res = await this.executeRequest(
2675
+ () => this.client.readResource({ uri }, options)
2676
+ );
2601
2677
  return res;
2602
2678
  }
2603
2679
  /**
@@ -2611,7 +2687,9 @@ var BaseConnector = class {
2611
2687
  throw new Error("MCP client is not connected");
2612
2688
  }
2613
2689
  logger.debug(`Subscribing to resource: ${uri}`);
2614
- return await this.client.subscribeResource({ uri }, options);
2690
+ return await this.executeRequest(
2691
+ () => this.client.subscribeResource({ uri }, options)
2692
+ );
2615
2693
  }
2616
2694
  /**
2617
2695
  * Unsubscribe from resource updates
@@ -2624,7 +2702,9 @@ var BaseConnector = class {
2624
2702
  throw new Error("MCP client is not connected");
2625
2703
  }
2626
2704
  logger.debug(`Unsubscribing from resource: ${uri}`);
2627
- return await this.client.unsubscribeResource({ uri }, options);
2705
+ return await this.executeRequest(
2706
+ () => this.client.unsubscribeResource({ uri }, options)
2707
+ );
2628
2708
  }
2629
2709
  /**
2630
2710
  * Lists prompts exposed by the server.
@@ -2641,7 +2721,7 @@ var BaseConnector = class {
2641
2721
  }
2642
2722
  try {
2643
2723
  logger.debug("Listing prompts");
2644
- return await this.client.listPrompts();
2724
+ return await this.executeRequest(() => this.client.listPrompts());
2645
2725
  } catch (err) {
2646
2726
  const error = err;
2647
2727
  if (error.code === -32601) {
@@ -2663,7 +2743,9 @@ var BaseConnector = class {
2663
2743
  throw new Error("MCP client is not connected");
2664
2744
  }
2665
2745
  logger.debug(`Getting prompt ${name}`);
2666
- return await this.client.getPrompt({ name, arguments: args });
2746
+ return await this.executeRequest(
2747
+ () => this.client.getPrompt({ name, arguments: args })
2748
+ );
2667
2749
  }
2668
2750
  /**
2669
2751
  * Sends a raw, potentially non-standard request through the SDK client.
@@ -2678,10 +2760,12 @@ var BaseConnector = class {
2678
2760
  throw new Error("MCP client is not connected");
2679
2761
  }
2680
2762
  logger.debug(`Sending raw request '${method}' with params`, params);
2681
- return await this.client.request(
2682
- { method, params: params ?? {} },
2683
- passthroughResultSchema,
2684
- options
2763
+ return await this.executeRequest(
2764
+ () => this.client.request(
2765
+ { method, params: params ?? {} },
2766
+ passthroughResultSchema,
2767
+ options
2768
+ )
2685
2769
  );
2686
2770
  }
2687
2771
  /**
@@ -2714,6 +2798,7 @@ var BaseConnector = class {
2714
2798
  }
2715
2799
  }
2716
2800
  this.toolsCache = null;
2801
+ this.authorizationCache = void 0;
2717
2802
  if (issues.length) {
2718
2803
  logger.warn(`Resource cleanup finished with ${issues.length} issue(s)`);
2719
2804
  }
@@ -2721,6 +2806,7 @@ var BaseConnector = class {
2721
2806
  };
2722
2807
 
2723
2808
  // src/transport/http.ts
2809
+ var MIXED_AUTH_DISCOVERY_TIMEOUT_MS = 2e3;
2724
2810
  function detectUnauthorized(err, depth = 0) {
2725
2811
  if (!err || depth > 5) return false;
2726
2812
  if (err instanceof UnauthorizedError2) return true;
@@ -2734,6 +2820,11 @@ function detectUnauthorized(err, depth = 0) {
2734
2820
  }
2735
2821
  return false;
2736
2822
  }
2823
+ function isOAuthClientProvider(provider) {
2824
+ return Boolean(
2825
+ provider && "redirectToAuthorization" in provider && typeof provider.redirectToAuthorization === "function" && "tokens" in provider && typeof provider.tokens === "function"
2826
+ );
2827
+ }
2737
2828
  function createMcpProxyFetch(logicalServerUrl, proxyUrl, baseFetch, serverId) {
2738
2829
  const logical = new URL(logicalServerUrl);
2739
2830
  const proxy = proxyUrl.replace(/\/$/, "");
@@ -2759,6 +2850,31 @@ function createMcpProxyFetch(logicalServerUrl, proxyUrl, baseFetch, serverId) {
2759
2850
  );
2760
2851
  };
2761
2852
  }
2853
+ function createDeadlineFetch(baseFetch, deadlineSignal) {
2854
+ return async (input, init) => {
2855
+ const requestSignal = init?.signal;
2856
+ if (!requestSignal) {
2857
+ return baseFetch(input, { ...init, signal: deadlineSignal });
2858
+ }
2859
+ const controller = new AbortController();
2860
+ const abortFromRequest = () => controller.abort(requestSignal.reason);
2861
+ const abortFromDeadline = () => controller.abort(deadlineSignal.reason);
2862
+ if (requestSignal.aborted) abortFromRequest();
2863
+ else
2864
+ requestSignal.addEventListener("abort", abortFromRequest, { once: true });
2865
+ if (deadlineSignal.aborted) abortFromDeadline();
2866
+ else
2867
+ deadlineSignal.addEventListener("abort", abortFromDeadline, {
2868
+ once: true
2869
+ });
2870
+ try {
2871
+ return await baseFetch(input, { ...init, signal: controller.signal });
2872
+ } finally {
2873
+ requestSignal.removeEventListener("abort", abortFromRequest);
2874
+ deadlineSignal.removeEventListener("abort", abortFromDeadline);
2875
+ }
2876
+ };
2877
+ }
2762
2878
  var HttpConnector = class extends BaseConnector {
2763
2879
  baseUrl;
2764
2880
  headers;
@@ -2769,8 +2885,12 @@ var HttpConnector = class extends BaseConnector {
2769
2885
  gatewayUrl;
2770
2886
  serverId;
2771
2887
  reconnectionOptions;
2888
+ detectMixedAuth;
2772
2889
  transportType = null;
2773
2890
  streamableTransport = null;
2891
+ hadAccessTokenAtConnect = false;
2892
+ pendingOAuthCompletion = null;
2893
+ authorizationDiscovery = null;
2774
2894
  /**
2775
2895
  * Creates an HTTP connector.
2776
2896
  *
@@ -2801,6 +2921,103 @@ var HttpConnector = class extends BaseConnector {
2801
2921
  };
2802
2922
  this.protocolNegotiation = opts.protocolNegotiation ?? "auto";
2803
2923
  this.reconnectionOptions = opts.reconnectionOptions;
2924
+ this.detectMixedAuth = opts.detectMixedAuth ?? true;
2925
+ }
2926
+ get oauthProvider() {
2927
+ return isOAuthClientProvider(this.opts.authProvider) ? this.opts.authProvider : void 0;
2928
+ }
2929
+ async completeInteractiveAuthorization() {
2930
+ const provider = this.oauthProvider;
2931
+ if (!provider) {
2932
+ throw new Error("No OAuth client provider is configured");
2933
+ }
2934
+ if (!this.pendingOAuthCompletion) {
2935
+ this.pendingOAuthCompletion = completeOAuthFlow(provider, this.baseUrl, {
2936
+ fetchFn: this.customFetch,
2937
+ finishAuthorization: async (code, iss) => {
2938
+ const transport = this.streamableTransport;
2939
+ if (!transport) {
2940
+ throw new Error("OAuth transport is no longer connected");
2941
+ }
2942
+ await transport.finishAuth(code, iss);
2943
+ }
2944
+ }).then(() => {
2945
+ if (this.authorizationCache) {
2946
+ this.authorizationCache = {
2947
+ ...this.authorizationCache,
2948
+ authenticated: true
2949
+ };
2950
+ }
2951
+ }).finally(() => {
2952
+ this.pendingOAuthCompletion = null;
2953
+ });
2954
+ }
2955
+ await this.pendingOAuthCompletion;
2956
+ }
2957
+ async executeRequest(operation) {
2958
+ try {
2959
+ return await operation();
2960
+ } catch (error) {
2961
+ const provider = this.oauthProvider;
2962
+ if (!provider || provider.preventAutoAuth === true || !isOAuthInteractionRequired(error)) {
2963
+ throw error;
2964
+ }
2965
+ await this.completeInteractiveAuthorization();
2966
+ return operation();
2967
+ }
2968
+ }
2969
+ /** Authenticate an already-connected server without requiring a 401 first. */
2970
+ async authenticate() {
2971
+ if (!this.connected || !this.streamableTransport) {
2972
+ throw new Error("MCP client is not connected");
2973
+ }
2974
+ await this.completeInteractiveAuthorization();
2975
+ }
2976
+ async discoverAuthorization() {
2977
+ if (!this.detectMixedAuth || !this.oauthProvider || this.hadAccessTokenAtConnect) {
2978
+ return this.authorizationCache;
2979
+ }
2980
+ if (this.authorizationDiscovery) return this.authorizationDiscovery;
2981
+ this.authorizationDiscovery = this.discoverMixedAuthorization();
2982
+ return this.authorizationDiscovery;
2983
+ }
2984
+ async discoverMixedAuthorization() {
2985
+ const controller = new AbortController();
2986
+ let timeout;
2987
+ const discoveryTimeout = new Promise((_, reject) => {
2988
+ timeout = setTimeout(() => {
2989
+ const error = new Error(
2990
+ `Mixed-auth metadata discovery timed out after ${MIXED_AUTH_DISCOVERY_TIMEOUT_MS}ms`
2991
+ );
2992
+ controller.abort(error);
2993
+ reject(error);
2994
+ }, MIXED_AUTH_DISCOVERY_TIMEOUT_MS);
2995
+ });
2996
+ const baseFetch = this.customFetch ?? globalThis.fetch.bind(globalThis);
2997
+ try {
2998
+ const metadata = await Promise.race([
2999
+ discoverOAuthProtectedResourceMetadata(
3000
+ this.baseUrl,
3001
+ { protocolVersion: this.negotiatedProtocolVersion },
3002
+ createDeadlineFetch(baseFetch, controller.signal)
3003
+ ),
3004
+ discoveryTimeout
3005
+ ]);
3006
+ this.authorizationCache = {
3007
+ mode: "mixed",
3008
+ authenticated: false,
3009
+ ...metadata.resource ? { resource: metadata.resource } : {},
3010
+ ...metadata.scopes_supported ? { scopesSupported: [...metadata.scopes_supported] } : {}
3011
+ };
3012
+ logger.info(
3013
+ "OAuth protected-resource metadata found after anonymous connection; server uses mixed auth"
3014
+ );
3015
+ } catch (error) {
3016
+ logger.debug("Mixed-auth metadata was not discovered:", error);
3017
+ } finally {
3018
+ if (timeout) clearTimeout(timeout);
3019
+ }
3020
+ return this.authorizationCache;
2804
3021
  }
2805
3022
  buildClientOptions() {
2806
3023
  return {
@@ -2907,6 +3124,16 @@ var HttpConnector = class extends BaseConnector {
2907
3124
  }
2908
3125
  const baseUrl = this.baseUrl;
2909
3126
  logger.debug(`Connecting to MCP implementation via HTTP: ${baseUrl}`);
3127
+ const oauthProvider = this.oauthProvider;
3128
+ if (oauthProvider) {
3129
+ try {
3130
+ this.hadAccessTokenAtConnect = Boolean(
3131
+ (await oauthProvider.tokens())?.access_token
3132
+ );
3133
+ } catch {
3134
+ this.hadAccessTokenAtConnect = false;
3135
+ }
3136
+ }
2910
3137
  try {
2911
3138
  await this.connectWithStreamableHttp(baseUrl);
2912
3139
  logger.debug("\u2705 Successfully connected via streamable HTTP");
@@ -3177,6 +3404,7 @@ var HttpConnector = class extends BaseConnector {
3177
3404
  }
3178
3405
  }
3179
3406
  await super.cleanupResources();
3407
+ this.authorizationDiscovery = null;
3180
3408
  }
3181
3409
  };
3182
3410
 
@@ -3258,6 +3486,7 @@ function createConnectorFromConfig(serverConfig, connectorOptions) {
3258
3486
  fetch: serverConfig.fetch,
3259
3487
  authToken: serverConfig.authToken,
3260
3488
  authProvider: serverConfig.authProvider,
3489
+ detectMixedAuth: serverConfig.detectMixedAuth,
3261
3490
  protocolNegotiation: serverConfig.protocolNegotiation,
3262
3491
  timeout: serverConfig.timeout,
3263
3492
  roots: serverConfig.roots,
@@ -3500,6 +3729,18 @@ var MCPConnection = class {
3500
3729
  get serverInfo() {
3501
3730
  return this.connector.serverInfo;
3502
3731
  }
3732
+ /** OAuth state discovered for this connection, when available. */
3733
+ get authorization() {
3734
+ return this.connector.authorization;
3735
+ }
3736
+ /** Discover optional OAuth metadata without delaying MCP readiness. */
3737
+ async discoverAuthorization() {
3738
+ return this.connector.discoverAuthorization();
3739
+ }
3740
+ /** Authenticate an already-connected mixed-auth server. */
3741
+ async authenticate() {
3742
+ await this.connector.authenticate();
3743
+ }
3503
3744
  /**
3504
3745
  * The negotiated protocol era for this session's connection:
3505
3746
  * `"legacy"` (2025-era) or `"modern"` (2026-07-28-era).
@@ -3532,7 +3773,8 @@ var MCPConnection = class {
3532
3773
  ...server ? { server } : {},
3533
3774
  capabilities,
3534
3775
  instructions: this.connector.instructions,
3535
- extensions
3776
+ extensions,
3777
+ ...this.authorization ? { authorization: this.authorization } : {}
3536
3778
  };
3537
3779
  }
3538
3780
  /**
@@ -3763,7 +4005,7 @@ var MCPConnection = class {
3763
4005
  };
3764
4006
 
3765
4007
  // src/core/base.ts
3766
- function isOAuthClientProvider(provider) {
4008
+ function isOAuthClientProvider2(provider) {
3767
4009
  return !!provider && typeof provider === "object" && "redirectUrl" in provider && "clientMetadata" in provider;
3768
4010
  }
3769
4011
  var BaseMCPClient = class {
@@ -3996,7 +4238,7 @@ var BaseMCPClient = class {
3996
4238
  ...serverConfig,
3997
4239
  authProvider: oauthProvider
3998
4240
  };
3999
- } else if ("authProvider" in serverConfig && serverConfig.authProvider && isOAuthClientProvider(serverConfig.authProvider)) {
4241
+ } else if ("authProvider" in serverConfig && serverConfig.authProvider && isOAuthClientProvider2(serverConfig.authProvider)) {
4000
4242
  oauthProvider = serverConfig.authProvider;
4001
4243
  }
4002
4244
  const openSession = async () => {
@@ -4336,6 +4578,7 @@ var BrowserMCPClient = class _BrowserMCPClient extends BaseMCPClient {
4336
4578
  fetch: configuredFetch,
4337
4579
  authToken,
4338
4580
  authProvider,
4581
+ detectMixedAuth,
4339
4582
  wrapTransport,
4340
4583
  clientOptions,
4341
4584
  protocolNegotiation,
@@ -4360,6 +4603,7 @@ var BrowserMCPClient = class _BrowserMCPClient extends BaseMCPClient {
4360
4603
  fetch: configuredFetch ?? globalThis.fetch.bind(globalThis),
4361
4604
  authToken,
4362
4605
  authProvider,
4606
+ detectMixedAuth,
4363
4607
  wrapTransport,
4364
4608
  clientOptions,
4365
4609
  onSampling: resolved.onSampling,
@@ -4470,6 +4714,7 @@ export {
4470
4714
  createOAuthProvider,
4471
4715
  detectFavicon,
4472
4716
  getPackageVersion,
4717
+ isOAuthInteractionRequired,
4473
4718
  isUnauthorized,
4474
4719
  logger,
4475
4720
  normalizeClientInfo,