@ai-sdk/mcp 1.0.45 → 1.0.47

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/dist/index.mjs CHANGED
@@ -312,15 +312,6 @@ import pkceChallenge from "pkce-challenge";
312
312
 
313
313
  // src/tool/oauth-types.ts
314
314
  import { z as z3 } from "zod/v4";
315
- var OAuthTokensSchema = z3.object({
316
- access_token: z3.string(),
317
- id_token: z3.string().optional(),
318
- // Optional for OAuth 2.1, but necessary in OpenID Connect
319
- token_type: z3.string(),
320
- expires_in: z3.number().optional(),
321
- scope: z3.string().optional(),
322
- refresh_token: z3.string().optional()
323
- }).strip();
324
315
  var SafeUrlSchema = z3.string().url().superRefine((val, ctx) => {
325
316
  if (!URL.canParse(val)) {
326
317
  ctx.addIssue({
@@ -337,6 +328,17 @@ var SafeUrlSchema = z3.string().url().superRefine((val, ctx) => {
337
328
  },
338
329
  { message: "URL cannot use javascript:, data:, or vbscript: scheme" }
339
330
  );
331
+ var OAuthTokensSchema = z3.object({
332
+ access_token: z3.string(),
333
+ id_token: z3.string().optional(),
334
+ // Optional for OAuth 2.1, but necessary in OpenID Connect
335
+ token_type: z3.string(),
336
+ expires_in: z3.number().optional(),
337
+ scope: z3.string().optional(),
338
+ refresh_token: z3.string().optional(),
339
+ authorization_server: SafeUrlSchema.optional(),
340
+ token_endpoint: SafeUrlSchema.optional()
341
+ }).strip();
340
342
  var OAuthProtectedResourceMetadataSchema = z3.object({
341
343
  resource: z3.string().url(),
342
344
  authorization_servers: z3.array(SafeUrlSchema).optional(),
@@ -389,7 +391,9 @@ var OAuthClientInformationSchema = z3.object({
389
391
  client_id: z3.string(),
390
392
  client_secret: z3.string().optional(),
391
393
  client_id_issued_at: z3.number().optional(),
392
- client_secret_expires_at: z3.number().optional()
394
+ client_secret_expires_at: z3.number().optional(),
395
+ authorization_server: SafeUrlSchema.optional(),
396
+ token_endpoint: SafeUrlSchema.optional()
393
397
  }).strip();
394
398
  var OAuthClientMetadataSchema = z3.object({
395
399
  redirect_uris: z3.array(SafeUrlSchema),
@@ -494,6 +498,106 @@ var UnauthorizedError = class extends Error {
494
498
  this.name = "UnauthorizedError";
495
499
  }
496
500
  };
501
+ function normalizeUrl(url) {
502
+ return new URL(url).href;
503
+ }
504
+ function createAuthorizationServerInformation(authorizationServerUrl, metadata) {
505
+ return {
506
+ authorizationServerUrl: normalizeUrl(authorizationServerUrl),
507
+ tokenEndpoint: normalizeUrl(
508
+ (metadata == null ? void 0 : metadata.token_endpoint) ? new URL(metadata.token_endpoint) : new URL("/token", authorizationServerUrl)
509
+ )
510
+ };
511
+ }
512
+ function addAuthorizationServerInformationToTokens(tokens, authorizationServerInformation) {
513
+ return {
514
+ ...tokens,
515
+ authorization_server: authorizationServerInformation.authorizationServerUrl,
516
+ token_endpoint: authorizationServerInformation.tokenEndpoint
517
+ };
518
+ }
519
+ function addAuthorizationServerInformationToClientInformation(clientInformation, authorizationServerInformation) {
520
+ return {
521
+ ...clientInformation,
522
+ authorization_server: authorizationServerInformation.authorizationServerUrl,
523
+ token_endpoint: authorizationServerInformation.tokenEndpoint
524
+ };
525
+ }
526
+ function getAuthorizationServerInformationFromCredentials(credentials) {
527
+ if (!(credentials == null ? void 0 : credentials.authorization_server) || !credentials.token_endpoint) {
528
+ return void 0;
529
+ }
530
+ return {
531
+ authorizationServerUrl: normalizeUrl(credentials.authorization_server),
532
+ tokenEndpoint: normalizeUrl(credentials.token_endpoint)
533
+ };
534
+ }
535
+ async function getStoredAuthorizationServerInformation({
536
+ provider,
537
+ clientInformation,
538
+ tokens
539
+ }) {
540
+ var _a3;
541
+ const tokenAuthorizationServerInformation = getAuthorizationServerInformationFromCredentials(tokens);
542
+ if (tokenAuthorizationServerInformation) {
543
+ return tokenAuthorizationServerInformation;
544
+ }
545
+ const providerAuthorizationServerInformation = await ((_a3 = provider.authorizationServerInformation) == null ? void 0 : _a3.call(provider));
546
+ if (providerAuthorizationServerInformation) {
547
+ return {
548
+ authorizationServerUrl: normalizeUrl(
549
+ providerAuthorizationServerInformation.authorizationServerUrl
550
+ ),
551
+ tokenEndpoint: normalizeUrl(
552
+ providerAuthorizationServerInformation.tokenEndpoint
553
+ )
554
+ };
555
+ }
556
+ return getAuthorizationServerInformationFromCredentials(clientInformation);
557
+ }
558
+ async function saveAuthorizationServerInformation({
559
+ provider,
560
+ clientInformation,
561
+ authorizationServerInformation
562
+ }) {
563
+ if (provider.saveAuthorizationServerInformation) {
564
+ await provider.saveAuthorizationServerInformation(
565
+ authorizationServerInformation
566
+ );
567
+ return true;
568
+ }
569
+ if (provider.saveClientInformation) {
570
+ await provider.saveClientInformation(
571
+ addAuthorizationServerInformationToClientInformation(
572
+ clientInformation,
573
+ authorizationServerInformation
574
+ )
575
+ );
576
+ return true;
577
+ }
578
+ return false;
579
+ }
580
+ function assertResourceMetadataUrlSameOrigin(serverUrl, resourceMetadataUrl) {
581
+ if (!resourceMetadataUrl) {
582
+ return;
583
+ }
584
+ const expectedOrigin = new URL(serverUrl).origin;
585
+ if (resourceMetadataUrl.origin !== expectedOrigin) {
586
+ throw new MCPClientOAuthError({
587
+ message: `OAuth protected resource metadata URL ${resourceMetadataUrl.href} must have the same origin as the MCP server URL ${expectedOrigin}`
588
+ });
589
+ }
590
+ }
591
+ function assertAuthorizationServerInformationMatches({
592
+ storedAuthorizationServerInformation,
593
+ currentAuthorizationServerInformation
594
+ }) {
595
+ if (storedAuthorizationServerInformation.authorizationServerUrl !== currentAuthorizationServerInformation.authorizationServerUrl || storedAuthorizationServerInformation.tokenEndpoint !== currentAuthorizationServerInformation.tokenEndpoint) {
596
+ throw new MCPClientOAuthError({
597
+ message: "OAuth authorization server metadata does not match the metadata that issued the stored credentials"
598
+ });
599
+ }
600
+ }
497
601
  function extractResourceMetadataUrl(response) {
498
602
  var _a3;
499
603
  const header = (_a3 = response.headers.get("www-authenticate")) != null ? _a3 : response.headers.get("WWW-Authenticate");
@@ -812,7 +916,12 @@ async function exchangeAuthorization(authorizationServerUrl, {
812
916
  redirect_uri: String(redirectUri)
813
917
  });
814
918
  if (addClientAuthentication) {
815
- addClientAuthentication(headers, params, authorizationServerUrl, metadata);
919
+ await addClientAuthentication(
920
+ headers,
921
+ params,
922
+ authorizationServerUrl,
923
+ metadata
924
+ );
816
925
  } else {
817
926
  const supportedMethods = (_a3 = metadata == null ? void 0 : metadata.token_endpoint_auth_methods_supported) != null ? _a3 : [];
818
927
  const authMethod = selectClientAuthMethod(
@@ -864,7 +973,12 @@ async function refreshAuthorization(authorizationServerUrl, {
864
973
  refresh_token: refreshToken
865
974
  });
866
975
  if (addClientAuthentication) {
867
- addClientAuthentication(headers, params, authorizationServerUrl, metadata);
976
+ await addClientAuthentication(
977
+ headers,
978
+ params,
979
+ authorizationServerUrl,
980
+ metadata
981
+ );
868
982
  } else {
869
983
  const supportedMethods = (_a3 = metadata == null ? void 0 : metadata.token_endpoint_auth_methods_supported) != null ? _a3 : [];
870
984
  const authMethod = selectClientAuthMethod(
@@ -961,8 +1075,10 @@ async function authInternal(provider, {
961
1075
  resourceMetadataUrl,
962
1076
  fetchFn
963
1077
  }) {
1078
+ var _a3;
964
1079
  let resourceMetadata;
965
1080
  let authorizationServerUrl;
1081
+ assertResourceMetadataUrlSameOrigin(serverUrl, resourceMetadataUrl);
966
1082
  try {
967
1083
  resourceMetadata = await discoverOAuthProtectedResourceMetadata(
968
1084
  serverUrl,
@@ -988,6 +1104,7 @@ async function authInternal(provider, {
988
1104
  fetchFn
989
1105
  }
990
1106
  );
1107
+ const currentAuthorizationServerInformation = createAuthorizationServerInformation(authorizationServerUrl, metadata);
991
1108
  let clientInformation = await Promise.resolve(provider.clientInformation());
992
1109
  if (!clientInformation) {
993
1110
  if (authorizationCode !== void 0) {
@@ -1005,8 +1122,11 @@ async function authInternal(provider, {
1005
1122
  clientMetadata: provider.clientMetadata,
1006
1123
  fetchFn
1007
1124
  });
1008
- await provider.saveClientInformation(fullInformation);
1009
- clientInformation = fullInformation;
1125
+ clientInformation = addAuthorizationServerInformationToClientInformation(
1126
+ fullInformation,
1127
+ currentAuthorizationServerInformation
1128
+ );
1129
+ await provider.saveClientInformation(clientInformation);
1010
1130
  }
1011
1131
  if (authorizationCode !== void 0) {
1012
1132
  if (provider.storedState) {
@@ -1017,6 +1137,19 @@ async function authInternal(provider, {
1017
1137
  );
1018
1138
  }
1019
1139
  }
1140
+ const storedAuthorizationServerInformation = await getStoredAuthorizationServerInformation({
1141
+ provider,
1142
+ clientInformation
1143
+ });
1144
+ if (!storedAuthorizationServerInformation) {
1145
+ throw new MCPClientOAuthError({
1146
+ message: "Stored OAuth authorization server metadata is required when exchanging an authorization code"
1147
+ });
1148
+ }
1149
+ assertAuthorizationServerInformationMatches({
1150
+ storedAuthorizationServerInformation,
1151
+ currentAuthorizationServerInformation
1152
+ });
1020
1153
  const codeVerifier2 = await provider.codeVerifier();
1021
1154
  const tokens2 = await exchangeAuthorization(authorizationServerUrl, {
1022
1155
  metadata,
@@ -1028,22 +1161,47 @@ async function authInternal(provider, {
1028
1161
  addClientAuthentication: provider.addClientAuthentication,
1029
1162
  fetchFn
1030
1163
  });
1031
- await provider.saveTokens(tokens2);
1164
+ await provider.saveTokens(
1165
+ addAuthorizationServerInformationToTokens(
1166
+ tokens2,
1167
+ currentAuthorizationServerInformation
1168
+ )
1169
+ );
1032
1170
  return "AUTHORIZED";
1033
1171
  }
1034
1172
  const tokens = await provider.tokens();
1035
1173
  if (tokens == null ? void 0 : tokens.refresh_token) {
1036
- try {
1037
- const newTokens = await refreshAuthorization(authorizationServerUrl, {
1038
- metadata,
1039
- clientInformation,
1040
- refreshToken: tokens.refresh_token,
1041
- resource,
1042
- addClientAuthentication: provider.addClientAuthentication,
1043
- fetchFn
1174
+ const storedAuthorizationServerInformation = await getStoredAuthorizationServerInformation({
1175
+ provider,
1176
+ clientInformation,
1177
+ tokens
1178
+ });
1179
+ if (storedAuthorizationServerInformation) {
1180
+ assertAuthorizationServerInformationMatches({
1181
+ storedAuthorizationServerInformation,
1182
+ currentAuthorizationServerInformation
1044
1183
  });
1045
- await provider.saveTokens(newTokens);
1046
- return "AUTHORIZED";
1184
+ } else {
1185
+ await ((_a3 = provider.invalidateCredentials) == null ? void 0 : _a3.call(provider, "tokens"));
1186
+ }
1187
+ try {
1188
+ if (storedAuthorizationServerInformation) {
1189
+ const newTokens = await refreshAuthorization(authorizationServerUrl, {
1190
+ metadata,
1191
+ clientInformation,
1192
+ refreshToken: tokens.refresh_token,
1193
+ resource,
1194
+ addClientAuthentication: provider.addClientAuthentication,
1195
+ fetchFn
1196
+ });
1197
+ await provider.saveTokens(
1198
+ addAuthorizationServerInformationToTokens(
1199
+ newTokens,
1200
+ currentAuthorizationServerInformation
1201
+ )
1202
+ );
1203
+ return "AUTHORIZED";
1204
+ }
1047
1205
  } catch (error) {
1048
1206
  if (
1049
1207
  // If this is a ServerError, or an unknown type, log it out and try to continue. Otherwise, escalate so we can fix things and retry.
@@ -1069,6 +1227,16 @@ async function authInternal(provider, {
1069
1227
  resource
1070
1228
  }
1071
1229
  );
1230
+ const savedAuthorizationServerInformation = await saveAuthorizationServerInformation({
1231
+ provider,
1232
+ clientInformation,
1233
+ authorizationServerInformation: currentAuthorizationServerInformation
1234
+ });
1235
+ if (!savedAuthorizationServerInformation) {
1236
+ throw new MCPClientOAuthError({
1237
+ message: "OAuth authorization server metadata must be saveable before starting authorization"
1238
+ });
1239
+ }
1072
1240
  await provider.saveCodeVerifier(codeVerifier);
1073
1241
  await provider.redirectToAuthorization(authorizationUrl);
1074
1242
  return "REDIRECT";