@mcp-use/client 2.0.0-beta.10 → 2.0.0-beta.11

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.
@@ -1473,7 +1473,7 @@ var HttpConnector = class extends BaseConnector {
1473
1473
  };
1474
1474
 
1475
1475
  // src/utils/version.ts
1476
- var VERSION = "2.0.0-beta.9";
1476
+ var VERSION = "2.0.0-beta.10";
1477
1477
  function getPackageVersion() {
1478
1478
  return VERSION;
1479
1479
  }
@@ -1696,29 +1696,39 @@ var OAuthSessionStore = class _OAuthSessionStore {
1696
1696
  if (ctx) await this.store.set(this.credentialKey("tokens"), serialized);
1697
1697
  await this.store.remove(this.getKey("code_verifier"));
1698
1698
  await this.store.remove(this.getKey("last_auth_url"));
1699
+ await this.store.remove(this.getKey("last_auth_callback_url"));
1699
1700
  }
1700
1701
  async clientInformation(ctx) {
1702
+ if (!this.allowClientSecret) {
1703
+ const registeredRedirectUri = await this.store.get(
1704
+ this.getKey("client_info_redirect_uri")
1705
+ );
1706
+ if (registeredRedirectUri !== this.redirectUrl) {
1707
+ await this.invalidateCredentials("registration");
1708
+ console.info(
1709
+ `[${this.storageKeyPrefix}] Re-registering browser OAuth client after its Inspector callback changed or could not be verified.`
1710
+ );
1711
+ return void 0;
1712
+ }
1713
+ }
1701
1714
  const stored = await this.readCredential("client_info", ctx);
1702
1715
  if (!stored) return void 0;
1703
1716
  const { key, value: clientInfo } = stored;
1704
1717
  try {
1705
1718
  if (!this.allowClientSecret && clientInfo.client_secret) {
1706
- await this.store.remove(key);
1707
- if (ctx) await this.store.remove(this.credentialKey("client_info"));
1719
+ await this.invalidateCredentials("registration");
1708
1720
  console.warn(
1709
- `[${this.storageKeyPrefix}] Removed OAuth client information containing a browser client_secret.`
1721
+ `[${this.storageKeyPrefix}] Recovered stale browser OAuth credentials containing a client_secret.`
1710
1722
  );
1711
1723
  return void 0;
1712
1724
  }
1713
1725
  const storedRedirectUris = Array.isArray(clientInfo.redirect_uris) ? clientInfo.redirect_uris : [];
1714
- const hasMatchingRedirect = storedRedirectUris.length === 0 || storedRedirectUris.includes(this.redirectUrl);
1726
+ const hasMatchingRedirect = storedRedirectUris.length === 0 && this.allowClientSecret || storedRedirectUris.includes(this.redirectUrl);
1715
1727
  if (!hasMatchingRedirect) {
1716
1728
  console.info(
1717
- `[${this.storageKeyPrefix}] Invalidating cached OAuth client info due to redirect URI mismatch.`
1729
+ `[${this.storageKeyPrefix}] Recovering cached OAuth credentials after a redirect URI change.`
1718
1730
  );
1719
- await this.store.remove(key);
1720
- await this.store.remove(this.credentialKey("tokens", ctx));
1721
- await this.store.remove(this.getKey("last_auth_url"));
1731
+ await this.invalidateCredentials("registration");
1722
1732
  return void 0;
1723
1733
  }
1724
1734
  return clientInfo;
@@ -1736,11 +1746,20 @@ var OAuthSessionStore = class _OAuthSessionStore {
1736
1746
  "Browser OAuth clients must be public clients; client_secret persistence is not allowed."
1737
1747
  );
1738
1748
  }
1739
- const serialized = JSON.stringify(clientInformation);
1749
+ const persistedClientInformation = !this.allowClientSecret && (!("redirect_uris" in clientInformation) || !Array.isArray(
1750
+ clientInformation.redirect_uris
1751
+ ) || clientInformation.redirect_uris.length === 0) ? { ...clientInformation, redirect_uris: [this.redirectUrl] } : clientInformation;
1752
+ const serialized = JSON.stringify(persistedClientInformation);
1740
1753
  await this.store.set(this.credentialKey("client_info", ctx), serialized);
1741
1754
  if (ctx) {
1742
1755
  await this.store.set(this.credentialKey("client_info"), serialized);
1743
1756
  }
1757
+ if (!this.allowClientSecret) {
1758
+ await this.store.set(
1759
+ this.getKey("client_info_redirect_uri"),
1760
+ this.redirectUrl
1761
+ );
1762
+ }
1744
1763
  }
