deadbyte-mcp 0.15.49 → 0.15.50

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 (93) hide show
  1. package/MANIFEST.SHA256 +82 -78
  2. package/PROVENANCE.json +3 -3
  3. package/README.txt +18 -18
  4. package/RELEASE.json +5 -5
  5. package/SBOM.cdx.json +2 -2
  6. package/TEST-MATRIX.json +2 -2
  7. package/docs/R130-SDK-SECURITY-PATCH.md +34 -0
  8. package/node_modules/@modelcontextprotocol/client/README.md +1 -7
  9. package/node_modules/@modelcontextprotocol/client/dist/{index-BCtJi0p5.d.mts → index-B-4n9P0J.d.mts} +5 -1
  10. package/node_modules/@modelcontextprotocol/client/dist/index-B-4n9P0J.d.mts.map +1 -0
  11. package/node_modules/@modelcontextprotocol/client/dist/{index-CEk3qkZM.d.cts → index-J2FaQ-KY.d.cts} +5 -1
  12. package/node_modules/@modelcontextprotocol/client/dist/index-J2FaQ-KY.d.cts.map +1 -0
  13. package/node_modules/@modelcontextprotocol/client/dist/index.cjs +175 -76
  14. package/node_modules/@modelcontextprotocol/client/dist/index.cjs.map +1 -1
  15. package/node_modules/@modelcontextprotocol/client/dist/index.d.cts +214 -35
  16. package/node_modules/@modelcontextprotocol/client/dist/index.d.cts.map +1 -1
  17. package/node_modules/@modelcontextprotocol/client/dist/index.d.mts +214 -35
  18. package/node_modules/@modelcontextprotocol/client/dist/index.d.mts.map +1 -1
  19. package/node_modules/@modelcontextprotocol/client/dist/index.mjs +175 -76
  20. package/node_modules/@modelcontextprotocol/client/dist/index.mjs.map +1 -1
  21. package/node_modules/@modelcontextprotocol/client/dist/shimsWorkerd.cjs +1 -1
  22. package/node_modules/@modelcontextprotocol/client/dist/shimsWorkerd.mjs +1 -1
  23. package/node_modules/@modelcontextprotocol/client/dist/{src-D0qEN74R.cjs → src-DpAS0jfg.cjs} +125 -11
  24. package/node_modules/@modelcontextprotocol/client/dist/src-DpAS0jfg.cjs.map +1 -0
  25. package/node_modules/@modelcontextprotocol/client/dist/{src-DDAAhLnO.mjs → src-WCy6ifGf.mjs} +102 -12
  26. package/node_modules/@modelcontextprotocol/client/dist/src-WCy6ifGf.mjs.map +1 -0
  27. package/node_modules/@modelcontextprotocol/client/dist/stdio.cjs +1 -1
  28. package/node_modules/@modelcontextprotocol/client/dist/stdio.d.cts +1 -1
  29. package/node_modules/@modelcontextprotocol/client/dist/stdio.d.mts +1 -1
  30. package/node_modules/@modelcontextprotocol/client/dist/stdio.mjs +1 -1
  31. package/node_modules/@modelcontextprotocol/client/package.json +5 -5
  32. package/node_modules/@modelcontextprotocol/core/dist/{auth--n_Yzytt.d.cts → auth-Anm-lwWi.d.mts} +9 -8
  33. package/node_modules/@modelcontextprotocol/core/dist/{auth--n_Yzytt.d.cts.map → auth-Anm-lwWi.d.mts.map} +1 -1
  34. package/node_modules/@modelcontextprotocol/core/dist/{auth-CGP0BDVq.mjs → auth-BNDyLTqp.mjs} +5 -3
  35. package/node_modules/@modelcontextprotocol/core/dist/{auth-CGP0BDVq.mjs.map → auth-BNDyLTqp.mjs.map} +1 -1
  36. package/node_modules/@modelcontextprotocol/core/dist/{auth-4-zilcqg.cjs → auth-D1CeV_Jr.cjs} +5 -3
  37. package/node_modules/@modelcontextprotocol/core/dist/{auth-4-zilcqg.cjs.map → auth-D1CeV_Jr.cjs.map} +1 -1
  38. package/node_modules/@modelcontextprotocol/core/dist/{auth-YUQV3RRv.d.mts → auth-V9XJSCfa.d.cts} +9 -8
  39. package/node_modules/@modelcontextprotocol/core/dist/{auth-YUQV3RRv.d.mts.map → auth-V9XJSCfa.d.cts.map} +1 -1
  40. package/node_modules/@modelcontextprotocol/core/dist/index.cjs +1 -1
  41. package/node_modules/@modelcontextprotocol/core/dist/index.d.cts +1 -1
  42. package/node_modules/@modelcontextprotocol/core/dist/index.d.mts +1 -1
  43. package/node_modules/@modelcontextprotocol/core/dist/index.mjs +1 -1
  44. package/node_modules/@modelcontextprotocol/core/dist/internal.cjs +1 -1
  45. package/node_modules/@modelcontextprotocol/core/dist/internal.d.cts +1 -1
  46. package/node_modules/@modelcontextprotocol/core/dist/internal.d.mts +1 -1
  47. package/node_modules/@modelcontextprotocol/core/dist/internal.mjs +1 -1
  48. package/node_modules/@modelcontextprotocol/core/package.json +2 -2
  49. package/node_modules/@modelcontextprotocol/server/README.md +1 -7
  50. package/node_modules/@modelcontextprotocol/server/dist/{createMcpHandler-Bt6U_Fqb.d.mts → createMcpHandler-D4NN8WsG.d.mts} +35 -13
  51. package/node_modules/@modelcontextprotocol/server/dist/createMcpHandler-D4NN8WsG.d.mts.map +1 -0
  52. package/node_modules/@modelcontextprotocol/server/dist/{createMcpHandler-BLVe3qmU.d.cts → createMcpHandler-DZmmlN8e.d.cts} +35 -13
  53. package/node_modules/@modelcontextprotocol/server/dist/createMcpHandler-DZmmlN8e.d.cts.map +1 -0
  54. package/node_modules/@modelcontextprotocol/server/dist/index.cjs +32 -5
  55. package/node_modules/@modelcontextprotocol/server/dist/index.cjs.map +1 -1
  56. package/node_modules/@modelcontextprotocol/server/dist/index.d.cts +41 -5
  57. package/node_modules/@modelcontextprotocol/server/dist/index.d.cts.map +1 -1
  58. package/node_modules/@modelcontextprotocol/server/dist/index.d.mts +41 -5
  59. package/node_modules/@modelcontextprotocol/server/dist/index.d.mts.map +1 -1
  60. package/node_modules/@modelcontextprotocol/server/dist/index.mjs +32 -5
  61. package/node_modules/@modelcontextprotocol/server/dist/index.mjs.map +1 -1
  62. package/node_modules/@modelcontextprotocol/server/dist/{mcp-DUcCQSTW.cjs → mcp-BumlNux0.cjs} +73 -23
  63. package/node_modules/@modelcontextprotocol/server/dist/mcp-BumlNux0.cjs.map +1 -0
  64. package/node_modules/@modelcontextprotocol/server/dist/{mcp-Dw2OlZ1f.mjs → mcp-DIH4cS6P.mjs} +73 -23
  65. package/node_modules/@modelcontextprotocol/server/dist/mcp-DIH4cS6P.mjs.map +1 -0
  66. package/node_modules/@modelcontextprotocol/server/dist/shimsWorkerd.cjs +1 -1
  67. package/node_modules/@modelcontextprotocol/server/dist/shimsWorkerd.mjs +1 -1
  68. package/node_modules/@modelcontextprotocol/server/dist/{src-CgFsfg3E.cjs → src-BhnGYybN.cjs} +29 -11
  69. package/node_modules/@modelcontextprotocol/server/dist/src-BhnGYybN.cjs.map +1 -0
  70. package/node_modules/@modelcontextprotocol/server/dist/{src-D-y6h4N7.mjs → src-Cqbh3MYc.mjs} +29 -11
  71. package/node_modules/@modelcontextprotocol/server/dist/src-Cqbh3MYc.mjs.map +1 -0
  72. package/node_modules/@modelcontextprotocol/server/dist/stdio.cjs +2 -2
  73. package/node_modules/@modelcontextprotocol/server/dist/stdio.d.cts +1 -1
  74. package/node_modules/@modelcontextprotocol/server/dist/stdio.d.mts +1 -1
  75. package/node_modules/@modelcontextprotocol/server/dist/stdio.mjs +2 -2
  76. package/node_modules/@modelcontextprotocol/server/package.json +4 -4
  77. package/node_modules/which/CHANGELOG.md +166 -0
  78. package/package.json +3 -3
  79. package/src/version.mjs +1 -1
  80. package/test/r129-sdk-security-baseline.test.mjs +38 -0
  81. package/test/r130-release-security-contract.test.mjs +28 -0
  82. package/test/r59-tool-surface-compat.test.mjs +1 -1
  83. package/test/r74-prepublish-contract.test.mjs +2 -2
  84. package/node_modules/@modelcontextprotocol/client/dist/index-BCtJi0p5.d.mts.map +0 -1
  85. package/node_modules/@modelcontextprotocol/client/dist/index-CEk3qkZM.d.cts.map +0 -1
  86. package/node_modules/@modelcontextprotocol/client/dist/src-D0qEN74R.cjs.map +0 -1
  87. package/node_modules/@modelcontextprotocol/client/dist/src-DDAAhLnO.mjs.map +0 -1
  88. package/node_modules/@modelcontextprotocol/server/dist/createMcpHandler-BLVe3qmU.d.cts.map +0 -1
  89. package/node_modules/@modelcontextprotocol/server/dist/createMcpHandler-Bt6U_Fqb.d.mts.map +0 -1
  90. package/node_modules/@modelcontextprotocol/server/dist/mcp-DUcCQSTW.cjs.map +0 -1
  91. package/node_modules/@modelcontextprotocol/server/dist/mcp-Dw2OlZ1f.mjs.map +0 -1
  92. package/node_modules/@modelcontextprotocol/server/dist/src-CgFsfg3E.cjs.map +0 -1
  93. package/node_modules/@modelcontextprotocol/server/dist/src-D-y6h4N7.mjs.map +0 -1
