@ai-sdk/mcp 2.0.64 → 2.0.66
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 +12 -0
- package/dist/index.d.ts +33 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +28 -7
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/error/oauth-error.ts +18 -0
- package/src/index.ts +4 -0
- package/src/tool/oauth.ts +24 -4
package/package.json
CHANGED
package/src/error/oauth-error.ts
CHANGED
|
@@ -42,6 +42,24 @@ export class UnauthorizedClientError extends MCPClientOAuthError {
|
|
|
42
42
|
static errorCode = 'unauthorized_client';
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
+
const mismatchName = 'AI_AuthorizationServerMismatchError';
|
|
46
|
+
const mismatchMarker = `vercel.ai.error.${mismatchName}`;
|
|
47
|
+
const mismatchSymbol = Symbol.for(mismatchMarker);
|
|
48
|
+
|
|
49
|
+
export class AuthorizationServerMismatchError extends MCPClientOAuthError {
|
|
50
|
+
private readonly [mismatchSymbol] = true;
|
|
51
|
+
|
|
52
|
+
static errorCode = 'authorization_server_mismatch';
|
|
53
|
+
|
|
54
|
+
constructor({ message, cause }: { message: string; cause?: unknown }) {
|
|
55
|
+
super({ name: 'AuthorizationServerMismatchError', message, cause });
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
static isInstance(error: unknown): error is AuthorizationServerMismatchError {
|
|
59
|
+
return AISDKError.hasMarker(error, mismatchMarker);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
45
63
|
export const OAUTH_ERRORS = {
|
|
46
64
|
[ServerError.errorCode]: ServerError,
|
|
47
65
|
[InvalidClientError.errorCode]: InvalidClientError,
|
package/src/index.ts
CHANGED
|
@@ -41,6 +41,10 @@ export type {
|
|
|
41
41
|
ClientCapabilities as MCPClientCapabilities,
|
|
42
42
|
} from './tool/types';
|
|
43
43
|
export { auth, UnauthorizedError } from './tool/oauth';
|
|
44
|
+
export {
|
|
45
|
+
MCPClientOAuthError,
|
|
46
|
+
AuthorizationServerMismatchError,
|
|
47
|
+
} from './error/oauth-error';
|
|
44
48
|
export type {
|
|
45
49
|
OAuthAuthorizationServerInformation,
|
|
46
50
|
OAuthClientProvider,
|
package/src/tool/oauth.ts
CHANGED
|
@@ -20,6 +20,7 @@ import {
|
|
|
20
20
|
InvalidClientError,
|
|
21
21
|
InvalidGrantError,
|
|
22
22
|
UnauthorizedClientError,
|
|
23
|
+
AuthorizationServerMismatchError,
|
|
23
24
|
} from '../error/oauth-error';
|
|
24
25
|
import {
|
|
25
26
|
resourceUrlFromServerUrl,
|
|
@@ -81,9 +82,15 @@ export interface OAuthClientProvider {
|
|
|
81
82
|
* If implemented, provides a way for the client to invalidate (e.g. delete) the specified
|
|
82
83
|
* credentials, in the case where the server has indicated that they are no longer valid.
|
|
83
84
|
* This avoids requiring the user to intervene manually.
|
|
85
|
+
*
|
|
86
|
+
* For token invalidation, context identifies the token generation being invalidated
|
|
87
|
+
* when available. Providers sharing storage must atomically compare and delete
|
|
88
|
+
* that generation so a concurrent refresh's tokens are preserved. Omitting or
|
|
89
|
+
* ignoring context retains unconditional invalidation.
|
|
84
90
|
*/
|
|
85
91
|
invalidateCredentials?(
|
|
86
92
|
scope: 'all' | 'client' | 'tokens' | 'verifier',
|
|
93
|
+
context?: { tokens: OAuthTokens },
|
|
87
94
|
): void | Promise<void>;
|
|
88
95
|
get redirectUrl(): string | URL;
|
|
89
96
|
get clientMetadata(): OAuthClientMetadata;
|
|
@@ -354,7 +361,7 @@ function assertAuthorizationServerInformationMatches({
|
|
|
354
361
|
storedAuthorizationServerInformation.tokenEndpoint !==
|
|
355
362
|
currentAuthorizationServerInformation.tokenEndpoint
|
|
356
363
|
) {
|
|
357
|
-
throw new
|
|
364
|
+
throw new AuthorizationServerMismatchError({
|
|
358
365
|
message:
|
|
359
366
|
'OAuth authorization server metadata does not match the metadata that issued the stored credentials',
|
|
360
367
|
});
|
|
@@ -1261,8 +1268,9 @@ export async function auth(
|
|
|
1261
1268
|
fetchFn?: FetchFunction;
|
|
1262
1269
|
},
|
|
1263
1270
|
): Promise<AuthResult> {
|
|
1271
|
+
const refreshAttempt: { tokens?: OAuthTokens } = {};
|
|
1264
1272
|
try {
|
|
1265
|
-
return await authInternal(provider, options);
|
|
1273
|
+
return await authInternal(provider, options, refreshAttempt);
|
|
1266
1274
|
} catch (error) {
|
|
1267
1275
|
if (
|
|
1268
1276
|
error instanceof InvalidClientError ||
|
|
@@ -1278,7 +1286,13 @@ export async function auth(
|
|
|
1278
1286
|
await provider.invalidateCredentials?.('all');
|
|
1279
1287
|
return await authInternal(provider, options);
|
|
1280
1288
|
} else if (error instanceof InvalidGrantError) {
|
|
1281
|
-
|
|
1289
|
+
if (refreshAttempt.tokens) {
|
|
1290
|
+
await provider.invalidateCredentials?.('tokens', {
|
|
1291
|
+
tokens: refreshAttempt.tokens,
|
|
1292
|
+
});
|
|
1293
|
+
} else {
|
|
1294
|
+
await provider.invalidateCredentials?.('tokens');
|
|
1295
|
+
}
|
|
1282
1296
|
return await authInternal(provider, options);
|
|
1283
1297
|
}
|
|
1284
1298
|
|
|
@@ -1336,6 +1350,7 @@ async function authInternal(
|
|
|
1336
1350
|
resourceMetadataUrl?: URL;
|
|
1337
1351
|
fetchFn?: FetchFunction;
|
|
1338
1352
|
},
|
|
1353
|
+
refreshAttempt?: { tokens?: OAuthTokens },
|
|
1339
1354
|
): Promise<AuthResult> {
|
|
1340
1355
|
let resourceMetadata: OAuthProtectedResourceMetadata | undefined;
|
|
1341
1356
|
let authorizationServerUrl: string | URL | undefined;
|
|
@@ -1554,11 +1569,16 @@ async function authInternal(
|
|
|
1554
1569
|
currentAuthorizationServerInformation,
|
|
1555
1570
|
});
|
|
1556
1571
|
} else {
|
|
1557
|
-
await provider.invalidateCredentials?.('tokens'
|
|
1572
|
+
await provider.invalidateCredentials?.('tokens', {
|
|
1573
|
+
tokens: { ...tokens },
|
|
1574
|
+
});
|
|
1558
1575
|
}
|
|
1559
1576
|
|
|
1560
1577
|
try {
|
|
1561
1578
|
if (storedAuthorizationServerInformation) {
|
|
1579
|
+
if (refreshAttempt) {
|
|
1580
|
+
refreshAttempt.tokens = { ...tokens };
|
|
1581
|
+
}
|
|
1562
1582
|
// Attempt to refresh the token
|
|
1563
1583
|
const newTokens = await refreshAuthorization(authorizationServerUrl, {
|
|
1564
1584
|
metadata,
|