1745
1764
  async saveCodeVerifier(codeVerifier) {
1746
1765
  await this.store.set(this.getKey("code_verifier"), codeVerifier);
@@ -1765,11 +1784,22 @@ var OAuthSessionStore = class _OAuthSessionStore {
1765
1784
  }
1766
1785
  };
1767
1786
  switch (scope) {
1787
+ case "registration":
1788
+ await removeCredentialKeys("tokens");
1789
+ await removeCredentialKeys("client_info");
1790
+ await this.store.remove(this.getKey("code_verifier"));
1791
+ await this.store.remove(this.getKey("last_auth_url"));
1792
+ await this.store.remove(this.getKey("last_auth_callback_url"));
1793
+ await this.store.remove(this.getKey("client_info_redirect_uri"));
1794
+ await this.store.remove(this.getKey("token_endpoint"));
1795
+ break;
1768
1796
  case "all":
1769
1797
  await removeCredentialKeys("tokens");
1770
1798
  await removeCredentialKeys("client_info");
1771
1799
  await this.store.remove(this.getKey("code_verifier"));
1772
1800
  await this.store.remove(this.getKey("last_auth_url"));
1801
+ await this.store.remove(this.getKey("last_auth_callback_url"));
1802
+ await this.store.remove(this.getKey("client_info_redirect_uri"));
1773
1803
  await this.store.remove(this.getKey("discovery_state"));
1774
1804
  await this.store.remove(this.getKey("token_endpoint"));
1775
1805
  break;
@@ -1839,6 +1869,10 @@ var OAuthSessionStore = class _OAuthSessionStore {
1839
1869
  authorizationUrl.searchParams.set("state", state);
1840
1870
  const sanitizedAuthUrl = sanitizeUrl(authorizationUrl.toString());
1841
1871
  await this.store.set(stateKey, JSON.stringify(stateData));
1872
+ await this.store.set(
1873
+ this.getKey("last_auth_callback_url"),
1874
+ this.redirectUrl
1875
+ );
1842
1876
  await this.store.set(this.getKey("last_auth_url"), sanitizedAuthUrl);
1843
1877
  return sanitizedAuthUrl;
1844
1878
  }
@@ -2058,23 +2092,40 @@ var BrowserOAuthClientProvider = class {
2058
2092
  }
2059
2093
  return response2;
2060
2094
  }
2061
- const body = init?.body ? await serializeBody(init.body) : void 0;
2095
+ const inputRequest = input instanceof Request ? input : void 0;
2096
+ const method = init?.method ?? inputRequest?.method ?? "POST";
2097
+ const requestHeaders = init?.headers ?? inputRequest?.headers;
2098
+ let body;
2099
+ if (init?.body !== void 0 && init.body !== null) {
2100
+ body = await serializeBody(init.body);
2101
+ } else if (inputRequest?.body && method !== "GET" && method !== "HEAD") {
2102
+ body = await inputRequest.clone().text();
2103
+ }
2062
2104
  const response = await base(proxyEndpoint, {
2063
2105
  method: "POST",
2064
2106
  headers: { "Content-Type": "application/json" },
2065
2107
  body: JSON.stringify({
2066
2108
  serverUrl: this.serverUrl,
2067
2109
  url,
2068
- method: init?.method || "POST",
2069
- headers: init?.headers ? Object.fromEntries(new Headers(init.headers)) : {},
2110
+ method,
2111
+ headers: requestHeaders ? Object.fromEntries(new Headers(requestHeaders)) : {},
2070
2112
  body
2071
2113
  })
2072
2114
  });
2073
2115
  const data = await response.json();
