@ai-sdk/mcp 2.0.51 → 2.0.53

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,25 @@
1
1
  # @ai-sdk/mcp
2
2
 
3
+ ## 2.0.53
4
+
5
+ ### Patch Changes
6
+
7
+ - 4b5cb49: fix(mcp): avoid duplicate legacy SSE OAuth refreshes for stale 401 responses
8
+ - Updated dependencies [0455398]
9
+ - @ai-sdk/provider-utils@5.0.44
10
+
11
+ ## 2.0.52
12
+
13
+ ### Patch Changes
14
+
15
+ - Updated dependencies [215b25e]
16
+ - Updated dependencies [d4d96bf]
17
+ - Updated dependencies [a7dd893]
18
+ - Updated dependencies [3456e2c]
19
+ - Updated dependencies [c4e76de]
20
+ - @ai-sdk/provider-utils@5.0.43
21
+ - @ai-sdk/provider@4.0.17
22
+
3
23
  ## 2.0.51
4
24
 
5
25
  ### Patch Changes
package/dist/index.js CHANGED
@@ -1562,6 +1562,30 @@ var SseMCPTransport = class {
1562
1562
  getRuntimeEnvironmentUserAgent()
1563
1563
  );
1564
1564
  }
1565
+ /**
1566
+ * Runs a single OAuth recovery flow for concurrent 401 responses.
1567
+ */
1568
+ authorizeOnce(resourceMetadataUrl, scope) {
1569
+ if (!this.authProvider) {
1570
+ return Promise.resolve("REDIRECT");
1571
+ }
1572
+ if (!this.authPromise) {
1573
+ this.authPromise = auth(this.authProvider, {
1574
+ serverUrl: this.url,
1575
+ resourceMetadataUrl,
1576
+ scope,
1577
+ fetchFn: this.fetchFn
1578
+ }).finally(() => {
1579
+ this.authPromise = void 0;
1580
+ });
1581
+ }
1582
+ return this.authPromise;
1583
+ }
1584
+ async accessTokenChanged(requestAuthorization) {
1585
+ var _a3, _b3;
1586
+ const accessToken = (_b3 = await ((_a3 = this.authProvider) == null ? void 0 : _a3.tokens())) == null ? void 0 : _b3.access_token;
1587
+ return accessToken != null && requestAuthorization !== `Bearer ${accessToken}`;
1588
+ }
1565
1589
  async start() {
1566
1590
  return new Promise((resolve, reject) => {
1567
1591
  if (this.connected) {
@@ -1583,12 +1607,10 @@ var SseMCPTransport = class {
1583
1607
  const { resourceMetadataUrl, scope } = extractWWWAuthenticateParams(response);
1584
1608
  this.resourceMetadataUrl = resourceMetadataUrl;
1585
1609
  try {
1586
- const result = await auth(this.authProvider, {
1587
- serverUrl: this.url,
1588
- resourceMetadataUrl: this.resourceMetadataUrl,
1589
- scope,
1590
- fetchFn: this.fetchFn
1591
- });
1610
+ const result = await this.authorizeOnce(
1611
+ this.resourceMetadataUrl,
1612
+ scope
1613
+ );
1592
1614
  if (result !== "AUTHORIZED") {
1593
1615
  const error = new UnauthorizedError();
1594
1616
  (_b3 = this.onerror) == null ? void 0 : _b3.call(this, error);
@@ -1701,7 +1723,7 @@ var SseMCPTransport = class {
1701
1723
  const transportSignal = (_b3 = this.abortController) == null ? void 0 : _b3.signal;
1702
1724
  const requestSignal = (options == null ? void 0 : options.signal) == null ? transportSignal : transportSignal == null ? options.signal : AbortSignal.any([transportSignal, options.signal]);
1703
1725
  const attempt = async (triedAuth = false) => {
1704
- var _a4, _b4;
1726
+ var _a4, _b4, _c;
1705
1727
  try {
1706
1728
  const headers = await this.commonHeaders({
1707
1729
  "Content-Type": "application/json"
@@ -1715,14 +1737,17 @@ var SseMCPTransport = class {
1715
1737
  };
1716
1738
  const response = await this.fetchFn(endpoint.href, init);
1717
1739
  if (response.status === 401 && this.authProvider && !triedAuth) {
1740
+ if (await this.accessTokenChanged(
1741
+ (_a4 = new Headers(headers).get("authorization")) != null ? _a4 : void 0
1742
+ )) {
1743
+ return attempt(true);
1744
+ }
1718
1745
  const { resourceMetadataUrl, scope } = extractWWWAuthenticateParams(response);
1719
1746
  this.resourceMetadataUrl = resourceMetadataUrl;
1720
- const result = await auth(this.authProvider, {
1721
- serverUrl: this.url,
1722
- resourceMetadataUrl: this.resourceMetadataUrl,
1723
- scope,
1724
- fetchFn: this.fetchFn
1725
- });
1747
+ const result = await this.authorizeOnce(
1748
+ this.resourceMetadataUrl,
1749
+ scope
1750
+ );
1726
1751
  if (result !== "AUTHORIZED") {
1727
1752
  throw new UnauthorizedError();
1728
1753
  }
@@ -1739,10 +1764,10 @@ var SseMCPTransport = class {
1739
1764
  throw error;
1740
1765
  }
1741
1766
  } catch (error) {
1742
- if ((_a4 = options == null ? void 0 : options.signal) == null ? void 0 : _a4.aborted) {
1767
+ if ((_b4 = options == null ? void 0 : options.signal) == null ? void 0 : _b4.aborted) {
1743
1768
  throw error;
1744
1769
  }
1745
- (_b4 = this.onerror) == null ? void 0 : _b4.call(this, error);
1770
+ (_c = this.onerror) == null ? void 0 : _c.call(this, error);
1746
1771
  throw error;
1747
1772
  }
1748
1773
  };