@@ -1,5 +1,5 @@
1
1
  const require_chunk = require('./chunk-Bnu9O96Y.cjs');
2
- const require_src = require('./src-D0qEN74R.cjs');
2
+ const require_src = require('./src-DpAS0jfg.cjs');
3
3
  let _modelcontextprotocol_client__shims = require("@modelcontextprotocol/client/_shims");
4
4
  let pkce_challenge = require("pkce-challenge");
5
5
  pkce_challenge = require_chunk.__toESM(pkce_challenge);
@@ -115,10 +115,12 @@ var RegistrationRejectedError = class extends OAuthClientFlowError {
115
115
  };
116
116
  /**
117
117
  * Thrown by the token-exchange and refresh paths when the resolved token
118
- * endpoint is not `https:` and is not a loopback host (SEP-2207). This is a
119
- * configuration error — re-authorizing cannot fix it — so it intentionally does
120
- * **not** extend `OAuthError` and `auth()`'s refresh branch rethrows it instead
121
- * of falling through to a fresh `/authorize` redirect.
118
+ * endpoint is not `https:` and is not a loopback host. The MCP authorization
119
+ * specification requires authorization server endpoints to use HTTPS; loopback
120
+ * hosts are exempt here for local development. This is a configuration error —
121
+ * re-authorizing cannot fix it — so it intentionally does **not** extend
122
+ * `OAuthError` and `auth()`'s refresh branch rethrows it instead of falling
123
+ * through to a fresh `/authorize` redirect.
122
124
  */
