@mcp-use/client 2.0.0-beta.8 → 2.0.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.
Files changed (91) hide show
  1. package/README.md +18 -19
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/auth/browser.d.ts +62 -6
  4. package/dist/auth/browser.d.ts.map +1 -1
  5. package/dist/auth/callback.d.ts.map +1 -1
  6. package/dist/auth/flow.d.ts.map +1 -1
  7. package/dist/auth/node.d.ts +115 -5
  8. package/dist/auth/node.d.ts.map +1 -1
  9. package/dist/auth/session-store.d.ts +7 -1
  10. package/dist/auth/session-store.d.ts.map +1 -1
  11. package/dist/auth/storage.d.ts +12 -3
  12. package/dist/auth/storage.d.ts.map +1 -1
  13. package/dist/code-mode/executor-e2b.d.ts.map +1 -1
  14. package/dist/core/base.d.ts +4 -8
  15. package/dist/core/base.d.ts.map +1 -1
  16. package/dist/core/browser.d.ts +14 -2
  17. package/dist/core/browser.d.ts.map +1 -1
  18. package/dist/core/config.d.ts +82 -20
  19. package/dist/core/config.d.ts.map +1 -1
  20. package/dist/core/node.d.ts +7 -10
  21. package/dist/core/node.d.ts.map +1 -1
  22. package/dist/core/session.d.ts +102 -25
  23. package/dist/core/session.d.ts.map +1 -1
  24. package/dist/index-browser.d.ts +1 -0
  25. package/dist/index-browser.d.ts.map +1 -1
  26. package/dist/index-browser.js +568 -163
  27. package/dist/index-browser.js.map +1 -1
  28. package/dist/index.d.ts +2 -2
  29. package/dist/index.d.ts.map +1 -1
  30. package/dist/index.js +407 -92
  31. package/dist/index.js.map +1 -1
  32. package/dist/react/McpClientProvider.d.ts +22 -10
  33. package/dist/react/McpClientProvider.d.ts.map +1 -1
  34. package/dist/react/index.d.ts +5 -2
  35. package/dist/react/index.d.ts.map +1 -1
  36. package/dist/react/index.js +1104 -368
  37. package/dist/react/index.js.map +1 -1
  38. package/dist/react/rpc-logger.d.ts +5 -0
  39. package/dist/react/rpc-logger.d.ts.map +1 -1
  40. package/dist/react/storage.d.ts +57 -10
  41. package/dist/react/storage.d.ts.map +1 -1
  42. package/dist/react/token-expiry.d.ts +9 -0
  43. package/dist/react/token-expiry.d.ts.map +1 -0
  44. package/dist/react/types.d.ts +134 -22
  45. package/dist/react/types.d.ts.map +1 -1
  46. package/dist/react/useMcp-helpers.d.ts.map +1 -1
  47. package/dist/react/useMcp-operations.d.ts +24 -6
  48. package/dist/react/useMcp-operations.d.ts.map +1 -1
  49. package/dist/react/useMcp.d.ts.map +1 -1
  50. package/dist/react/useMcpServerQueues.d.ts +36 -9
  51. package/dist/react/useMcpServerQueues.d.ts.map +1 -1
  52. package/dist/react/view/ViewRenderer.d.ts +12 -4
  53. package/dist/react/view/ViewRenderer.d.ts.map +1 -1
  54. package/dist/react/view/ext-apps-bridge.d.ts +1 -1
  55. package/dist/react/view/ext-apps-bridge.d.ts.map +1 -1
  56. package/dist/react/view/inject-openai-file-apis.d.ts.map +1 -1
  57. package/dist/react/view/parse-custom-props.d.ts +8 -0
  58. package/dist/react/view/parse-custom-props.d.ts.map +1 -1
  59. package/dist/react/view/resolve-view-resource.d.ts +10 -0
  60. package/dist/react/view/resolve-view-resource.d.ts.map +1 -1
  61. package/dist/react/view/sandbox-blob-url.d.ts +2 -0
  62. package/dist/react/view/sandbox-blob-url.d.ts.map +1 -1
  63. package/dist/react/view/types.d.ts +111 -4
  64. package/dist/react/view/types.d.ts.map +1 -1
  65. package/dist/react/view/view-detection.d.ts +18 -0
  66. package/dist/react/view/view-detection.d.ts.map +1 -1
  67. package/dist/react/view/view-host-policy.d.ts +61 -0
  68. package/dist/react/view/view-host-policy.d.ts.map +1 -0
  69. package/dist/sandbox.d.ts +2 -0
  70. package/dist/sandbox.d.ts.map +1 -0
  71. package/dist/sandbox.js +283 -0
  72. package/dist/sandbox.js.map +1 -0
  73. package/dist/telemetry/events.d.ts.map +1 -1
  74. package/dist/telemetry/tel-fetch.d.ts.map +1 -1
  75. package/dist/telemetry/telemetry.d.ts +5 -1
  76. package/dist/telemetry/telemetry.d.ts.map +1 -1
  77. package/dist/transport/base.d.ts +169 -34
  78. package/dist/transport/base.d.ts.map +1 -1
  79. package/dist/transport/connection-manager.d.ts +5 -1
  80. package/dist/transport/connection-manager.d.ts.map +1 -1
  81. package/dist/transport/http.d.ts +51 -2
  82. package/dist/transport/http.d.ts.map +1 -1
  83. package/dist/transport/stdio.d.ts +29 -1
  84. package/dist/transport/stdio.d.ts.map +1 -1
  85. package/dist/utils/elicitation.d.ts +4 -2
  86. package/dist/utils/elicitation.d.ts.map +1 -1
  87. package/dist/utils/logging.d.ts +1 -0
  88. package/dist/utils/logging.d.ts.map +1 -1
  89. package/dist/utils/version.d.ts +6 -0
  90. package/dist/utils/version.d.ts.map +1 -1
  91. package/package.json +9 -3
@@ -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.0.0-beta.7";
131
+ var VERSION = "2.0.0";
132
132
  function getPackageVersion() {
133
133
  return VERSION;
134
134
  }
