@ai-sdk/mcp 1.0.42 → 1.0.43

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-sdk/mcp",
3
- "version": "1.0.42",
3
+ "version": "1.0.43",
4
4
  "license": "Apache-2.0",
5
5
  "sideEffects": false,
6
6
  "main": "./dist/index.js",
@@ -16,6 +16,7 @@ import {
16
16
  extractResourceMetadataUrl,
17
17
  UnauthorizedError,
18
18
  auth,
19
+ type AuthResult,
19
20
  type OAuthClientProvider,
20
21
  } from './oauth';
21
22
  import { LATEST_PROTOCOL_VERSION } from './types';
@@ -37,6 +38,7 @@ export class HttpMCPTransport implements MCPTransport {
37
38
  private inboundSseConnection?: { close: () => void };
38
39
  private redirectMode: RequestRedirect;
39
40
  private fetchFn: FetchFunction;
41
+ private authPromise?: Promise<AuthResult>;
40
42
 
41
43
  // Inbound SSE resumption and reconnection state
42
44
  private lastInboundEventId?: string;
@@ -100,6 +102,27 @@ export class HttpMCPTransport implements MCPTransport {
100
102
  );
101
103
  }
102
104
 
105
+ /**
106
+ * Runs a single OAuth recovery flow for concurrent 401 responses.
107
+ */
108
+ private authorizeOnce(resourceMetadataUrl?: URL): Promise<AuthResult> {
109
+ if (!this.authProvider) {
110
+ return Promise.resolve('REDIRECT');
111
+ }
112
+
113
+ if (!this.authPromise) {
114
+ this.authPromise = auth(this.authProvider, {
115
+ serverUrl: this.url,
116
+ resourceMetadataUrl,
117
+ fetchFn: this.fetchFn,
118
+ }).finally(() => {
119
+ this.authPromise = undefined;
120
+ });
121
+ }
122
+
123
+ return this.authPromise;
124
+ }
125
+
103
126
  async start(): Promise<void> {
104
127
  if (this.abortController) {
105
128
  throw new MCPClientError({
@@ -160,11 +183,7 @@ export class HttpMCPTransport implements MCPTransport {
160
183
  if (response.status === 401 && this.authProvider && !triedAuth) {
161
184
  this.resourceMetadataUrl = extractResourceMetadataUrl(response);
162
185
  try {
163
- const result = await auth(this.authProvider, {
164
- serverUrl: this.url,
165
- resourceMetadataUrl: this.resourceMetadataUrl,
166
- fetchFn: this.fetchFn,
167
- });
186
+ const result = await this.authorizeOnce(this.resourceMetadataUrl);
168
187
  if (result !== 'AUTHORIZED') {
169
188
  const error = new UnauthorizedError();
170
189
  throw error;
@@ -340,11 +359,7 @@ export class HttpMCPTransport implements MCPTransport {
340
359
  if (response.status === 401 && this.authProvider && !triedAuth) {
341
360
  this.resourceMetadataUrl = extractResourceMetadataUrl(response);
342
361
  try {
343
- const result = await auth(this.authProvider, {
344
- serverUrl: this.url,
345
- resourceMetadataUrl: this.resourceMetadataUrl,
346
- fetchFn: this.fetchFn,
347
- });
362
+ const result = await this.authorizeOnce(this.resourceMetadataUrl);
348
363
  if (result !== 'AUTHORIZED') {
349
364
  const error = new UnauthorizedError();
350
365
  this.onerror?.(error);