@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 +20 -0
- package/dist/index.js +40 -15
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/src/tool/mcp-sse-transport.ts +50 -10
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-sdk/mcp",
|
|
3
|
-
"version": "2.0.
|
|
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.
|
|
35
|
-
"@ai-sdk/provider-utils": "5.0.
|
|
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
|
|
115
|
-
|
|
116
|
-
resourceMetadataUrl: this.resourceMetadataUrl,
|
|
150
|
+
const result = await this.authorizeOnce(
|
|
151
|
+
this.resourceMetadataUrl,
|
|
117
152
|
scope,
|
|
118
|
-
|
|
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
|
|
284
|
-
|
|
285
|
-
resourceMetadataUrl: this.resourceMetadataUrl,
|
|
325
|
+
const result = await this.authorizeOnce(
|
|
326
|
+
this.resourceMetadataUrl,
|
|
286
327
|
scope,
|
|
287
|
-
|
|
288
|
-
});
|
|
328
|
+
);
|
|
289
329
|
if (result !== 'AUTHORIZED') {
|
|
290
330
|
throw new UnauthorizedError();
|
|
291
331
|
}
|