@@ -148,16 +148,13 @@ var MCPAgentExecutionEvent = class extends BaseTelemetryEvent {
148
148
  return {
149
149
  // Core execution info
150
150
  execution_method: this.data.executionMethod,
151
- query: this.data.query,
152
151
  query_length: this.data.query.length,
153
152
  success: this.data.success,
154
153
  // Agent configuration
155
154
  model_provider: this.data.modelProvider,
156
155
  model_name: this.data.modelName,
157
156
  server_count: this.data.serverCount,
158
- server_identifiers: this.data.serverIdentifiers,
159
157
  total_tools_available: this.data.totalToolsAvailable,
160
- tools_available_names: this.data.toolsAvailableNames,
161
158
  max_steps_configured: this.data.maxStepsConfigured,
162
159
  memory_enabled: this.data.memoryEnabled,
163
160
  use_server_manager: this.data.useServerManager,
@@ -168,8 +165,6 @@ var MCPAgentExecutionEvent = class extends BaseTelemetryEvent {
168
165
  // Execution results (always include, even if null)
169
166
  steps_taken: this.data.stepsTaken ?? null,
170
167
  tools_used_count: this.data.toolsUsedCount ?? null,
171
- tools_used_names: this.data.toolsUsedNames ?? null,
172
- response: this.data.response ?? null,
173
168
  response_length: this.data.response ? this.data.response.length : null,
174
169
  execution_time_ms: this.data.executionTimeMs ?? null,
175
170
  error_type: this.data.errorType ?? null,
@@ -265,21 +260,72 @@ async function telFetch(url, init) {
265
260
  }
266
261
  var POSTHOG_HOST = "https://eu.i.posthog.com";
267
262
  var POSTHOG_API_KEY = "phc_lyTtbYwvkdSbrcMQNPiKiiRWrrM1seyKIMjycSvItEI";
268
- function capturePostHog(params) {
269
- const host = params.host ?? POSTHOG_HOST;
270
- const apiKey = params.apiKey ?? POSTHOG_API_KEY;
271
- return telFetch(`${host}/i/v0/e/`, {
272
- method: "POST",
273
- headers: { "Content-Type": "application/json" },
274
- keepalive: true,
275
- body: JSON.stringify({
263
+ var CONTENT_PROPERTY = /(^|_)(arguments?|args|body|command|headers?|location|message|query|response|secret|subject|token|uri|url|user_agent)(_|$)/i;
264
+ var IDENTIFYING_PROPERTY = /(^|_)(server_identifiers?|server_names?|servers|tool_names?|tools_(available|used)_names)(_|$)/i;
265
+ var AGGREGATE_PROPERTY = /(_count|_length|_duration(?:_ms)?|_time_ms|(^|_)num_[a-z0-9_]+)$/i;
266
+ function normalizePropertyKey(key) {
267
+ return key.replace(/([a-z0-9])([A-Z])/g, "$1_$2").replace(/[^a-z0-9_$]+/gi, "_").toLowerCase();
268
+ }
269
+ function sanitizeValue(value, seen) {
270
+ if (Array.isArray(value)) {
271
+ if (seen.has(value)) {
272
+ throw new TypeError("Cyclic telemetry properties are not supported");
273
+ }
274
+ seen.add(value);
275
+ const sanitized = value.map((item) => sanitizeValue(item, seen));
276
+ seen.delete(value);
277
+ return sanitized;
278
+ }
279
+ if (value !== null && typeof value === "object" && (Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null)) {
280
+ if (seen.has(value)) {
281
+ throw new TypeError("Cyclic telemetry properties are not supported");
282
+ }
283
+ seen.add(value);
284
+ const sanitized = sanitizeProperties(
285
+ value,
286
+ seen
287
+ );
288
+ seen.delete(value);
289
+ return sanitized;
290
+ }
291
+ return value;
292
+ }
293
+ function sanitizeProperties(properties, seen = /* @__PURE__ */ new WeakSet()) {
294
+ const sanitized = {};
295
+ for (const [key, value] of Object.entries(properties)) {
296
+ const normalizedKey = normalizePropertyKey(key);
297
+ if (AGGREGATE_PROPERTY.test(normalizedKey)) {
298
+ if (value === null || typeof value === "number") {
299
+ sanitized[key] = value;
300
+ }
301
+ continue;
302
+ }
303
+ if (IDENTIFYING_PROPERTY.test(normalizedKey) || CONTENT_PROPERTY.test(normalizedKey)) {
304
+ continue;
305
+ }
306
+ sanitized[key] = sanitizeValue(value, seen);
307
+ }
308
+ return sanitized;
309
+ }
310
+ async function capturePostHog(params) {
311
+ try {
312
+ const host = params.host ?? POSTHOG_HOST;
313
+ const apiKey = params.apiKey ?? POSTHOG_API_KEY;
314
+ const body = JSON.stringify({
276
315
  api_key: apiKey,
277
316
  event: params.event,
278
317
  distinct_id: params.distinctId,
279
- properties: params.properties,
318
+ properties: sanitizeProperties(params.properties),
280
319
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
281
- })
282
- });
320
+ });
321
+ await telFetch(`${host}/i/v0/e/`, {
322
+ method: "POST",
323
+ headers: { "Content-Type": "application/json" },
324
+ keepalive: true,
325
+ body
326
+ });
327
+ } catch {
328
+ }
283
329
  }
284
330
 
285
331
  // src/telemetry/telemetry.ts
@@ -589,6 +635,186 @@ setConnectorTelemetryTracker(
589
635
  (data) => Telemetry.getInstance().trackConnectorInit(data).catch(() => void 0)
590
636
  );
591
637
 
638
+ // src/auth/storage.ts
639
+ var AUTH_CRYPTO_DATABASE = "mcp-use-oauth-crypto";
640
+ var AUTH_CRYPTO_STORE = "keys";
641
+ var AUTH_CRYPTO_KEY = "aes-gcm-v1";
642
+ var textEncoder = new TextEncoder();
643
+ var textDecoder = new TextDecoder();
644
+ var LocalStorageKVStore = class {
645
+ fallback = /* @__PURE__ */ new Map();
646
+ keyPromise;
647
+ durable = true;
648
+ async get(key) {
649
+ if (!this.durable) return this.fallback.get(key) ?? null;
650
+ let stored;
651
+ try {
652
+ stored = localStorage.getItem(key);
653
+ } catch {
654
+ this.durable = false;
655
+ return this.fallback.get(key) ?? null;
656
+ }
657
+ if (stored === null) return null;
658
+ const envelope = parseEncryptedEnvelope(stored);
659
+ if (!envelope) {
660
+ await this.set(key, stored);
661
+ return stored;
662
+ }
663
+ try {
664
+ const cryptoKey = await this.getCryptoKey();
665
+ const plaintext = await globalThis.crypto.subtle.decrypt(
666
+ {
667
+ name: "AES-GCM",
668
+ iv: decodeBase64(envelope.iv),
669
+ additionalData: textEncoder.encode(key)
670
+ },
671
+ cryptoKey,
672
+ decodeBase64(envelope.ciphertext)
673
+ );
674
+ return textDecoder.decode(plaintext);
675
+ } catch {
676
+ await this.remove(key);
677
+ return null;
678
+ }
679
+ }
680
+ async set(key, value) {
681
+ if (!this.durable) {
682
+ this.fallback.set(key, value);
683
+ return;
684
+ }
685
+ try {
686
+ const cryptoKey = await this.getCryptoKey();
687
+ const iv = globalThis.crypto.getRandomValues(new Uint8Array(12));
688
+ const ciphertext = await globalThis.crypto.subtle.encrypt(
689
+ {
690
+ name: "AES-GCM",
691
+ iv,
692
+ additionalData: textEncoder.encode(key)
693
+ },
694
+ cryptoKey,
695
+ textEncoder.encode(value)
696
+ );
697
+ const envelope = {
698
+ v: 1,
699
+ alg: "A256GCM",
700
+ iv: encodeBase64(iv),
701
+ ciphertext: encodeBase64(new Uint8Array(ciphertext))
702
+ };
703
+ localStorage.setItem(key, JSON.stringify(envelope));
704
+ this.fallback.delete(key);
705
+ } catch {
706
+ this.durable = false;
707
+ try {
708
+ localStorage.removeItem(key);
709
+ } catch {
710
+ }
711
+ this.fallback.set(key, value);
712
+ }
713
+ }
714
+ remove(key) {
715
+ this.fallback.delete(key);
716
+ try {
717
+ localStorage.removeItem(key);
718
+ } catch {
719
+ this.durable = false;
720
+ }
721
+ }
722
+ keys() {
723
+ const out = new Set(this.fallback.keys());
724
+ if (this.durable) {
725
+ try {
726
+ for (let i = 0; i < localStorage.length; i++) {
727
+ const key = localStorage.key(i);
728
+ if (key) out.add(key);
729
+ }
730
+ } catch {
731
+ this.durable = false;
732
+ }
733
+ }
734
+ return [...out];
735
+ }
736
+ getCryptoKey() {
737
+ this.keyPromise ??= getOrCreateCryptoKey();
738
+ return this.keyPromise;
739
+ }
740
+ };
741
+ function parseEncryptedEnvelope(value) {
742
+ try {
743
+ const parsed = JSON.parse(value);
744
+ if (!parsed || typeof parsed !== "object" || !("v" in parsed) || parsed.v !== 1 || !("alg" in parsed) || parsed.alg !== "A256GCM" || !("iv" in parsed) || typeof parsed.iv !== "string" || !("ciphertext" in parsed) || typeof parsed.ciphertext !== "string") {
745
+ return void 0;
746
+ }
747
+ return parsed;
748
+ } catch {
749
+ return void 0;
750
+ }
751
+ }
752
+ async function getOrCreateCryptoKey() {
753
+ if (!globalThis.crypto?.subtle || typeof indexedDB === "undefined") {
754
+ throw new Error("Durable browser cryptography is unavailable");
755
+ }
756
+ const candidate = await globalThis.crypto.subtle.generateKey(
757
+ { name: "AES-GCM", length: 256 },
758
+ false,
759
+ ["encrypt", "decrypt"]
760
+ );
761
+ const database = await openCryptoDatabase();
762
+ try {
763
+ return await new Promise((resolve, reject) => {
764
+ const transaction = database.transaction(AUTH_CRYPTO_STORE, "readwrite");
765
+ const store = transaction.objectStore(AUTH_CRYPTO_STORE);
766
+ const request = store.get(AUTH_CRYPTO_KEY);
767
+ let selected;
768
+ request.onsuccess = () => {
769
+ selected = request.result;
770
+ if (!selected) {
771
+ selected = candidate;
772
+ store.put(candidate, AUTH_CRYPTO_KEY);
773
+ }
774
+ };
775
+ request.onerror = () => reject(request.error);
776
+ transaction.oncomplete = () => {
777
+ if (selected) resolve(selected);
778
+ else reject(new Error("OAuth encryption key was not initialized"));
779
+ };
780
+ transaction.onerror = () => reject(transaction.error);
781
+ transaction.onabort = () => reject(transaction.error);
782
+ });
783
+ } finally {
784
+ database.close();
785
+ }
786
+ }
787
+ function openCryptoDatabase() {
788
+ return new Promise((resolve, reject) => {
789
+ const request = indexedDB.open(AUTH_CRYPTO_DATABASE, 1);
790
+ request.onupgradeneeded = () => {
791
+ const database = request.result;
792
+ if (!database.objectStoreNames.contains(AUTH_CRYPTO_STORE)) {
793
+ database.createObjectStore(AUTH_CRYPTO_STORE);
794
+ }
795
+ };
796
+ request.onsuccess = () => resolve(request.result);
797
+ request.onerror = () => reject(request.error);
798
+ request.onblocked = () => reject(new Error("OAuth encryption database is blocked"));
799
+ });
800
+ }
801
+ function encodeBase64(bytes) {
802
+ let binary = "";
803
+ for (const byte of bytes) binary += String.fromCharCode(byte);
804
+ return btoa(binary);
805
+ }
806
+ function decodeBase64(value) {
807
+ const binary = atob(value);
808
+ const bytes = new Uint8Array(binary.length);
809
+ for (let index = 0; index < binary.length; index++) {
810
+ bytes[index] = binary.charCodeAt(index);
811
+ }
812
+ return bytes;
813
+ }
814
+
815
+ // src/auth/session-store.ts
816
+ import { validateClientMetadataUrl } from "@modelcontextprotocol/client";
817
+
592
818
  // src/auth/url.ts
593
819
  function sanitizeUrl(raw) {
594
820
  const abort = () => {
@@ -613,29 +839,7 @@ function sanitizeParam([k, v]) {
613
839
  return `${encodeURIComponent(k)}${v.length > 0 ? `=${encodeURIComponent(v)}` : ""}`;
614
840
  }
615
841
 
616
- // src/auth/storage.ts
617
- var LocalStorageKVStore = class {
618
- get(key) {
619
- return localStorage.getItem(key);
620
- }
621
- set(key, value) {
622
- localStorage.setItem(key, value);
623
- }
624
- remove(key) {
625
- localStorage.removeItem(key);
626
- }
627
- keys() {
628
- const out = [];
629
- for (let i = 0; i < localStorage.length; i++) {
630
- const k = localStorage.key(i);
631
- if (k) out.push(k);
632
- }
633
- return out;
634
- }
635
- };
636
-
637
842
  // src/auth/session-store.ts
638
- import { validateClientMetadataUrl } from "@modelcontextprotocol/client";
639
843
  var OAuthSessionStore = class _OAuthSessionStore {
640
844
  serverUrl;
641
845
  storageKeyPrefix;
@@ -741,29 +945,39 @@ var OAuthSessionStore = class _OAuthSessionStore {
741
945
  if (ctx) await this.store.set(this.credentialKey("tokens"), serialized);
742
946
  await this.store.remove(this.getKey("code_verifier"));
743
947
  await this.store.remove(this.getKey("last_auth_url"));
948
+ await this.store.remove(this.getKey("last_auth_callback_url"));
744
949
  }
745
950
  async clientInformation(ctx) {
951
+ if (!this.allowClientSecret) {
952
+ const registeredRedirectUri = await this.store.get(
953
+ this.getKey("client_info_redirect_uri")
954
+ );
955
+ if (registeredRedirectUri !== this.redirectUrl) {
956
+ await this.invalidateCredentials("registration");
957
+ console.info(
958
+ `[${this.storageKeyPrefix}] Re-registering browser OAuth client after its Inspector callback changed or could not be verified.`
959
+ );
960
+ return void 0;
961
+ }
962
+ }
746
963
  const stored = await this.readCredential("client_info", ctx);
747
964
  if (!stored) return void 0;
748
965
  const { key, value: clientInfo } = stored;
749
966
  try {
750
967
  if (!this.allowClientSecret && clientInfo.client_secret) {
751
- await this.store.remove(key);
752
- if (ctx) await this.store.remove(this.credentialKey("client_info"));
968
+ await this.invalidateCredentials("registration");
753
969
  console.warn(
754
- `[${this.storageKeyPrefix}] Removed OAuth client information containing a browser client_secret.`
970
+ `[${this.storageKeyPrefix}] Recovered stale browser OAuth credentials containing a client_secret.`
755
971
  );
756
972
  return void 0;
757
973
  }
758
974
  const storedRedirectUris = Array.isArray(clientInfo.redirect_uris) ? clientInfo.redirect_uris : [];
759
- const hasMatchingRedirect = storedRedirectUris.length === 0 || storedRedirectUris.includes(this.redirectUrl);
975
+ const hasMatchingRedirect = storedRedirectUris.length === 0 && this.allowClientSecret || storedRedirectUris.includes(this.redirectUrl);
760
976
  if (!hasMatchingRedirect) {
761
977
  console.info(
762
- `[${this.storageKeyPrefix}] Invalidating cached OAuth client info due to redirect URI mismatch.`
978
+ `[${this.storageKeyPrefix}] Recovering cached OAuth credentials after a redirect URI change.`
763
979
  );
764
- await this.store.remove(key);
765
- await this.store.remove(this.credentialKey("tokens", ctx));
766
- await this.store.remove(this.getKey("last_auth_url"));
980
+ await this.invalidateCredentials("registration");
767
981
  return void 0;
768
982
  }
769
983
  return clientInfo;
@@ -781,11 +995,20 @@ var OAuthSessionStore = class _OAuthSessionStore {
781
995
  "Browser OAuth clients must be public clients; client_secret persistence is not allowed."
782
996
  );
783
997
  }
784
- const serialized = JSON.stringify(clientInformation);
998
+ const persistedClientInformation = !this.allowClientSecret && (!("redirect_uris" in clientInformation) || !Array.isArray(
999
+ clientInformation.redirect_uris
1000
+ ) || clientInformation.redirect_uris.length === 0) ? { ...clientInformation, redirect_uris: [this.redirectUrl] } : clientInformation;
1001
+ const serialized = JSON.stringify(persistedClientInformation);
785
1002
  await this.store.set(this.credentialKey("client_info", ctx), serialized);
786
1003
  if (ctx) {
787
1004
  await this.store.set(this.credentialKey("client_info"), serialized);
788
1005
  }
1006
+ if (!this.allowClientSecret) {
1007
+ await this.store.set(
1008
+ this.getKey("client_info_redirect_uri"),
1009
+ this.redirectUrl
1010
+ );
1011
+ }
789
1012
  }
790
1013
  async saveCodeVerifier(codeVerifier) {
791
1014
  await this.store.set(this.getKey("code_verifier"), codeVerifier);
@@ -810,11 +1033,22 @@ var OAuthSessionStore = class _OAuthSessionStore {
810
1033
  }
811
1034
  };
812
1035
  switch (scope) {
1036
+ case "registration":
1037
+ await removeCredentialKeys("tokens");
1038
+ await removeCredentialKeys("client_info");
1039
+ await this.store.remove(this.getKey("code_verifier"));
1040
+ await this.store.remove(this.getKey("last_auth_url"));
1041
+ await this.store.remove(this.getKey("last_auth_callback_url"));
1042
+ await this.store.remove(this.getKey("client_info_redirect_uri"));
1043
+ await this.store.remove(this.getKey("token_endpoint"));
1044
+ break;
813
1045
  case "all":
814
1046
  await removeCredentialKeys("tokens");
815
1047
  await removeCredentialKeys("client_info");
816
1048
  await this.store.remove(this.getKey("code_verifier"));
817
1049
  await this.store.remove(this.getKey("last_auth_url"));
1050
+ await this.store.remove(this.getKey("last_auth_callback_url"));
1051
+ await this.store.remove(this.getKey("client_info_redirect_uri"));
818
1052
  await this.store.remove(this.getKey("discovery_state"));
819
1053
  await this.store.remove(this.getKey("token_endpoint"));
820
1054
  break;
@@ -864,7 +1098,7 @@ var OAuthSessionStore = class _OAuthSessionStore {
864
1098
  */
865
1099
  async storeAuthorizationState(authorizationUrl, opts = {}) {
866
1100
  const state = globalThis.crypto.randomUUID();
867
- const stateKey = `${this.storageKeyPrefix}:state_${state}`;
1101
+ const stateKey = `${this.storageKeyPrefix}_${this.serverUrlHash}_state_${state}`;
868
1102
  const stateData = {
869
1103
  serverUrlHash: this.serverUrlHash,
870
1104
  expiry: Date.now() + 1e3 * 60 * 10,
@@ -884,6 +1118,10 @@ var OAuthSessionStore = class _OAuthSessionStore {
884
1118
  authorizationUrl.searchParams.set("state", state);
885
1119
  const sanitizedAuthUrl = sanitizeUrl(authorizationUrl.toString());
886
1120
  await this.store.set(stateKey, JSON.stringify(stateData));
1121
+ await this.store.set(
1122
+ this.getKey("last_auth_callback_url"),
1123
+ this.redirectUrl
1124
+ );
887
1125
  await this.store.set(this.getKey("last_auth_url"), sanitizedAuthUrl);
888
1126
  return sanitizedAuthUrl;
889
1127
  }
@@ -913,16 +1151,30 @@ async function serializeBody(body) {
913
1151
  if (body instanceof Blob) return await body.text();
914
1152
  return body;
915
1153
  }
1154
+ function trimTrailingSlashes(value) {
1155
+ let end = value.length;
1156
+ while (end > 0 && value.charCodeAt(end - 1) === 47) {
1157
+ end--;
1158
+ }
1159
+ return value.slice(0, end);
1160
+ }
916
1161
  var BrowserOAuthClientProvider = class {
1162
+ /** Protected MCP server URL associated with this provider. */
917
1163
  serverUrl;
1164
+ /** Pre-registered public client information, when configured. */
918
1165
  staticClientInfo;
919
1166
  session;
1167
+ storage;
920
1168
  // Browser-only state
1169
+ /** Whether initial connection waits for explicit authentication. */
921
1170
  preventAutoAuth;
922
1171
  useRedirectFlow;
923
1172
  oauthProxyUrl;
924
1173
  connectionUrl;
925
1174
  proxyOAuthRequests;
1175
+ lastAttemptedAuthUrl = null;
1176
+ authorizationPending = false;
1177
+ /** Callback invoked immediately before an authorization popup opens. */
926
1178
  onPopupWindow;
927
1179
  constructor(serverUrl, options = {}) {
928
1180
  if (options.staticClientInfo?.client_secret) {
@@ -931,10 +1183,11 @@ var BrowserOAuthClientProvider = class {
931
1183
  );
932
1184
  }
933
1185
  this.serverUrl = serverUrl;
1186
+ this.storage = new LocalStorageKVStore();
934
1187
  this.session = new OAuthSessionStore(
935
1188
  serverUrl,
936
1189
  { ...options, allowClientSecret: false },
937
- new LocalStorageKVStore()
1190
+ this.storage
938
1191
  );
939
1192
  this.preventAutoAuth = options.preventAutoAuth;
940
1193
  this.useRedirectFlow = options.useRedirectFlow;
@@ -945,33 +1198,54 @@ var BrowserOAuthClientProvider = class {
945
1198
  this.onPopupWindow = options.onPopupWindow;
946
1199
  }
947
1200
  // --- Identity / key fields exposed for callback handling ---
1201
+ /** Prefix used for persisted OAuth keys. */
948
1202
  get storageKeyPrefix() {
949
1203
  return this.session.storageKeyPrefix;
950
1204
  }
1205
+ /** Stable hash used to namespace storage for this server. */
951
1206
  get serverUrlHash() {
952
1207
  return this.session.serverUrlHash;
953
1208
  }
1209
+ /** Human-readable OAuth client name. */
954
1210
  get clientName() {
955
1211
  return this.session.clientName;
956
1212
  }
1213
+ /** Public website describing the OAuth client. */
957
1214
  get clientUri() {
958
1215
  return this.session.clientUri;
959
1216
  }
1217
+ /** Public OAuth client logo URL. */
960
1218
  get logoUri() {
961
1219
  return this.session.logoUri;
962
1220
  }
1221
+ /** OAuth redirect URI. */
963
1222
  get callbackUrl() {
964
1223
  return this.session.callbackUrl;
965
1224
  }
1225
+ /** Space-delimited OAuth scopes requested by the client. */
966
1226
  get scope() {
967
1227
  return this.session.scope;
968
1228
  }
969
1229
  get clientMetadataUrl() {
970
1230
  return this.session.clientMetadataUrl;
971
1231
  }
1232
+ /**
1233
+ * Returns a provider-scoped storage key.
1234
+ *
1235
+ * @param keySuffix - Suffix identifying the stored value.
1236
+ * @returns Namespaced storage key.
1237
+ */
972
1238
  getKey(keySuffix) {
973
1239
  return this.session.getKey(keySuffix);
974
1240
  }
1241
+ /** Whether an authorization flow is awaiting completion. */
1242
+ get hasPendingFlow() {
1243
+ return this.authorizationPending;
1244
+ }
1245
+ /** Marks the current authorization flow as complete. */
1246
+ markFlowComplete() {
1247
+ this.authorizationPending = false;
1248
+ }
975
1249
  /**
976
1250
  * Re-anchor an SDK-derived OAuth discovery URL from the MCP connection
977
1251
  * (proxy) origin onto the actual MCP server.
@@ -999,8 +1273,8 @@ var BrowserOAuthClientProvider = class {
999
1273
  const [doc, ...suffixParts] = rest.split("/");
1000
1274
  if (!doc) return url;
1001
1275
  const suffix = suffixParts.length ? `/${suffixParts.join("/")}` : "";
1002
- const connectionPath = connection.pathname.replace(/\/+$/, "");
1003
- const targetPath = target.pathname.replace(/\/+$/, "");
1276
+ const connectionPath = trimTrailingSlashes(connection.pathname);
1277
+ const targetPath = trimTrailingSlashes(target.pathname);
1004
1278
  const newSuffix = suffix && suffix === connectionPath ? targetPath : suffix;
1005
1279
  return `${target.origin}/.well-known/${doc}${newSuffix}${requested.search}`;
1006
1280
  } catch {
@@ -1019,20 +1293,19 @@ var BrowserOAuthClientProvider = class {
1019
1293
  * therefore never alters fetch behavior for other servers, other
1020
1294
  * connections, or the rest of the page.
1021
1295
  *
1022
- * When this provider is not configured to proxy OAuth requests (no
1023
- * `oauthProxyUrl`, or `proxyOAuthRequests` disabled), the provided
1024
- * `baseFetch` is returned as-is (or `undefined` when none is given, letting
1025
- * the SDK fall back to its default `fetch`).
1296
+ * OAuth metadata is always fetched with `cache: "no-store"`, including in
1297
+ * direct mode. Authorization servers commonly vary CORS headers by Origin;
1298
+ * bypassing the browser HTTP cache prevents a revalidated response cached
1299
+ * for another localhost origin from poisoning discovery. When OAuth proxying
1300
+ * is disabled or no `oauthProxyUrl` is configured, all requests still go
1301
+ * directly to their original URLs.
1026
1302
  *
1027
1303
  * @param baseFetch - The fetch used for non-OAuth requests and for the
1028
1304
  * underlying proxy calls. Defaults to the global `fetch`.
1029
1305
  */
1030
1306
  getProxyFetch(baseFetch) {
1031
- if (!this.proxyOAuthRequests || !this.oauthProxyUrl) {
1032
- return baseFetch;
1033
- }
1034
1307
  const base = baseFetch ?? globalThis.fetch.bind(globalThis);
1035
- const oauthProxyUrl = this.oauthProxyUrl;
1308
+ const oauthProxyUrl = this.proxyOAuthRequests && this.oauthProxyUrl ? this.oauthProxyUrl : void 0;
1036
1309
  const discoveredEndpoints = /* @__PURE__ */ new Set();
1037
1310
  let restoredDiscovery = false;
1038
1311
  return async (input, init) => {
@@ -1045,6 +1318,12 @@ var BrowserOAuthClientProvider = class {
1045
1318
  return await base(input, init);
1046
1319
  }
1047
1320
  const isMetadata = pathname.includes("/.well-known/");
1321
+ if (!oauthProxyUrl) {
1322
+ return await base(
1323
+ isMetadata ? url : input,
1324
+ isMetadata ? { ...init, cache: "no-store" } : init
1325
+ );
1326
+ }
1048
1327
  if (!restoredDiscovery) {
1049
1328
  restoredDiscovery = true;
1050
1329
  const metadata = (await this.discoveryState())?.authorizationServerMetadata;
@@ -1079,7 +1358,8 @@ var BrowserOAuthClientProvider = class {
1079
1358
  if (isMetadata) {
1080
1359
  const response2 = await base(proxyEndpoint, {
1081
1360
  ...init,
1082
- method: "GET"
1361
+ method: "GET",
1362
+ cache: "no-store"
1083
1363
  });
1084
1364
  try {
1085
1365
  const metadata = await response2.clone().json();
@@ -1097,23 +1377,40 @@ var BrowserOAuthClientProvider = class {
1097
1377
  }
1098
1378
  return response2;
1099
1379
  }
1100
- const body = init?.body ? await serializeBody(init.body) : void 0;
1380
+ const inputRequest = input instanceof Request ? input : void 0;
1381
+ const method = init?.method ?? inputRequest?.method ?? "POST";
1382
+ const requestHeaders = init?.headers ?? inputRequest?.headers;
1383
+ let body;
1384
+ if (init?.body !== void 0 && init.body !== null) {
1385
+ body = await serializeBody(init.body);
1386
+ } else if (inputRequest?.body && method !== "GET" && method !== "HEAD") {
1387
+ body = await inputRequest.clone().text();
1388
+ }
1101
1389
  const response = await base(proxyEndpoint, {
1102
1390
  method: "POST",
1103
1391
  headers: { "Content-Type": "application/json" },
1104
1392
  body: JSON.stringify({
1105
1393
  serverUrl: this.serverUrl,
1106
1394
  url,
1107
- method: init?.method || "POST",
1108
- headers: init?.headers ? Object.fromEntries(new Headers(init.headers)) : {},
1395
+ method,
1396
+ headers: requestHeaders ? Object.fromEntries(new Headers(requestHeaders)) : {},
1109
1397
  body
1110
1398
  })
1111
1399
  });
1112
1400
  const data = await response.json();
1401
+ if (!response.ok || typeof data.status !== "number") {
1402
+ return new Response(JSON.stringify(data), {
1403
+ status: response.status,
1404
+ statusText: response.statusText,
1405
+ headers: response.headers
1406
+ });
1407
+ }
1113
1408
  return new Response(JSON.stringify(data.body), {
1114
1409
  status: data.status,
1115
- statusText: data.statusText,
1116
- headers: new Headers(data.headers)
1410
+ statusText: typeof data.statusText === "string" ? data.statusText : void 0,
1411
+ headers: new Headers(
1412
+ data.headers && typeof data.headers === "object" ? data.headers : void 0
1413
+ )
1117
1414
  });
1118
1415
  };
1119
1416
  }
@@ -1128,15 +1425,41 @@ var BrowserOAuthClientProvider = class {
1128
1425
  return this.session.tokens(ctx);
1129
1426
  }
1130
1427
  saveTokens(tokens, ctx) {
1428
+ this.lastAttemptedAuthUrl = null;
1429
+ this.authorizationPending = false;
1131
1430
  return this.session.saveTokens(tokens, ctx);
1132
1431
  }
1432
+ /**
1433
+ * Returns the configured or dynamically registered OAuth client information.
1434
+ *
1435
+ * @param ctx - Optional registration context.
1436
+ * @returns OAuth client information, or `undefined` when not registered.
1437
+ */
1133
1438
  async clientInformation(ctx) {
1134
1439
  if (this.staticClientInfo) return this.staticClientInfo;
1135
1440
  return this.session.clientInformation(ctx);
1136
1441
  }
1442
+ /**
1443
+ * Persists public OAuth client registration information.
1444
+ *
1445
+ * Static client configuration takes precedence, and browser providers discard
1446
+ * any client secret returned for a public client.
1447
+ *
1448
+ * @param clientInformation - Registration information to save.
1449
+ * @param ctx - Optional registration context.
1450
+ */
1137
1451
  async saveClientInformation(clientInformation, ctx) {
1138
1452
  if (this.staticClientInfo) return;
1139
- return this.session.saveClientInformation(clientInformation, ctx);
1453
+ const { client_secret: discardedClientSecret, ...publicClientInformation } = clientInformation;
1454
+ if (discardedClientSecret) {
1455
+ console.info(
1456
+ `[${this.storageKeyPrefix}] Discarded client_secret returned for a public browser OAuth client.`
1457
+ );
1458
+ }
1459
+ return this.session.saveClientInformation(
1460
+ publicClientInformation,
1461
+ ctx
1462
+ );
1140
1463
  }
1141
1464
  codeVerifier() {
1142
1465
  return this.session.codeVerifier();
@@ -1185,20 +1508,26 @@ var BrowserOAuthClientProvider = class {
1185
1508
  * use `redirectToAuthorization` for that.
1186
1509
  */
1187
1510
  async prepareAuthorizationUrl(authorizationUrl) {
1188
- return this.session.storeAuthorizationState(authorizationUrl, {
1189
- extraProviderOptions: {
1190
- oauthProxyUrl: this.oauthProxyUrl,
1191
- ...this.clientMetadataUrl ? { clientMetadataUrl: this.clientMetadataUrl } : {},
1192
- ...this.staticClientInfo ? { staticClientInfo: this.staticClientInfo } : {},
1193
- ...this.scope ? { scope: this.scope } : {}
1194
- },
1195
- flowType: this.useRedirectFlow ? "redirect" : "popup",
1196
- returnUrl: typeof window !== "undefined" ? window.location.href : void 0
1197
- });
1511
+ const prepared = await this.session.storeAuthorizationState(
1512
+ authorizationUrl,
1513
+ {
1514
+ extraProviderOptions: {
1515
+ oauthProxyUrl: this.oauthProxyUrl,
1516
+ ...this.clientMetadataUrl ? { clientMetadataUrl: this.clientMetadataUrl } : {},
1517
+ ...this.staticClientInfo ? { staticClientInfo: this.staticClientInfo } : {},
1518
+ ...this.scope ? { scope: this.scope } : {}
1519
+ },
1520
+ flowType: this.useRedirectFlow ? "redirect" : "popup",
1521
+ returnUrl: typeof window !== "undefined" ? window.location.href : void 0
1522
+ }
1523
+ );
1524
+ this.lastAttemptedAuthUrl = prepared;
1525
+ this.authorizationPending = true;
1526
+ return prepared;
1198
1527
  }
1199
1528
  /**
1200
1529
  * Redirects the user agent to the authorization URL, storing necessary state.
1201
- * @param authorizationUrl The fully constructed authorization URL from the SDK.
1530
+ * @param authorizationUrl - The fully constructed authorization URL from the SDK.
1202
1531
  */
1203
1532
  async redirectToAuthorization(authorizationUrl) {
1204
1533
  const sanitizedAuthUrl = await this.prepareAuthorizationUrl(authorizationUrl);
@@ -1246,40 +1575,27 @@ var BrowserOAuthClientProvider = class {
1246
1575
  * Retrieves the last URL passed to `redirectToAuthorization`. Useful for manual fallback.
1247
1576
  */
1248
1577
  getLastAttemptedAuthUrl() {
1249
- const storedUrl = localStorage.getItem(this.getKey("last_auth_url"));
1250
- if (!storedUrl) return null;
1251
- return sanitizeUrl(storedUrl);
1578
+ return this.lastAttemptedAuthUrl;
1252
1579
  }
1580
+ /**
1581
+ * Removes OAuth state stored for this server.
1582
+ *
1583
+ * @returns The number of storage entries removed.
1584
+ */
1253
1585
  clearStorage() {
1586
+ this.lastAttemptedAuthUrl = null;
1587
+ this.authorizationPending = false;
1254
1588
  const prefixPattern = `${this.storageKeyPrefix}_${this.serverUrlHash}_`;
1255
- const statePattern = `${this.storageKeyPrefix}:state_`;
1256
1589
  const keysToRemove = [];
1257
1590
  let count = 0;
1258
- for (let i = 0; i < localStorage.length; i++) {
1259
- const key = localStorage.key(i);
1260
- if (!key) continue;
1591
+ for (const key of this.storage.keys()) {
1261
1592
  if (key.startsWith(prefixPattern)) {
1262
1593
  keysToRemove.push(key);
1263
- } else if (key.startsWith(statePattern)) {
1264
- try {
1265
- const item = localStorage.getItem(key);
1266
- if (item) {
1267
- const state = JSON.parse(item);
1268
- if (state.serverUrlHash === this.serverUrlHash) {
1269
- keysToRemove.push(key);
1270
- }
1271
- }
1272
- } catch (e) {
1273
- console.warn(
1274
- `[${this.storageKeyPrefix}] Error parsing state key ${key} during clearStorage:`,
1275
- e
1276
- );
1277
- }
1278
1594
  }
1279
1595
  }
1280
1596
  const uniqueKeysToRemove = [...new Set(keysToRemove)];
1281
1597
  uniqueKeysToRemove.forEach((key) => {
1282
- localStorage.removeItem(key);
1598
+ this.storage.remove(key);
1283
1599
  count++;
1284
1600
  });
1285
1601
  return count;
@@ -1487,20 +1803,14 @@ function renderResult(title, message, error, returnUrl) {
1487
1803
  }
1488
1804
  document.body.appendChild(container);
1489
1805
  }
1490
- function findStoredState(state) {
1491
- const defaultKey = `mcp:auth:state_${state}`;
1492
- let key = localStorage.getItem(defaultKey) ? defaultKey : null;
1493
- if (!key) {
1494
- const suffix = `:state_${state}`;
1495
- for (let index = 0; index < localStorage.length; index++) {
1496
- const candidate = localStorage.key(index);
1497
- if (candidate?.endsWith(suffix)) {
1498
- key = candidate;
1499
- break;
1500
- }
1501
- }
1502
- }
1503
- const serialized = key ? localStorage.getItem(key) : null;
1806
+ async function findStoredState(state) {
1807
+ const store = new LocalStorageKVStore();
1808
+ const legacySuffix = `:state_${state}`;
1809
+ const scopedSuffix = `_state_${state}`;
1810
+ const key = (await store.keys()).find(
1811
+ (candidate) => candidate.endsWith(legacySuffix) || candidate.endsWith(scopedSuffix)
1812
+ );
1813
+ const serialized = key ? await store.get(key) : null;
1504
1814
  if (!key || !serialized) {
1505
1815
  throw new Error(`Invalid or expired OAuth state "${state}".`);
1506
1816
  }
@@ -1508,10 +1818,10 @@ function findStoredState(state) {
1508
1818
  try {
1509
1819
  value = JSON.parse(serialized);
1510
1820
  } catch {
1511
- localStorage.removeItem(key);
1821
+ await store.remove(key);
1512
1822
  throw new Error("Failed to parse stored OAuth state.");
1513
1823
  }
1514
- return { key, value };
1824
+ return { key, value, store };
1515
1825
  }
1516
1826
  function redirectWithError(returnUrl, message) {
1517
1827
  const url = new URL(returnUrl);
@@ -1570,17 +1880,19 @@ async function completeAuthorization() {
1570
1880
  const callbackParams = new URLSearchParams(window.location.search);
1571
1881
  const state = callbackParams.get("state");
1572
1882
  let stateKey = null;
1883
+ let stateStore = null;
1573
1884
  let storedState = null;
1574
1885
  let provider = null;
1575
1886
  try {
1576
1887
  if (!state) {
1577
1888
  throw new Error("OAuth callback is missing the state parameter.");
1578
1889
  }
1579
- const stored = findStoredState(state);
1890
+ const stored = await findStoredState(state);
1580
1891
  stateKey = stored.key;
1892
+ stateStore = stored.store;
1581
1893
  storedState = stored.value;
1582
1894
  if (!storedState.expiry || storedState.expiry < Date.now()) {
1583
- localStorage.removeItem(stateKey);
1895
+ await stateStore.remove(stateKey);
1584
1896
  throw new Error(
1585
1897
  "OAuth state has expired. Please start authentication again."
1586
1898
  );
@@ -1595,7 +1907,7 @@ async function completeAuthorization() {
1595
1907
  fetch: provider.getProxyFetch()
1596
1908
  });
1597
1909
  await transport.finishAuth(callbackParams);
1598
- localStorage.removeItem(stateKey);
1910
+ await stateStore.remove(stateKey);
1599
1911
  signalResult(true, void 0, storedState, {
1600
1912
  state,
1601
1913
  serverUrlHash: storedState.serverUrlHash
@@ -1603,8 +1915,12 @@ async function completeAuthorization() {
1603
1915
  } catch (error) {
1604
1916
  const message = error instanceof Error ? error.message : String(error);
1605
1917
  console.error("[mcp-callback] OAuth callback failed:", error);
1606
- if (stateKey) localStorage.removeItem(stateKey);
1607
- if (provider) localStorage.removeItem(provider.getKey("last_auth_url"));
1918
+ if (stateKey && stateStore) await stateStore.remove(stateKey);
1919
+ if (provider) {
1920
+ await (stateStore ?? new LocalStorageKVStore()).remove(
1921
+ provider.getKey("last_auth_url")
1922
+ );
1923
+ }
1608
1924
  signalResult(false, message, storedState, {
1609
1925
  state,
1610
1926
  serverUrlHash: storedState?.serverUrlHash
@@ -1646,11 +1962,12 @@ async function completeOAuthFlow(provider, serverUrl, options = {}) {
1646
1962
  throw new Error(`Unexpected OAuth auth() result: ${result}`);
1647
1963
  }
1648
1964
  }
1649
- if (typeof flowProvider.getAuthorizationCode === "function") {
1650
- const code = await flowProvider.getAuthorizationCode();
1965
+ if (typeof flowProvider.getAuthorizationResponse === "function" || typeof flowProvider.getAuthorizationCode === "function") {
1966
+ const response = typeof flowProvider.getAuthorizationResponse === "function" ? await flowProvider.getAuthorizationResponse() : { code: await flowProvider.getAuthorizationCode() };
1651
1967
  await auth(provider, {
1652
1968
  serverUrl,
1653
- authorizationCode: code,
1969
+ authorizationCode: response.code,
1970
+ ...response.iss !== void 0 ? { iss: response.iss } : {},
1654
1971
  fetchFn
1655
1972
  });
1656
1973
  return;
@@ -1664,6 +1981,8 @@ async function waitForBrowserAuthComplete(provider, timeoutMs) {
1664
1981
  );
1665
1982
  }
1666
1983
  if (provider.useRedirectFlow) {
1984
+ await new Promise(() => {
1985
+ });
1667
1986
  return;
1668
1987
  }
1669
1988
  const tokensKey = provider.getKey?.("tokens");
@@ -1680,25 +1999,29 @@ async function waitForBrowserAuthComplete(provider, timeoutMs) {
1680
1999
  } catch {
1681
2000
  }
1682
2001
  }
1683
- const result = await runAuthPopup({
1684
- popup: null,
1685
- state,
1686
- tokensKey,
1687
- timeoutMs
1688
- });
1689
- switch (result.kind) {
1690
- case "success":
1691
- return;
1692
- case "cancelled":
1693
- throw new Error("OAuth authentication was cancelled.");
1694
- case "timeout":
1695
- throw new Error(
1696
- `OAuth callback not received within ${timeoutMs}ms. Ensure /oauth/callback calls onMcpAuthorization().`
1697
- );
1698
- case "error":
1699
- throw new Error(result.error);
1700
- default:
1701
- throw new Error("Unexpected OAuth popup result");
2002
+ try {
2003
+ const result = await runAuthPopup({
2004
+ popup: null,
2005
+ state,
2006
+ tokensKey,
2007
+ timeoutMs
2008
+ });
2009
+ switch (result.kind) {
2010
+ case "success":
2011
+ return;
2012
+ case "cancelled":
2013
+ throw new Error("OAuth authentication was cancelled.");
2014
+ case "timeout":
2015
+ throw new Error(
2016
+ `OAuth callback not received within ${timeoutMs}ms. Ensure /oauth/callback calls onMcpAuthorization().`
2017
+ );
2018
+ case "error":
2019
+ throw new Error(result.error);
2020
+ default:
2021
+ throw new Error("Unexpected OAuth popup result");
2022
+ }
2023
+ } finally {
2024
+ provider.markFlowComplete?.();
1702
2025
  }
1703
2026
  }
1704
2027
 
@@ -1769,6 +2092,11 @@ var BaseConnector = class {
1769
2092
  notificationHandlers = [];
1770
2093
  rootsCache = [];
1771
2094
  activeProgressHandlers = /* @__PURE__ */ new Set();
2095
+ /**
2096
+ * Creates a connector with shared SDK and callback options.
2097
+ *
2098
+ * @param opts - Connector initialization options.
2099
+ */
1772
2100
  constructor(opts = {}) {
1773
2101
  this.opts = opts;
1774
2102
  if (opts.roots) {
@@ -1951,7 +2279,9 @@ var BaseConnector = class {
1951
2279
  }
1952
2280
  }
1953
2281
  /**
1954
- * Get the current roots.
2282
+ * Returns the roots currently advertised to the server.
2283
+ *
2284
+ * @returns A copy of the configured roots.
1955
2285
  */
1956
2286
  getRoots() {
1957
2287
  return [...this.rootsCache];
@@ -2020,7 +2350,11 @@ var BaseConnector = class {
2020
2350
  "setupElicitationHandler: Elicitation handler registered successfully"
2021
2351
  );
2022
2352
  }
2023
- /** Disconnect and release resources. */
2353
+ /**
2354
+ * Disconnects the SDK client and releases transport resources.
2355
+ *
2356
+ * @returns A promise that resolves after cleanup completes.
2357
+ */
2024
2358
  async disconnect() {
2025
2359
  if (!this.connected) {
2026
2360
  logger.debug("Not connected to MCP implementation");
@@ -2031,7 +2365,7 @@ var BaseConnector = class {
2031
2365
  this.connected = false;
2032
2366
  logger.debug("Disconnected from MCP implementation");
2033
2367
  }
2034
- /** Check if the client is connected */
2368
+ /** Whether an SDK client currently exists for this connector. */
2035
2369
  get isClientConnected() {
2036
2370
  return this.client != null;
2037
2371
  }
@@ -2041,6 +2375,10 @@ var BaseConnector = class {
2041
2375
  * In the SDK, `Client.connect(transport)` automatically performs the
2042
2376
  * protocol‑level `initialize` handshake, so we only need to cache the list of
2043
2377
  * tools and expose some server info.
2378
+ *
2379
+ * @param defaultRequestOptions - Options used while fetching the initial tool list.
2380
+ * @returns The capabilities advertised by the server.
2381
+ * @throws When {@link BaseConnector.connect} has not completed.
2044
2382
  */
2045
2383
  async initialize(defaultRequestOptions = this.opts.defaultRequestOptions ?? {}) {
2046
2384
  if (!this.client) {
@@ -2078,18 +2416,22 @@ var BaseConnector = class {
2078
2416
  logger.debug("Server info:", serverInfo);
2079
2417
  return capabilities;
2080
2418
  }
2081
- /** Lazily expose the cached tools list. */
2419
+ /**
2420
+ * Returns the tool list cached during initialization.
2421
+ *
2422
+ * @throws When {@link BaseConnector.initialize} has not completed.
2423
+ */
2082
2424
  get tools() {
2083
2425
  if (!this.toolsCache) {
2084
2426
  throw new Error("MCP client is not initialized; call initialize() first");
2085
2427
  }
2086
2428
  return this.toolsCache;
2087
2429
  }
2088
- /** Expose cached server capabilities. */
2430
+ /** Capabilities cached during initialization, or an empty object. */
2089
2431
  get serverCapabilities() {
2090
2432
  return this.capabilitiesCache || {};
2091
2433
  }
2092
- /** Expose cached server info. */
2434
+ /** Server identity cached during initialization, or `null`. */
2093
2435
  get serverInfo() {
2094
2436
  return this.serverInfoCache;
2095
2437
  }
@@ -2110,7 +2452,15 @@ var BaseConnector = class {
2110
2452
  get negotiatedProtocolVersion() {
2111
2453
  return this.client?.getNegotiatedProtocolVersion?.();
2112
2454
  }
2113
- /** Call a tool on the server. */
2455
+ /**
2456
+ * Calls a tool on the connected server.
2457
+ *
2458
+ * @param name - Tool name.
2459
+ * @param args - Tool arguments.
2460
+ * @param options - Per-request timeout, cancellation, and progress options.
2461
+ * @returns The tool result returned by the server.
2462
+ * @throws When the connector is not connected or the tool call fails.
2463
+ */
2114
2464
  async callTool(name, args, options) {
2115
2465
  if (!this.client) {
2116
2466
  throw new Error("MCP client is not connected");
@@ -2235,7 +2585,13 @@ var BaseConnector = class {
2235
2585
  );
2236
2586
  return result;
2237
2587
  }
2238
- /** Read a resource by URI. */
2588
+ /**
2589
+ * Reads a resource by URI.
2590
+ *
2591
+ * @param uri - Resource URI to read.
2592
+ * @param options - Per-request options.
2593
+ * @returns The resource contents returned by the server.
2594
+ */
2239
2595
  async readResource(uri, options) {
2240
2596
  if (!this.client) {
2241
2597
  throw new Error("MCP client is not connected");
@@ -2270,6 +2626,11 @@ var BaseConnector = class {
2270
2626
  logger.debug(`Unsubscribing from resource: ${uri}`);
2271
2627
  return await this.client.unsubscribeResource({ uri }, options);
2272
2628
  }
2629
+ /**
2630
+ * Lists prompts exposed by the server.
2631
+ *
2632
+ * @returns The prompt list, or an empty list when prompts are unsupported.
2633
+ */
2273
2634
  async listPrompts() {
2274
2635
  if (!this.client) {
2275
2636
  throw new Error("MCP client is not connected");
@@ -2290,6 +2651,13 @@ var BaseConnector = class {
2290
2651
  throw err;
2291
2652
  }
2292
2653
  }
2654
+ /**
2655
+ * Gets a prompt with the supplied arguments.
2656
+ *
2657
+ * @param name - Prompt name.
2658
+ * @param args - Prompt arguments.
2659
+ * @returns The rendered prompt returned by the server.
2660
+ */
2293
2661
  async getPrompt(name, args) {
2294
2662
  if (!this.client) {
2295
2663
  throw new Error("MCP client is not connected");
@@ -2297,7 +2665,14 @@ var BaseConnector = class {
2297
2665
  logger.debug(`Getting prompt ${name}`);
2298
2666
  return await this.client.getPrompt({ name, arguments: args });
2299
2667
  }
2300
- /** Send a raw request through the client. */
2668
+ /**
2669
+ * Sends a raw, potentially non-standard request through the SDK client.
2670
+ *
2671
+ * @param method - JSON-RPC method name.
2672
+ * @param params - Request parameters. Defaults to an empty object.
2673
+ * @param options - Per-request options.
2674
+ * @returns The unvalidated result returned by the server.
2675
+ */
2301
2676
  async request(method, params = null, options) {
2302
2677
  if (!this.client) {
2303
2678
  throw new Error("MCP client is not connected");
@@ -2396,6 +2771,12 @@ var HttpConnector = class extends BaseConnector {
2396
2771
  reconnectionOptions;
2397
2772
  transportType = null;
2398
2773
  streamableTransport = null;
2774
+ /**
2775
+ * Creates an HTTP connector.
2776
+ *
2777
+ * @param baseUrl - MCP endpoint URL.
2778
+ * @param opts - Authentication, transport, SDK, and reconnection options.
2779
+ */
2399
2780
  constructor(baseUrl, opts = {}) {
2400
2781
  super(opts);
2401
2782
  const originalUrl = baseUrl.replace(/\/$/, "");
@@ -2513,7 +2894,12 @@ var HttpConnector = class extends BaseConnector {
2513
2894
  }
2514
2895
  return { fallbackReason, is401Error, httpStatusCode };
2515
2896
  }
2516
- /** Establish connection to the MCP implementation via streamable HTTP. */
2897
+ /**
2898
+ * Establishes a streamable HTTP connection to the MCP server.
2899
+ *
2900
+ * @returns A promise that resolves after protocol negotiation completes.
2901
+ * @throws An error with `code: 401` when authentication is required.
2902
+ */
2517
2903
  async connect() {
2518
2904
  if (this.connected) {
2519
2905
  logger.debug("Already connected to MCP implementation");
@@ -2741,6 +3127,11 @@ var HttpConnector = class extends BaseConnector {
2741
3127
  throw err;
2742
3128
  }
2743
3129
  }
3130
+ /**
3131
+ * Returns fields that identify the endpoint and negotiated transport.
3132
+ *
3133
+ * @returns HTTP connector identity metadata.
3134
+ */
2744
3135
  get publicIdentifier() {
2745
3136
  return {
2746
3137
  type: "http",
@@ -2749,7 +3140,11 @@ var HttpConnector = class extends BaseConnector {
2749
3140
  protocolEra: this.protocolEra ?? "unknown"
2750
3141
  };
2751
3142
  }
2752
- /** Get the active transport type (`streamable-http` once connected). */
3143
+ /**
3144
+ * Returns the active transport type.
3145
+ *
3146
+ * @returns `"streamable-http"` after connection, otherwise `null`.
3147
+ */
2753
3148
  getTransportType() {
2754
3149
  return this.transportType;
2755
3150
  }
@@ -3117,7 +3512,7 @@ var MCPConnection = class {
3117
3512
  /**
3118
3513
  * Normalized server metadata for this ready connection.
3119
3514
  *
3120
- * @throws {Error} When called before protocol negotiation completes.
3515
+ * @throws When called before protocol negotiation completes.
3121
3516
  */
3122
3517
  get info() {
3123
3518
  const protocolEra = this.protocolEra;
@@ -3329,12 +3724,10 @@ function isOAuthClientProvider(provider) {
3329
3724
  var BaseMCPClient = class {
3330
3725
  /**
3331
3726
  * Internal configuration object containing MCP server definitions.
3332
- * @protected
3333
3727
  */
3334
3728
  config = {};
3335
3729
  /**
3336
3730
  * Map of server names to their active sessions.
3337
- * @protected
3338
3731
  */
3339
3732
  sessions = {};
3340
3733
  /**
@@ -3378,7 +3771,7 @@ var BaseMCPClient = class {
3378
3771
  *
3379
3772
  * @param _cfg - Configuration dictionary
3380
3773
  * @returns Client instance
3381
- * @throws {Error} If called on the base class instead of a concrete implementation
3774
+ * @throws If called on the base class instead of a concrete implementation
3382
3775
  *
3383
3776
  * @example
3384
3777
  * ```typescript
@@ -3520,7 +3913,7 @@ var BaseMCPClient = class {
3520
3913
  * @param serverName - The name of the server as defined in the client configuration
3521
3914
  * @param autoInitialize - Whether to automatically initialize the session (default: true)
3522
3915
  * @returns A promise that resolves to the created MCPSession instance
3523
- * @throws {Error} If the server is not found in the configuration
3916
+ * @throws If the server is not found in the configuration
3524
3917
  *
3525
3918
  * @example
3526
3919
  * ```typescript
@@ -3690,7 +4083,7 @@ var BaseMCPClient = class {
3690
4083
  *
3691
4084
  * @param serverName - Name of the server
3692
4085
  * @returns The session instance
3693
- * @throws {Error} If the session is not found
4086
+ * @throws If the session is not found
3694
4087
  *
3695
4088
  * @example
3696
4089
  * ```typescript
@@ -3859,16 +4252,28 @@ function trackBrowserClientInit(config) {
3859
4252
  }
3860
4253
  var BrowserMCPClient = class _BrowserMCPClient extends BaseMCPClient {
3861
4254
  /**
3862
- * Get the mcp-use package version.
3863
- * Works in all environments (Node.js, browser, Cloudflare Workers, Deno, etc.)
4255
+ * Returns the installed `@mcp-use/client` package version.
4256
+ *
4257
+ * @returns The package version string.
3864
4258
  */
3865
4259
  static getPackageVersion() {
3866
4260
  return getPackageVersion();
3867
4261
  }
4262
+ /**
4263
+ * Creates a browser MCP client.
4264
+ *
4265
+ * @param config - Client configuration containing an optional `mcpServers` map.
4266
+ */
3868
4267
  constructor(config) {
3869
4268
  super(config);
3870
4269
  trackBrowserClientInit(this.config);
3871
4270
  }
4271
+ /**
4272
+ * Creates a browser client from an inline configuration object.
4273
+ *
4274
+ * @param cfg - Client configuration containing an optional `mcpServers` map.
4275
+ * @returns A browser client initialized with `cfg`.
4276
+ */
3872
4277
  static fromDict(cfg) {
3873
4278
  return new _BrowserMCPClient(cfg);
3874
4279
  }