@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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-sdk/mcp",
3
- "version": "2.0.51",
3
+ "version": "2.0.53",
4
4
  "type": "module",
5
5
  "license": "Apache-2.0",
6
6
  "sideEffects": false,
@@ -31,8 +31,8 @@
31
31
  }
32
32
  },
33
33
  "dependencies": {
34
- "@ai-sdk/provider": "4.0.16",
35
- "@ai-sdk/provider-utils": "5.0.42",
34
+ "@ai-sdk/provider": "4.0.17",
35
+ "@ai-sdk/provider-utils": "5.0.44",
36
36
  "cross-spawn": "^7.0.6",
37
37
  "pkce-challenge": "^5.0.1"
38
38
  },
@@ -12,6 +12,7 @@ import {
12
12
  extractWWWAuthenticateParams,
13
13
  UnauthorizedError,
14
14
  auth,
15
+ type AuthResult,
15
16
  type OAuthClientProvider,
16
17
  } from './oauth';
17
18
  import { LATEST_LEGACY_PROTOCOL_VERSION } from './types';
@@ -33,6 +34,7 @@ export class SseMCPTransport implements MCPTransport {
33
34
  private resourceMetadataUrl?: URL;
34
35
  private redirectMode: RequestRedirect;
35
36
  private fetchFn: FetchFunction;
37
+ private authPromise?: Promise<AuthResult>;
36
38
 
37
39
  onclose?: () => void;
38
40
  onerror?: (error: unknown) => void;
@@ -87,6 +89,40 @@ export class SseMCPTransport implements MCPTransport {
87
89
  );
88
90
  }
89
91
 
92
+ /**
93
+ * Runs a single OAuth recovery flow for concurrent 401 responses.
94
+ */
95
+ private authorizeOnce(
96
+ resourceMetadataUrl?: URL,
97
+ scope?: string,
98
+ ): Promise<AuthResult> {
99
+ if (!this.authProvider) {
100
+ return Promise.resolve('REDIRECT');
101
+ }
102
+
103
+ if (!this.authPromise) {
104
+ this.authPromise = auth(this.authProvider, {
105
+ serverUrl: this.url,
106
+ resourceMetadataUrl,
107
+ scope,
108
+ fetchFn: this.fetchFn,
109
+ }).finally(() => {
110
+ this.authPromise = undefined;
111
+ });
112
+ }
113
+
114
+ return this.authPromise;
115
+ }
116
+
117
+ private async accessTokenChanged(
118
+ requestAuthorization: string | undefined,
119
+ ): Promise<boolean> {
120
+ const accessToken = (await this.authProvider?.tokens())?.access_token;
121
+ return (
122
+ accessToken != null && requestAuthorization !== `Bearer ${accessToken}`
123
+ );
124
+ }
125
+
90
126
  async start(): Promise<void> {
91
127
  return new Promise<void>((resolve, reject) => {
92
128
  if (this.connected) {
@@ -111,12 +147,10 @@ export class SseMCPTransport implements MCPTransport {
111
147
  extractWWWAuthenticateParams(response);
112
148
  this.resourceMetadataUrl = resourceMetadataUrl;
113
149
  try {
114
- const result = await auth(this.authProvider, {
115
- serverUrl: this.url,
116
- resourceMetadataUrl: this.resourceMetadataUrl,
150
+ const result = await this.authorizeOnce(
151
+ this.resourceMetadataUrl,
117
152
  scope,
118
- fetchFn: this.fetchFn,
119
- });
153
+ );
120
154
  if (result !== 'AUTHORIZED') {
121
155
  const error = new UnauthorizedError();
122
156
  this.onerror?.(error);
@@ -277,15 +311,21 @@ export class SseMCPTransport implements MCPTransport {
277
311
  const response = await this.fetchFn(endpoint.href, init);
278
312
 
279
313
  if (response.status === 401 && this.authProvider && !triedAuth) {
314
+ if (
315
+ await this.accessTokenChanged(
316
+ new Headers(headers).get('authorization') ?? undefined,
317
+ )
318
+ ) {
319
+ return attempt(true);
320
+ }
321
+
280
322
  const { resourceMetadataUrl, scope } =
281
323
  extractWWWAuthenticateParams(response);
282
324
  this.resourceMetadataUrl = resourceMetadataUrl;
283
- const result = await auth(this.authProvider, {
284
- serverUrl: this.url,
285
- resourceMetadataUrl: this.resourceMetadataUrl,
325
+ const result = await this.authorizeOnce(
326
+ this.resourceMetadataUrl,
286
327
  scope,
287
- fetchFn: this.fetchFn,
288
- });
328
+ );
289
329
  if (result !== 'AUTHORIZED') {
290
330
  throw new UnauthorizedError();
291
331
  }