2116
+ if (!response.ok || typeof data.status !== "number") {
2117
+ return new Response(JSON.stringify(data), {
2118
+ status: response.status,
2119
+ statusText: response.statusText,
2120
+ headers: response.headers
2121
+ });
2122
+ }
2074
2123
  return new Response(JSON.stringify(data.body), {
2075
2124
  status: data.status,
2076
- statusText: data.statusText,
2077
- headers: new Headers(data.headers)
2125
+ statusText: typeof data.statusText === "string" ? data.statusText : void 0,
2126
+ headers: new Headers(
2127
+ data.headers && typeof data.headers === "object" ? data.headers : void 0
2128
+ )
2078
2129
  });
2079
2130
  };
2080
2131
  }
@@ -2218,7 +2269,31 @@ var BrowserOAuthClientProvider = class {
2218
2269
  getLastAttemptedAuthUrl() {
2219
2270
  const storedUrl = localStorage.getItem(this.getKey("last_auth_url"));
2220
2271
  if (!storedUrl) return null;
2221
- return sanitizeUrl(storedUrl);
2272
+ const storedCallbackUrl = localStorage.getItem(
2273
+ this.getKey("last_auth_callback_url")
2274
+ );
2275
+ if (storedCallbackUrl !== this.callbackUrl) {
2276
+ console.info(
2277
+ `[${this.storageKeyPrefix}] Recovering stale OAuth state whose callback cannot be verified.`
2278
+ );
2279
+ this.clearStorage();
2280
+ return null;
2281
+ }
2282
+ const sanitized = sanitizeUrl(storedUrl);
2283
+ try {
2284
+ const redirectUri = new URL(sanitized).searchParams.get("redirect_uri");
2285
+ if (redirectUri && new URL(redirectUri).toString() !== new URL(this.callbackUrl).toString()) {
2286
+ console.info(
2287
+ `[${this.storageKeyPrefix}] Recovering stale OAuth state after the Inspector callback path changed.`
2288
+ );
2289
+ this.clearStorage();
2290
+ return null;
2291
+ }
2292
+ } catch {
2293
+ this.clearStorage();
2294
+ return null;
2295
+ }
2296
+ return sanitized;
2222
2297
  }
2223
2298
  clearStorage() {
2224
2299
  const prefixPattern = `${this.storageKeyPrefix}_${this.serverUrlHash}_`;
@@ -4062,9 +4137,14 @@ function startConnectionHealthMonitoring(params) {
4062
4137
  return;
4063
4138
  }
4064
4139
  const authHeaders = params.getAuthHeaders ? await params.getAuthHeaders() : {};
4140
+ const healthCheckHeaders = {
4141
+ ...params.allHeaders,
4142
+ ...authHeaders,
4143
+ ...params.gatewayUrl && params.url ? { "X-Target-URL": params.url } : {}
4144
+ };
4065
4145
  const response = await fetch(healthCheckUrl, {
4066
4146
  method: "HEAD",
4067
- headers: { ...params.allHeaders, ...authHeaders },
4147
+ headers: healthCheckHeaders,
4068
4148
  signal: AbortSignal.timeout(5e3)
4069
4149
  });
4070
4150
  if (response.status === 405 || response.status === 404) {
@@ -4908,9 +4988,22 @@ function useMcp(options) {
4908
4988
  });
4909
4989
  setTools(connection.tools || []);
4910
4990
  const [resourcesResult, promptsResult, templatesResult] = await Promise.all([
4911
- connection.listAllResources(),
4912
- connection.listPrompts(),
4913
- connection.supports("resources") ? connection.listResourceTemplates() : Promise.resolve({ resourceTemplates: [] })
4991
+ connection.listAllResources().catch((error2) => {
4992
+ addLog("warn", "Failed to load initial resources:", error2);
4993
+ return { resources: [] };
4994
+ }),
4995
+ connection.listPrompts().catch((error2) => {
4996
+ addLog("warn", "Failed to load initial prompts:", error2);
4997
+ return { prompts: [] };
4998
+ }),
4999
+ connection.supports("resources") ? connection.listResourceTemplates().catch((error2) => {
5000
+ addLog(
5001
+ "warn",
5002
+ "Failed to load initial resource templates:",
5003
+ error2
5004
+ );
5005
+ return { resourceTemplates: [] };
5006
+ }) : Promise.resolve({ resourceTemplates: [] })
4914
5007
  ]);
4915
5008
  if (!isMountedRef.current) {
4916
5009
  addLog(