@ai-sdk/mcp 1.0.81 → 1.0.82

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @ai-sdk/mcp
2
2
 
3
+ ## 1.0.82
4
+
5
+ ### Patch Changes
6
+
7
+ - 1620182: fix(mcp): avoid duplicate legacy SSE OAuth refreshes for stale 401 responses
8
+
3
9
  ## 1.0.81
4
10
 
5
11
  ### Patch Changes
package/dist/index.js CHANGED
@@ -1434,6 +1434,30 @@ var SseMCPTransport = class {
1434
1434
  (0, import_provider_utils3.getRuntimeEnvironmentUserAgent)()
1435
1435
  );
1436
1436
  }
1437
+ /**
1438
+ * Runs a single OAuth recovery flow for concurrent 401 responses.
1439
+ */
1440
+ authorizeOnce(resourceMetadataUrl, scope) {
1441
+ if (!this.authProvider) {
1442
+ return Promise.resolve("REDIRECT");
1443
+ }
1444
+ if (!this.authPromise) {
1445
+ this.authPromise = auth(this.authProvider, {
1446
+ serverUrl: this.url,
1447
+ resourceMetadataUrl,
1448
+ scope,
1449
+ fetchFn: this.fetchFn
1450
+ }).finally(() => {
1451
+ this.authPromise = void 0;
1452
+ });
1453
+ }
1454
+ return this.authPromise;
1455
+ }
1456
+ async accessTokenChanged(requestAuthorization) {
1457
+ var _a3, _b3;
1458
+ const accessToken = (_b3 = await ((_a3 = this.authProvider) == null ? void 0 : _a3.tokens())) == null ? void 0 : _b3.access_token;
1459
+ return accessToken != null && requestAuthorization !== `Bearer ${accessToken}`;
1460
+ }
1437
1461
  async start() {
1438
1462
  return new Promise((resolve, reject) => {
1439
1463
  if (this.connected) {
@@ -1455,12 +1479,10 @@ var SseMCPTransport = class {
1455
1479
  const { resourceMetadataUrl, scope } = extractWWWAuthenticateParams(response);
1456
1480
  this.resourceMetadataUrl = resourceMetadataUrl;
1457
1481
  try {
1458
- const result = await auth(this.authProvider, {
1459
- serverUrl: this.url,
1460
- resourceMetadataUrl: this.resourceMetadataUrl,
1461
- scope,
1462
- fetchFn: this.fetchFn
1463
- });
1482
+ const result = await this.authorizeOnce(
1483
+ this.resourceMetadataUrl,
1484
+ scope
1485
+ );
1464
1486
  if (result !== "AUTHORIZED") {
1465
1487
  const error = new UnauthorizedError();
1466
1488
  (_b3 = this.onerror) == null ? void 0 : _b3.call(this, error);
@@ -1573,7 +1595,7 @@ var SseMCPTransport = class {
1573
1595
  const transportSignal = (_b3 = this.abortController) == null ? void 0 : _b3.signal;
1574
1596
  const requestSignal = (options == null ? void 0 : options.signal) == null ? transportSignal : transportSignal == null ? options.signal : AbortSignal.any([transportSignal, options.signal]);
1575
1597
  const attempt = async (triedAuth = false) => {
1576
- var _a4, _b4;
1598
+ var _a4, _b4, _c;
1577
1599
  try {
1578
1600
  const headers = await this.commonHeaders({
1579
1601
  "Content-Type": "application/json"
@@ -1587,14 +1609,17 @@ var SseMCPTransport = class {
1587
1609
  };
1588
1610
  const response = await this.fetchFn(endpoint.href, init);
1589
1611
  if (response.status === 401 && this.authProvider && !triedAuth) {
1612
+ if (await this.accessTokenChanged(
1613
+ (_a4 = new Headers(headers).get("authorization")) != null ? _a4 : void 0
1614
+ )) {
1615
+ return attempt(true);
1616
+ }
1590
1617
  const { resourceMetadataUrl, scope } = extractWWWAuthenticateParams(response);
1591
1618
  this.resourceMetadataUrl = resourceMetadataUrl;
1592
- const result = await auth(this.authProvider, {
1593
- serverUrl: this.url,
1594
- resourceMetadataUrl: this.resourceMetadataUrl,
1595
- scope,
1596
- fetchFn: this.fetchFn
1597
- });
1619
+ const result = await this.authorizeOnce(
1620
+ this.resourceMetadataUrl,
1621
+ scope
1622
+ );
1598
1623
  if (result !== "AUTHORIZED") {
1599
1624
  throw new UnauthorizedError();
1600
1625
  }
@@ -1611,10 +1636,10 @@ var SseMCPTransport = class {
1611
1636
  throw error;
1612
1637
  }
1613
1638
  } catch (error) {
1614
- if ((_a4 = options == null ? void 0 : options.signal) == null ? void 0 : _a4.aborted) {
1639
+ if ((_b4 = options == null ? void 0 : options.signal) == null ? void 0 : _b4.aborted) {
1615
1640
  throw error;
1616
1641
  }
1617
- (_b4 = this.onerror) == null ? void 0 : _b4.call(this, error);
1642
+ (_c = this.onerror) == null ? void 0 : _c.call(this, error);
1618
1643
  throw error;
1619
1644
  }
1620
1645
  };