123
125
  var InsecureTokenEndpointError = class extends OAuthClientFlowError {
124
126
  static {
@@ -127,7 +129,7 @@ var InsecureTokenEndpointError = class extends OAuthClientFlowError {
127
129
  /** The token endpoint URL that was rejected. */
128
130
  tokenEndpoint;
129
131
  constructor(tokenEndpoint) {
130
- super(`Refusing to send credentials to non-https token endpoint '${tokenEndpoint}'. OAuth token requests MUST use TLS (localhost / 127.0.0.1 / ::1 are exempt).`);
132
+ super(`Refusing to send credentials to non-https token endpoint '${tokenEndpoint}'. OAuth token requests MUST use TLS (localhost / *.localhost / 127.0.0.1 / ::1 are exempt).`);
131
133
  this.tokenEndpoint = tokenEndpoint;
132
134
  }
133
135
  };
@@ -152,21 +154,25 @@ var InsecureTokenEndpointError = class extends OAuthClientFlowError {
152
154
  * `requiredScope`, which appears in the error message).
153
155
  */
154
156
  /**
155
- * Thrown by `auth()` on the authorization-code callback leg when the
156
- * authorization server resolved by discovery differs from the one recorded in
157
- * `discoveryState()` at redirect time. The `authorization_code` and PKCE
158
- * `code_verifier` are bound to the AS that minted the code (RFC 7636); sending
159
- * them to a different AS's token endpoint is a credential-exfiltration vector.
160
- *
161
- * This is the only runtime check left in the SEP-2352 model — stored tokens and
162
- * client credentials are protected structurally by the `issuer` stamp instead.
157
+ * Thrown by `auth()` and `fetchToken()` when the authorization server in use differs
158
+ * from the one a credential is bound to and the flow cannot simply start over:
159
+ *
160
+ * - on the authorization-code callback leg, when it differs from the one recorded
161
+ * in `discoveryState()` at redirect time — the `authorization_code` and PKCE
162
+ * `code_verifier` are bound to the AS that minted the code (RFC 7636);
163
+ * - for client information whose `issuer` stamp names a different authorization
164
+ * server on a provider that cannot re-register (no `saveClientInformation()`,
165
+ * e.g. the bundled static-credential providers); `fetchToken()` throws for any provider.
166
+ *
167
+ * Stored tokens and re-registrable client information are protected structurally
168
+ * by the `issuer` stamp instead (they read back as absent).
163
169
  */
164
170
  var AuthorizationServerMismatchError = class extends OAuthClientFlowError {
165
171
  static {
166
172
  Object.defineProperty(this, "mcpBrand", { value: "mcp.AuthorizationServerMismatchError" });
167
173
  }
168
174
  constructor(recordedIssuer, currentIssuer) {
169
- super(`Authorization server changed between redirect and callback (redirected to ${JSON.stringify(recordedIssuer)}, callback resolved ${JSON.stringify(currentIssuer)}); refusing to send authorization_code/code_verifier to a different token endpoint`);
175
+ super(`Authorization server mismatch: credentials are bound to ${JSON.stringify(recordedIssuer)} but this call resolved ${JSON.stringify(currentIssuer)}; refusing to present them to a different authorization server`);
170
176
  this.recordedIssuer = recordedIssuer;
171
177
  this.currentIssuer = currentIssuer;
172
178
  }
@@ -210,10 +216,13 @@ var InsufficientScopeError = class extends OAuthClientFlowError {
210
216
  * "binding on first use" claim would be false and would fire on every call.
211
217
  */
212
218
  function discardIfIssuerMismatch(stored, issuer, opts) {
213
- if (stored === void 0) return void 0;
214
- if (stored.issuer === void 0) {
219
+ if (!stored) return void 0;
220
+ if (typeof stored.issuer !== "string") {
215
221
  if (opts?.canPersistStamp !== false) console.warn("[mcp-sdk] SEP-2352: stored OAuth credential has no 'issuer' stamp (pre-upgrade storage or provider not round-tripping the value). SEP-2352 isolation is inactive for this read; ensure your provider round-trips the issuer field.");
216
- return stored;
222
+ return stored.issuer === void 0 ? stored : {
223
+ ...stored,
224
+ issuer: void 0
225
+ };
217
226
  }
218
227
  return issuersMatch(stored.issuer, issuer) ? stored : void 0;
219
228
  }
@@ -521,13 +530,19 @@ function applyPostAuth(clientId, clientSecret, params) {
521
530
  function applyPublicAuth(clientId, params) {
522
531
  params.set("client_id", clientId);
523
532
  }
524
- /** Loopback hosts exempt from the in-transit `https:` requirement (RFC 8252 §7.3). */
533
+ /**
534
+ * Loopback hosts exempt from the in-transit `https:` requirement (RFC 8252 §7.3).
535
+ * Includes bare `localhost` and any name ending in `.localhost` (RFC 6761 §6.3).
536
+ */
525
537
  function isLoopbackHost(hostname) {
526
- return hostname === "localhost" || hostname === "127.0.0.1" || hostname === "[::1]" || hostname === "::1";
538
+ return hostname === "localhost" || hostname.endsWith(".localhost") || hostname === "127.0.0.1" || hostname === "[::1]" || hostname === "::1";
527
539
  }
528
540
  /**
529
- * SEP-2207: refuse to send credentials to a non-TLS, non-loopback token endpoint.
530
- * Throws {@linkcode InsecureTokenEndpointError}. Loopback hosts are exempt.
541
+ * Refuse to send credentials to a non-TLS token endpoint. The MCP authorization
542
+ * specification requires authorization server endpoints to use HTTPS. Loopback
543
+ * hosts are exempt here for local development.
544
+ *
545
+ * @throws {@linkcode InsecureTokenEndpointError} if the endpoint is insecure.
531
546
  */
532
547
  function assertSecureTokenEndpoint(tokenEndpoint) {
533
548
  const url = new URL(String(tokenEndpoint));
@@ -977,12 +992,13 @@ async function discoverOAuthProtectedResourceMetadata(serverUrl, opts, fetchFn =
977
992
  * error object alone, so the swallow-and-fallthrough heuristic is preserved there.
978
993
  */
979
994
  async function fetchWithCorsRetry(url, headers, fetchFn = fetch) {
995
+ const withinOrigin = require_src.fetchWithinOrigin(fetchFn);
980
996
  try {
981
- return await fetchFn(url, { headers });
997
+ return await withinOrigin(url, { headers });
982
998
  } catch (error) {
983
999
  if (!(error instanceof TypeError) || !_modelcontextprotocol_client__shims.CORS_IS_POSSIBLE) throw error;
984
1000
  if (headers) try {
985
- return await fetchFn(url, {});
1001
+ return await withinOrigin(url, {});
986
1002
  } catch (retryError) {
987
1003
  if (!(retryError instanceof TypeError)) throw retryError;
988
1004
  return;
@@ -1009,7 +1025,7 @@ async function tryMetadataDiscovery(url, protocolVersion, fetchFn = fetch) {
1009
1025
  function shouldAttemptFallback(response, pathname) {
1010
1026
  if (!response) return true;
1011
1027
  if (pathname === "/") return false;
1012
- return response.status >= 400 && response.status < 500 || response.status === 502;
1028
+ return !response.ok && response.status < 500 || response.status === 502;
1013
1029
  }
1014
1030
  /**
1015
1031
  * Generic function for discovering OAuth metadata with fallback support
@@ -1132,7 +1148,7 @@ async function discoverAuthorizationServerMetadata(authorizationServerUrl, { fet
1132
1148
  continue;
1133
1149
  if (!response.ok) {
1134
1150
  await response.text?.().catch(() => {});
1135
- if (response.status >= 400 && response.status < 500 || response.status === 502) continue;
1151
+ if (response.status < 500 || response.status === 502) continue;
1136
1152
  throw new Error(`HTTP ${response.status} trying to load ${type === "oauth" ? "OAuth" : "OpenID provider"} metadata from ${endpointUrl}`);
1137
1153
  }
1138
1154
  const parsed = type === "oauth" ? _modelcontextprotocol_core_internal.OAuthMetadataSchema.parse(await response.json()) : _modelcontextprotocol_core_internal.OpenIdProviderDiscoveryMetadataSchema.parse(await response.json());
@@ -1251,7 +1267,7 @@ async function executeTokenRequest(authorizationServerUrl, { metadata, tokenRequ
1251
1267
  htm: "POST",
1252
1268
  htu: tokenUrl
1253
1269
  }));
1254
- return (fetchFn ?? fetch)(tokenUrl, {
1270
+ return require_src.fetchWithinOrigin(fetchFn ?? fetch)(tokenUrl, {
1255
1271
  method: "POST",
1256
1272
  headers: requestHeaders,
1257
1273
  body: tokenRequestParams
@@ -1268,7 +1284,7 @@ async function executeTokenRequest(authorizationServerUrl, { metadata, tokenRequ
1268
1284
  if (!response.ok) throw await parseErrorResponse(response);
1269
1285
  const json = await response.json();
1270
1286
  try {
1271
- return _modelcontextprotocol_core_internal.OAuthTokensSchema.parse(json);
1287
+ return _modelcontextprotocol_core_internal.OAuthTokensSchema.parse(require_src.withoutIssuer(json));
1272
1288
  } catch (parseError) {
1273
1289
  if (typeof json === "object" && json !== null && "error" in json) throw await parseErrorResponse(JSON.stringify(json));
1274
1290
  throw parseError;
@@ -1364,6 +1380,14 @@ async function fetchToken(provider, authorizationServerUrl, { metadata, resource
1364
1380
  expectedIssuer: metadata?.issuer,
1365
1381
  issParameterSupported: isIssParameterSupported(metadata)
1366
1382
  });
1383
+ const issuer = metadata?.issuer ?? String(authorizationServerUrl);
1384
+ const readClientInformation = async () => {
1385
+ const rawClientInfo = await provider.clientInformation({ issuer });
1386
+ const checked = discardIfIssuerMismatch(rawClientInfo, issuer, { canPersistStamp: false });
1387
+ if (rawClientInfo && checked === void 0) throw new AuthorizationServerMismatchError(String(rawClientInfo.issuer), issuer);
1388
+ return checked;
1389
+ };
1390
+ let clientInformation = await readClientInformation();
1367
1391
  const effectiveScope = scope ?? provider.clientMetadata.scope;
1368
1392
  let tokenRequestParams;
1369
1393
  if (provider.prepareTokenRequest) tokenRequestParams = await provider.prepareTokenRequest(effectiveScope);
@@ -1372,11 +1396,11 @@ async function fetchToken(provider, authorizationServerUrl, { metadata, resource
1372
1396
  if (!provider.redirectUrl) throw new Error("redirectUrl is required for authorization_code flow");
1373
1397
  tokenRequestParams = prepareAuthorizationCodeRequest(authorizationCode, await provider.codeVerifier(), provider.redirectUrl);
1374
1398
  }
1375
- const clientInformation = await provider.clientInformation({ issuer: metadata?.issuer ?? String(authorizationServerUrl) });
1399
+ clientInformation ??= await readClientInformation();
1376
1400
  return executeTokenRequest(authorizationServerUrl, {
1377
1401
  metadata,
1378
1402
  tokenRequestParams,
1379
- clientInformation: clientInformation ?? void 0,
1403
+ clientInformation,
1380
1404
  addClientAuthentication: provider.addClientAuthentication,
1381
1405
  resource,
1382
1406
  dpop: await provider.dpop?.(),
@@ -1392,10 +1416,17 @@ async function fetchToken(provider, authorizationServerUrl, { metadata, resource
1392
1416
  * consistently across both DCR and the subsequent authorization request.
1393
1417
  *
1394
1418
  * @deprecated Dynamic Client Registration is deprecated as of protocol version
1395
- * 2026-07-28 (SEP-2577) in favor of Client ID Metadata Documents (SEP-991).
1396
- * Remains functional during the deprecation window (at least twelve months).
1397
- * Prefer a CIMD URL `client_id` when the authorization server advertises
1398
- * `client_id_metadata_document_supported`; the SDK already gates on this for you.
1419
+ * 2026-07-28 in favor of Client ID Metadata Documents (SEP-991); the deprecation
1420
+ * landed via spec PR
1421
+ * {@link https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2858 | modelcontextprotocol#2858}
1422
+ * (SEP-2577 is the separate roots/sampling/logging deprecation). Remains
1423
+ * functional during the deprecation window — at least twelve months under the
1424
+ * feature lifecycle policy (SEP-2596), so 2027-07-28 is the earliest possible
1425
+ * removal date. Prefer a CIMD URL `client_id` when the authorization server
1426
+ * advertises `client_id_metadata_document_supported`: the built-in `auth()` flow
1427
+ * skips registration for you when that capability is advertised AND your
1428
+ * provider supplies `clientMetadataUrl`, but `registerClient` itself does not
1429
+ * gate — calling it directly always sends the registration request.
1399
1430
  */
1400
1431
  async function registerClient(authorizationServerUrl, { metadata, clientMetadata, scope, fetchFn }) {
1401
1432
  let registrationUrl;
@@ -1407,7 +1438,7 @@ async function registerClient(authorizationServerUrl, { metadata, clientMetadata
1407
1438
  ...clientMetadata,
1408
1439
  ...scope === void 0 ? {} : { scope }
1409
1440
  };
1410
- const response = await (fetchFn ?? fetch)(registrationUrl, {
1441
+ const response = await require_src.fetchWithinOrigin(fetchFn ?? fetch)(registrationUrl, {
1411
1442
  method: "POST",
1412
1443
  headers: { "Content-Type": "application/json" },
1413
1444
  body: JSON.stringify(submittedMetadata)
@@ -1417,7 +1448,7 @@ async function registerClient(authorizationServerUrl, { metadata, clientMetadata
1417
1448
  body: await response.text(),
1418
1449
  submittedMetadata
1419
1450
  });
1420
- return _modelcontextprotocol_core_internal.OAuthClientInformationFullSchema.parse(await response.json());
1451
+ return _modelcontextprotocol_core_internal.OAuthClientInformationFullSchema.parse(require_src.withoutIssuer(await response.json()));
1421
1452
  }
1422
1453
 
1423
1454
  //#endregion
@@ -1472,6 +1503,15 @@ function createPrivateKeyJwtAuth(options) {
1472
1503
  };
1473
1504
  }
1474
1505
  /**
1506
+ * The `issuer` stamp for constructor-supplied client information. Omitting `expectedIssuer` is
1507
+ * deprecated: nothing else says which authorization server such credentials belong to.
1508
+ */
1509
+ function checkedExpectedIssuer(expectedIssuer) {
1510
+ if (expectedIssuer === void 0) console.warn("[mcp-sdk] Omitting `expectedIssuer` is deprecated. Without it, the MCP server decides which authorization server receives this client's credentials; pass your authorization server's issuer URL as `expectedIssuer` so they are only sent there.");
1511
+ else if (typeof expectedIssuer !== "string" || !expectedIssuer) throw new Error("expectedIssuer must be the authorization server's issuer URL");
1512
+ return expectedIssuer;
1513
+ }
1514
+ /**
1475
1515
  * OAuth provider for `client_credentials` grant with `client_secret_basic` authentication.
1476
1516
  *
1477
1517
  * This provider is designed for machine-to-machine authentication where
@@ -1481,7 +1521,8 @@ function createPrivateKeyJwtAuth(options) {
1481
1521
  * ```ts source="./authExtensions.examples.ts#ClientCredentialsProvider_basicUsage"
1482
1522
  * const provider = new ClientCredentialsProvider({
1483
1523
  * clientId: 'my-client',
1484
- * clientSecret: 'my-secret'
1524
+ * clientSecret: 'my-secret',
1525
+ * expectedIssuer: 'https://auth.example.com'
1485
1526
  * });
1486
1527
  *
1487
1528
  * const transport = new StreamableHTTPClientTransport(serverUrl, {
@@ -1497,7 +1538,7 @@ var ClientCredentialsProvider = class {
1497
1538
  this._clientInfo = {
1498
1539
  client_id: options.clientId,
1499
1540
  client_secret: options.clientSecret,
1500
- issuer: options.expectedIssuer
1541
+ issuer: checkedExpectedIssuer(options.expectedIssuer)
1501
1542
  };
1502
1543
  this._clientMetadata = {
1503
1544
  client_name: options.clientName ?? "client-credentials-client",
@@ -1545,7 +1586,8 @@ var ClientCredentialsProvider = class {
1545
1586
  * const provider = new PrivateKeyJwtProvider({
1546
1587
  * clientId: 'my-client',
1547
1588
  * privateKey: pemEncodedPrivateKey,
1548
- * algorithm: 'RS256'
1589
+ * algorithm: 'RS256',
1590
+ * expectedIssuer: 'https://auth.example.com'
1549
1591
  * });
1550
1592
  *
1551
1593
  * const transport = new StreamableHTTPClientTransport(serverUrl, {
@@ -1561,7 +1603,7 @@ var PrivateKeyJwtProvider = class {
1561
1603
  constructor(options) {
1562
1604
  this._clientInfo = {
1563
1605
  client_id: options.clientId,
1564
- issuer: options.expectedIssuer
1606
+ issuer: checkedExpectedIssuer(options.expectedIssuer)
1565
1607
  };
1566
1608
  this._clientMetadata = {
1567
1609
  client_name: options.clientName ?? "private-key-jwt-client",
@@ -1620,7 +1662,7 @@ var StaticPrivateKeyJwtProvider = class {
1620
1662
  constructor(options) {
1621
1663
  this._clientInfo = {
1622
1664
  client_id: options.clientId,
1623
- issuer: options.expectedIssuer
1665
+ issuer: checkedExpectedIssuer(options.expectedIssuer)
1624
1666
  };
1625
1667
  this._clientMetadata = {
1626
1668
  client_name: options.clientName ?? "static-private-key-jwt-client",
@@ -1692,7 +1734,8 @@ var StaticPrivateKeyJwtProvider = class {
1692
1734
  * return result.jwtAuthGrant;
1693
1735
  * },
1694
1736
  * clientId: 'my-mcp-client',
1695
- * clientSecret: 'my-mcp-secret'
1737
+ * clientSecret: 'my-mcp-secret',
1738
+ * expectedIssuer: 'https://auth.example.com'
1696
1739
  * });
1697
1740
  *
1698
1741
  * const transport = new StreamableHTTPClientTransport(serverUrl, {
@@ -1713,7 +1756,7 @@ var CrossAppAccessProvider = class {
1713
1756
  this._clientInfo = {
1714
1757
  client_id: options.clientId,
1715
1758
  client_secret: options.clientSecret,
1716
- issuer: options.expectedIssuer
1759
+ issuer: checkedExpectedIssuer(options.expectedIssuer)
1717
1760
  };
1718
1761
  this._clientMetadata = {
1719
1762
  client_name: options.clientName ?? "cross-app-access-client",
@@ -2376,6 +2419,10 @@ function classifyProbeOutcome(outcome, context) {
2376
2419
  case "rpc-error": return classifyRpcError(outcome, context);
2377
2420
  case "http-error": return classifyHttpError(outcome, context);
2378
2421
  case "network-error": return classifyNetworkError(outcome.error, context);
2422
+ case "unusable-reply": return {
2423
+ kind: "error",
2424
+ error: new require_src.SdkError(require_src.SdkErrorCode.EraNegotiationFailed, `Version negotiation probe failed: the server answered with an unusable reply (${describeError(outcome.error)})`, { cause: outcome.error }, { cause: outcome.error })
2425
+ };
2379
2426
  case "auth-required": return {
2380
2427
  kind: "error",
2381
2428
  error: outcome.error
@@ -2713,6 +2760,11 @@ function buildProbeRequest(id, protocolVersion, clientInfo, capabilities) {
2713
2760
  }) }
2714
2761
  };
2715
2762
  }
2763
+ /** True for what the transport throws when the probe was answered 2xx without a usable reply. */
2764
+ function isUnusableReplyError(error) {
2765
+ if (error instanceof require_src.SdkError && error.code === require_src.SdkErrorCode.ClientHttpUnexpectedContent) return true;
2766
+ return error instanceof Error && error.name === "SyntaxError";
2767
+ }
2716
2768
  function normalizeReply(reply, timeoutMs) {
2717
2769
  switch (reply.kind) {
2718
2770
  case "response": return reply.error === void 0 ? {
@@ -2737,6 +2789,10 @@ function normalizeReply(reply, timeoutMs) {
2737
2789
  statusText: error.data.statusText
2738
2790
  };
2739
2791
  }
2792
+ if (isUnusableReplyError(error)) return {
2793
+ kind: "unusable-reply",
2794
+ error
2795
+ };
2740
2796
  return {
2741
2797
  kind: "network-error",
2742
2798
  error
@@ -3635,7 +3691,7 @@ var Client = class extends require_src.Protocol {
3635
3691
  }, options);
3636
3692
  const hit = await this._serveFromCache("prompts/list", void 0, options);
3637
3693
  if (hit !== void 0) return hit;
3638
- return this._listAllPages("prompts/list", params, options, (acc, page) => acc.prompts.push(...page.prompts));
3694
+ return this._listAllPages("prompts/list", params, options, (r) => r.prompts);
3639
3695
  }
3640
3696
  /**
3641
3697
  * Lists available resources.
@@ -3674,7 +3730,7 @@ var Client = class extends require_src.Protocol {
3674
3730
  }, options);
3675
3731
  const hit = await this._serveFromCache("resources/list", void 0, options);
3676
3732
  if (hit !== void 0) return hit;
3677
- return this._listAllPages("resources/list", params, options, (acc, page) => acc.resources.push(...page.resources));
3733
+ return this._listAllPages("resources/list", params, options, (r) => r.resources);
3678
3734
  }
3679
3735
  /**
3680
3736
  * Lists available resource URI templates for dynamic resources.
@@ -3699,7 +3755,7 @@ var Client = class extends require_src.Protocol {
3699
3755
  }, options);
3700
3756
  const hit = await this._serveFromCache("resources/templates/list", void 0, options);
3701
3757
  if (hit !== void 0) return hit;
3702
- return this._listAllPages("resources/templates/list", params, options, (acc, page) => acc.resourceTemplates.push(...page.resourceTemplates));
3758
+ return this._listAllPages("resources/templates/list", params, options, (r) => r.resourceTemplates);
3703
3759
  }
3704
3760
  /**
3705
3761
  * Walk every page of a paginated list verb, aggregate, and write ONE
@@ -3707,8 +3763,7 @@ var Client = class extends require_src.Protocol {
3707
3763
  * methods' no-`cursor` auto-aggregate path. Page 1's result object is
3708
3764
  * mutated in place (its items array is extended; `nextCursor` is
3709
3765
  * cleared); page-1 metadata (`ttlMs`, `cacheScope`, `_meta`) is preserved.
3710
- * A `nextCursor` that repeats stops the walk (defence against a
3711
- * non-converging server, mcp.d's `drainList` guard);
3766
+ * A page with the same items and `nextCursor` as the previous page ends the walk;
3712
3767
  * {@linkcode ClientOptions.listMaxPages} is a hard cap — hitting it
3713
3768
  * throws, so a partial aggregate is never cached. The
3714
3769
  * captured-generation guard skips the write when a `list_changed` landed
@@ -3723,7 +3778,7 @@ var Client = class extends require_src.Protocol {
3723
3778
  * trace context) supplied to the public `list*()` reaches every wire
3724
3779
  * request the walk issues.
3725
3780
  */
3726
- async _listAllPages(method, baseParams, options, append, finalize) {
3781
+ async _listAllPages(method, baseParams, options, items, finalize) {
3727
3782
  const bypass = options?.cacheMode === "bypass";
3728
3783
  const generation = this._cache.captureGeneration(method);
3729
3784
  const acc = await this.request({
@@ -3731,14 +3786,13 @@ var Client = class extends require_src.Protocol {
3731
3786
  ...baseParams && { params: { ...baseParams } }
3732
3787
  }, options);
3733
3788
  let cursor = acc.nextCursor;
3734
- const seen = /* @__PURE__ */ new Set();
3789
+ let previous = acc;
3735
3790
  let pages = 1;
3736
- while (cursor !== void 0 && !seen.has(cursor)) {
3791
+ while (cursor !== void 0) {
3737
3792
  if (this._listMaxPages !== 0 && pages >= this._listMaxPages) throw new require_src.SdkError(require_src.SdkErrorCode.ListPaginationExceeded, `${method}: exceeded listMaxPages (${this._listMaxPages}); server pagination did not terminate`, {
3738
3793
  method,
3739
3794
  listMaxPages: this._listMaxPages
3740
3795
  });
3741
- seen.add(cursor);
3742
3796
  const page = await this.request({
3743
3797
  method,
3744
3798
  params: {
@@ -3746,7 +3800,9 @@ var Client = class extends require_src.Protocol {
3746
3800
  cursor
3747
3801
  }
3748
3802
  }, options);
3749
- append(acc, page);
3803
+ if (page.nextCursor === cursor && JSON.stringify(items(page)) === JSON.stringify(items(previous))) break;
3804
+ items(acc).push(...items(page));
3805
+ previous = page;
3750
3806
  cursor = page.nextCursor;
3751
3807
  pages++;
3752
3808
  }
@@ -4007,19 +4063,22 @@ var Client = class extends require_src.Protocol {
4007
4063
  notifications: filter
4008
4064
  }
4009
4065
  };
4066
+ const routeSendFailure = (error) => {
4067
+ settle({
4068
+ cause: "remote",
4069
+ error: error instanceof Error ? error : new Error(String(error))
4070
+ });
4071
+ };
4010
4072
  try {
4011
- await this.transport.send(jsonrpcRequest, {
4073
+ this.transport.send(jsonrpcRequest, {
4012
4074
  requestSignal: requestAbort.signal,
4013
4075
  onRequestStreamEnd: () => settle({
4014
4076
  cause: "remote",
4015
4077
  error: /* @__PURE__ */ new Error("subscriptions/listen: stream ended")
4016
4078
  })
4017
- });
4079
+ }).catch(routeSendFailure);
4018
4080
  } catch (error) {
4019
- settle({
4020
- cause: "remote",
4021
- error: error instanceof Error ? error : new Error(String(error))
4022
- });
4081
+ routeSendFailure(error);
4023
4082
  }
4024
4083
  return {
4025
4084
  honoredFilter: await opening,
@@ -4271,7 +4330,7 @@ var Client = class extends require_src.Protocol {
4271
4330
  }
4272
4331
  const hit = await this._serveFromCache("tools/list", void 0, options);
4273
4332
  if (hit !== void 0) return hit;
4274
- return this._listAllPages("tools/list", params, options, (acc, page) => acc.tools.push(...page.tools), (acc) => this._excludeInvalidXMcpHeaderTools(acc));
4333
+ return this._listAllPages("tools/list", params, options, (r) => r.tools, (acc) => this._excludeInvalidXMcpHeaderTools(acc));
4275
4334
  }
4276
4335
  /**
4277
4336
  * SEP-2243 (protocol revision 2026-07-28): a Streamable HTTP client MUST
@@ -4384,7 +4443,7 @@ async function requestJwtAuthorizationGrant(options) {
4384
4443
  });
4385
4444
  if (clientSecret) params.set("client_secret", clientSecret);
4386
4445
  if (scope) params.set("scope", scope);
4387
- const response = await fetchFn(tokenUrl, {
4446
+ const response = await require_src.fetchWithinOrigin(fetchFn)(tokenUrl, {
4388
4447
  method: "POST",
4389
4448
  headers: { "Content-Type": "application/x-www-form-urlencoded" },
4390
4449
  body: params.toString()
@@ -4477,7 +4536,7 @@ async function exchangeJwtAuthGrant(options) {
4477
4536
  client_id: clientId,
4478
4537
  client_secret: clientSecret
4479
4538
  }, headers, params);
4480
- const response = await fetchFn(tokenUrl, {
4539
+ const response = await require_src.fetchWithinOrigin(fetchFn)(tokenUrl, {
4481
4540
  method: "POST",
4482
4541
  headers,
4483
4542
  body: params.toString()
@@ -4492,7 +4551,7 @@ async function exchangeJwtAuthGrant(options) {
4492
4551
  throw new Error(`JWT grant exchange failed with status ${response.status}: ${JSON.stringify(errorBody)}`);
4493
4552
  }
4494
4553
  const responseBody = await response.json();
4495
- const parseResult = _modelcontextprotocol_core_internal.OAuthTokensSchema.safeParse(responseBody);
4554
+ const parseResult = _modelcontextprotocol_core_internal.OAuthTokensSchema.safeParse(require_src.withoutIssuer(responseBody));
4496
4555
  if (!parseResult.success) throw new Error(`Invalid token response: ${parseResult.error.message}`);
4497
4556
  return parseResult.data;
4498
4557
  }
@@ -4997,6 +5056,7 @@ var SSEClientTransport = class {
4997
5056
  _skipIssuerMetadataValidation;
4998
5057
  _fetch;
4999
5058
  _fetchWithInit;
5059
+ _redirectPolicy;
5000
5060
  _dpop;
5001
5061
  _protocolVersion;
5002
5062
  onclose;
@@ -5018,9 +5078,21 @@ var SSEClientTransport = class {
5018
5078
  this._fetch = this._dpop(opts.fetch ?? fetch);
5019
5079
  }
5020
5080
  } else this._authProvider = opts?.authProvider;
5081
+ this._redirectPolicy = opts?.redirectPolicy;
5021
5082
  this._fetchWithInit = require_src.createFetchWithInit(opts?.fetch, opts?.requestInit);
5083
+ if (this._redirectPolicy === "follow") this._fetchWithInit = require_src.fetchLeavingRedirects(this._fetchWithInit);
5022
5084
  }
5023
5085
  _last401Response;
5086
+ _connectAuthRetried = false;
5087
+ /** `baseFetch` with redirects handled as `redirectPolicy` says. */
5088
+ _redirects(baseFetch) {
5089
+ return this._redirectPolicy === "follow" ? baseFetch : require_src.fetchWithinOrigin(baseFetch);
5090
+ }
5091
+ /** Error text for a redirect `response` that was not followed, or `undefined` for any other response. */
5092
+ _unfollowedRedirect(url, response) {
5093
+ const text = this._redirectPolicy === "follow" ? void 0 : require_src.unfollowedRedirect(url, response);
5094
+ return text && `${text} (redirectPolicy: 'same-origin')`;
5095
+ }
5024
5096
  async _commonHeaders() {
5025
5097
  const headers = new Headers(this._requestInit?.headers || void 0);
5026
5098
  let token;
@@ -5035,7 +5107,8 @@ var SSEClientTransport = class {
5035
5107
  }
5036
5108
  _startOrAuth() {
5037
5109
  const eventSourceFetch = this._eventSourceInit?.fetch;
5038
- const fetchImpl = eventSourceFetch ? this._dpop?.(eventSourceFetch) ?? eventSourceFetch : this._fetch ?? fetch;
5110
+ const fetchImpl = this._redirects(eventSourceFetch ? this._dpop?.(eventSourceFetch) ?? eventSourceFetch : this._fetch ?? fetch);
5111
+ let redirect;
5039
5112
  return new Promise((resolve, reject) => {
5040
5113
  this._eventSource = new eventsource.EventSource(this._url.href, {
5041
5114
  ...this._eventSourceInit,
@@ -5046,6 +5119,7 @@ var SSEClientTransport = class {
5046
5119
  ...init,
5047
5120
  headers
5048
5121
  });
5122
+ redirect = this._unfollowedRedirect(url, response);
5049
5123
  if (response.status === 401) {
5050
5124
  this._last401Response = response;
5051
5125
  if (response.headers.has("www-authenticate")) {
@@ -5060,31 +5134,42 @@ var SSEClientTransport = class {
5060
5134
  this._abortController = new AbortController();
5061
5135
  this._eventSource.onerror = (event) => {
5062
5136
  if (event.code === 401 && this._authProvider) {
5063
- if (this._authProvider.onUnauthorized && this._last401Response) {
5137
+ if (this._authProvider.onUnauthorized && this._last401Response && !this._connectAuthRetried) {
5064
5138
  const response = this._last401Response;
5065
5139
  this._last401Response = void 0;
5140
+ this._connectAuthRetried = true;
5066
5141
  this._eventSource?.close();
5067
5142
  this._authProvider.onUnauthorized({
5068
5143
  response,
5069
5144
  serverUrl: this._url,
5070
5145
  fetchFn: this._fetchWithInit
5071
5146
  }).then(() => this._startOrAuth().then(resolve, reject), (error$2) => {
5147
+ this._connectAuthRetried = false;
5072
5148
  markAuthSeamEscape(error$2);
5073
5149
  this.onerror?.(error$2);
5074
5150
  reject(error$2);
5075
5151
  });
5076
5152
  return;
5077
5153
  }
5078
- const error$1 = markAuthSeamEscape(new UnauthorizedError());
5154
+ const retried = this._connectAuthRetried;
5155
+ this._connectAuthRetried = false;
5156
+ const error$1 = markAuthSeamEscape(retried ? new require_src.SdkHttpError(require_src.SdkErrorCode.ClientHttpAuthentication, "Server returned 401 after re-authentication", {
5157
+ status: 401,
5158
+ statusText: this._last401Response?.statusText ?? ""
5159
+ }) : new UnauthorizedError());
5160
+ this._last401Response = void 0;
5079
5161
  reject(error$1);
5080
5162
  this.onerror?.(error$1);
5081
5163
  return;
5082
5164
  }
5083
- const error = new SseError(event.code, event.message, event);
5165
+ this._connectAuthRetried = false;
5166
+ const error = new SseError(event.code, redirect ?? event.message, event);
5084
5167
  reject(error);
5085
5168
  this.onerror?.(error);
5086
5169
  };
5087
- this._eventSource.onopen = () => {};
5170
+ this._eventSource.onopen = () => {
5171
+ this._connectAuthRetried = false;
5172
+ };
5088
5173
  this._eventSource.addEventListener("endpoint", (event) => {
5089
5174
  const messageEvent = event;
5090
5175
  try {
@@ -5151,7 +5236,7 @@ var SSEClientTransport = class {
5151
5236
  body: JSON.stringify(message),
5152
5237
  signal: this._abortController?.signal
5153
5238
  };
5154
- const response = await (this._fetch ?? fetch)(this._endpoint, init);
5239
+ const response = await this._redirects(this._fetch ?? fetch)(this._endpoint, init);
5155
5240
  if (!response.ok) {
5156
5241
  if (response.status === 401 && this._authProvider) {
5157
5242
  if (response.headers.has("www-authenticate")) {
@@ -5180,7 +5265,7 @@ var SSEClientTransport = class {
5180
5265
  throw markAuthSeamEscape(new UnauthorizedError());
5181
5266
  }
5182
5267
  const text = await response.text?.().catch(() => null);
5183
- throw new Error(`Error POSTing to endpoint (HTTP ${response.status}): ${text}`);
5268
+ throw new Error(`Error POSTing to endpoint (HTTP ${response.status}): ${this._unfollowedRedirect(this._endpoint, response) ?? text}`);
5184
5269
  }
5185
5270
  await response.text?.().catch(() => {});
5186
5271
  } catch (error) {
@@ -5265,6 +5350,7 @@ var StreamableHTTPClientTransport = class {
5265
5350
  _skipIssuerMetadataValidation;
5266
5351
  _fetch;
5267
5352
  _fetchWithInit;
5353
+ _redirectPolicy;
5268
5354
  _sessionId;
5269
5355
  _reconnectionOptions;
5270
5356
  _protocolVersion;
@@ -5295,7 +5381,9 @@ var StreamableHTTPClientTransport = class {
5295
5381
  this._authProvider = adaptOAuthProvider(opts.authProvider, { skipIssuerMetadataValidation: opts.skipIssuerMetadataValidation });
5296
5382
  if (opts.authProvider.dpop) this._fetch = withDpopFromProvider(opts.authProvider)(opts.fetch ?? fetch);
5297
5383
  } else this._authProvider = opts?.authProvider;
5384
+ this._redirectPolicy = opts?.redirectPolicy;
5298
5385
  this._fetchWithInit = require_src.createFetchWithInit(opts?.fetch, opts?.requestInit);
5386
+ if (this._redirectPolicy === "follow") this._fetchWithInit = require_src.fetchLeavingRedirects(this._fetchWithInit);
5299
5387
  this._sessionId = opts?.sessionId;
5300
5388
  this._protocolVersion = opts?.protocolVersion;
5301
5389
  this._reconnectionOptions = opts?.reconnectionOptions ?? DEFAULT_STREAMABLE_HTTP_RECONNECTION_OPTIONS;
@@ -5347,6 +5435,15 @@ var StreamableHTTPClientTransport = class {
5347
5435
  skipIssuerMetadataValidation: this._skipIssuerMetadataValidation
5348
5436
  });
5349
5437
  }
5438
+ /** `baseFetch` with redirects handled as `redirectPolicy` says. */
5439
+ _redirects(baseFetch) {
5440
+ return this._redirectPolicy === "follow" ? baseFetch : require_src.fetchWithinOrigin(baseFetch);
5441
+ }
5442
+ /** Error text for a redirect `response` that was not followed, or `undefined` for any other response. */
5443
+ _unfollowedRedirect(url, response) {
5444
+ const text = this._redirectPolicy === "follow" ? void 0 : require_src.unfollowedRedirect(url, response);
5445
+ return text && `${text} (redirectPolicy: 'same-origin')`;
5446
+ }
5350
5447
  async _commonHeaders() {
5351
5448
  const headers = new Headers(this._requestInit?.headers || void 0);
5352
5449
  let token;
@@ -5398,7 +5495,7 @@ var StreamableHTTPClientTransport = class {
5398
5495
  if (resumptionToken) headers.set("last-event-id", resumptionToken);
5399
5496
  const transportSignal = this._abortController?.signal;
5400
5497
  const signal = requestSignal !== void 0 && transportSignal !== void 0 ? anySignal(transportSignal, requestSignal) : requestSignal ?? transportSignal;
5401
- const response = await (this._fetch ?? fetch)(this._url, {
5498
+ const response = await this._redirects(this._fetch ?? fetch)(this._url, {
5402
5499
  ...this._requestInit,
5403
5500
  method: "GET",
5404
5501
  headers,
@@ -5450,7 +5547,8 @@ var StreamableHTTPClientTransport = class {
5450
5547
  options.onRequestStreamEnd?.();
5451
5548
  return;
5452
5549
  }
5453
- throw new require_src.SdkHttpError(require_src.SdkErrorCode.ClientHttpFailedToOpenStream, `Failed to open SSE stream: ${response.statusText}`, {
5550
+ const reason = this._unfollowedRedirect(this._url, response) ?? response.statusText;
5551
+ throw new require_src.SdkHttpError(require_src.SdkErrorCode.ClientHttpFailedToOpenStream, `Failed to open SSE stream: ${reason}`, {
5454
5552
  status: response.status,
5455
5553
  statusText: response.statusText
5456
5554
  });
@@ -5639,7 +5737,7 @@ var StreamableHTTPClientTransport = class {
5639
5737
  body: JSON.stringify(message),
5640
5738
  signal
5641
5739
  };
5642
- const response = await (this._fetch ?? fetch)(this._url, init);
5740
+ const response = await this._redirects(this._fetch ?? fetch)(this._url, init);
5643
5741
  if (isHandshake && response.ok) this._sessionId = response.headers.get("mcp-session-id") || void 0;
5644
5742
  if (!response.ok) {
5645
5743
  if (response.status === 401 && this._authProvider) {
@@ -5690,7 +5788,8 @@ var StreamableHTTPClientTransport = class {
5690
5788
  return;
5691
5789
  }
5692
5790
  } catch {}
5693
- throw new require_src.SdkHttpError(require_src.SdkErrorCode.ClientHttpNotImplemented, `Error POSTing to endpoint: ${text}`, {
5791
+ const reason = this._unfollowedRedirect(this._url, response) ?? text;
5792
+ throw new require_src.SdkHttpError(require_src.SdkErrorCode.ClientHttpNotImplemented, `Error POSTing to endpoint: ${reason}`, {
5694
5793
  status: response.status,
5695
5794
  statusText: response.statusText,
5696
5795
  text
@@ -5747,9 +5846,9 @@ var StreamableHTTPClientTransport = class {
5747
5846
  headers,
5748
5847
  signal: this._abortController?.signal
5749
5848
  };
5750
- const response = await (this._fetch ?? fetch)(this._url, init);
5849
+ const response = await this._redirects(this._fetch ?? fetch)(this._url, init);
5751
5850
  await response.text?.().catch(() => {});
5752
- if (!response.ok && response.status !== 405) throw new require_src.SdkHttpError(require_src.SdkErrorCode.ClientHttpFailedToTerminateSession, `Failed to terminate session: ${response.statusText}`, {
5851
+ if (!response.ok && response.status !== 405) throw new require_src.SdkHttpError(require_src.SdkErrorCode.ClientHttpFailedToTerminateSession, `Failed to terminate session: ${this._unfollowedRedirect(this._url, response) ?? response.statusText}`, {
5753
5852
  status: response.status,
5754
5853
  statusText: response.statusText
5755
5854
  });