@ai-sdk/mcp 1.0.46 → 1.0.48

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");
@@ -971,8 +1075,10 @@ async function authInternal(provider, {
971
1075
  resourceMetadataUrl,
972
1076
  fetchFn
973
1077
  }) {
1078
+ var _a3, _b3;
974
1079
  let resourceMetadata;
975
1080
  let authorizationServerUrl;
1081
+ assertResourceMetadataUrlSameOrigin(serverUrl, resourceMetadataUrl);
976
1082
  try {
977
1083
  resourceMetadata = await discoverOAuthProtectedResourceMetadata(
978
1084
  serverUrl,
@@ -992,12 +1098,18 @@ async function authInternal(provider, {
992
1098
  provider,
993
1099
  resourceMetadata
994
1100
  );
1101
+ await ((_a3 = provider.validateAuthorizationServerURL) == null ? void 0 : _a3.call(
1102
+ provider,
1103
+ serverUrl,
1104
+ authorizationServerUrl
1105
+ ));
995
1106
  const metadata = await discoverAuthorizationServerMetadata(
996
1107
  authorizationServerUrl,
997
1108
  {
998
1109
  fetchFn
999
1110
  }
1000
1111
  );
1112
+ const currentAuthorizationServerInformation = createAuthorizationServerInformation(authorizationServerUrl, metadata);
1001
1113
  let clientInformation = await Promise.resolve(provider.clientInformation());
1002
1114
  if (!clientInformation) {
1003
1115
  if (authorizationCode !== void 0) {
@@ -1015,8 +1127,11 @@ async function authInternal(provider, {
1015
1127
  clientMetadata: provider.clientMetadata,
1016
1128
  fetchFn
1017
1129
  });
1018
- await provider.saveClientInformation(fullInformation);
1019
- clientInformation = fullInformation;
1130
+ clientInformation = addAuthorizationServerInformationToClientInformation(
1131
+ fullInformation,
1132
+ currentAuthorizationServerInformation
1133
+ );
1134
+ await provider.saveClientInformation(clientInformation);
1020
1135
  }
1021
1136
  if (authorizationCode !== void 0) {
1022
1137
  if (provider.storedState) {
@@ -1027,6 +1142,19 @@ async function authInternal(provider, {
1027
1142
  );
1028
1143
  }
1029
1144
  }
1145
+ const storedAuthorizationServerInformation = await getStoredAuthorizationServerInformation({
1146
+ provider,
1147
+ clientInformation
1148
+ });
1149
+ if (!storedAuthorizationServerInformation) {
1150
+ throw new MCPClientOAuthError({
1151
+ message: "Stored OAuth authorization server metadata is required when exchanging an authorization code"
1152
+ });
1153
+ }
1154
+ assertAuthorizationServerInformationMatches({
1155
+ storedAuthorizationServerInformation,
1156
+ currentAuthorizationServerInformation
1157
+ });
1030
1158
  const codeVerifier2 = await provider.codeVerifier();
1031
1159
  const tokens2 = await exchangeAuthorization(authorizationServerUrl, {
1032
1160
  metadata,
@@ -1038,22 +1166,47 @@ async function authInternal(provider, {
1038
1166
  addClientAuthentication: provider.addClientAuthentication,
1039
1167
  fetchFn
1040
1168
  });
1041
- await provider.saveTokens(tokens2);
1169
+ await provider.saveTokens(
1170
+ addAuthorizationServerInformationToTokens(
1171
+ tokens2,
1172
+ currentAuthorizationServerInformation
1173
+ )
1174
+ );
1042
1175
  return "AUTHORIZED";
1043
1176
  }
1044
1177
  const tokens = await provider.tokens();
1045
1178
  if (tokens == null ? void 0 : tokens.refresh_token) {
1046
- try {
1047
- const newTokens = await refreshAuthorization(authorizationServerUrl, {
1048
- metadata,
1049
- clientInformation,
1050
- refreshToken: tokens.refresh_token,
1051
- resource,
1052
- addClientAuthentication: provider.addClientAuthentication,
1053
- fetchFn
1179
+ const storedAuthorizationServerInformation = await getStoredAuthorizationServerInformation({
1180
+ provider,
1181
+ clientInformation,
1182
+ tokens
1183
+ });
1184
+ if (storedAuthorizationServerInformation) {
1185
+ assertAuthorizationServerInformationMatches({
1186
+ storedAuthorizationServerInformation,
1187
+ currentAuthorizationServerInformation
1054
1188
  });
1055
- await provider.saveTokens(newTokens);
1056
- return "AUTHORIZED";
1189
+ } else {
1190
+ await ((_b3 = provider.invalidateCredentials) == null ? void 0 : _b3.call(provider, "tokens"));
1191
+ }
1192
+ try {
1193
+ if (storedAuthorizationServerInformation) {
1194
+ const newTokens = await refreshAuthorization(authorizationServerUrl, {
1195
+ metadata,
1196
+ clientInformation,
1197
+ refreshToken: tokens.refresh_token,
1198
+ resource,
1199
+ addClientAuthentication: provider.addClientAuthentication,
1200
+ fetchFn
1201
+ });
1202
+ await provider.saveTokens(
1203
+ addAuthorizationServerInformationToTokens(
1204
+ newTokens,
1205
+ currentAuthorizationServerInformation
1206
+ )
1207
+ );
1208
+ return "AUTHORIZED";
1209
+ }
1057
1210
  } catch (error) {
1058
1211
  if (
1059
1212
  // 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.
@@ -1079,6 +1232,16 @@ async function authInternal(provider, {
1079
1232
  resource
1080
1233
  }
1081
1234
  );
1235
+ const savedAuthorizationServerInformation = await saveAuthorizationServerInformation({
1236
+ provider,
1237
+ clientInformation,
1238
+ authorizationServerInformation: currentAuthorizationServerInformation
1239
+ });
1240
+ if (!savedAuthorizationServerInformation) {
1241
+ throw new MCPClientOAuthError({
1242
+ message: "OAuth authorization server metadata must be saveable before starting authorization"
1243
+ });
1244
+ }
1082
1245
  await provider.saveCodeVerifier(codeVerifier);
1083
1246
  await provider.redirectToAuthorization(authorizationUrl);
1084
1247
  return "REDIRECT";
@@ -1100,6 +1263,9 @@ var SseMCPTransport = class {
1100
1263
  this.redirectMode = redirect;
1101
1264
  this.fetchFn = fetchFn != null ? fetchFn : globalThis.fetch;
1102
1265
  }
1266
+ setProtocolVersion(version) {
1267
+ this.protocolVersion = version;
1268
+ }
1103
1269
  async commonHeaders(base) {
1104
1270
  var _a3;
1105
1271
  const headers = {
@@ -1319,6 +1485,9 @@ var HttpMCPTransport = class {
1319
1485
  this.redirectMode = redirect;
1320
1486
  this.fetchFn = fetchFn != null ? fetchFn : globalThis.fetch;
1321
1487
  }
1488
+ setProtocolVersion(version) {
1489
+ this.protocolVersion = version;
1490
+ }
1322
1491
  async commonHeaders(base) {
1323
1492
  var _a3;
1324
1493
  const headers = {
@@ -1762,8 +1931,12 @@ var DefaultMCPClient = class {
1762
1931
  }
1763
1932
  this.serverCapabilities = result.capabilities;
1764
1933
  this._serverInfo = result.serverInfo;
1934
+ if (this.transport.setProtocolVersion) {
1935
+ this.transport.setProtocolVersion(result.protocolVersion);
1936
+ } else {
1937
+ this.transport.protocolVersion = result.protocolVersion;
1938
+ }
1765
1939
  this._serverInstructions = result.instructions;
1766
- this.transport.protocolVersion = result.protocolVersion;
1767
1940
  await this.notification({
1768
1941
  method: "notifications/initialized"
1769
1942
  });