@ai-sdk/mcp 1.0.48 → 1.0.50

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
@@ -692,15 +692,18 @@ async function discoverOAuthProtectedResourceMetadata(serverUrl, opts, fetchFn =
692
692
  function buildDiscoveryUrls(authorizationServerUrl) {
693
693
  const url = typeof authorizationServerUrl === "string" ? new URL(authorizationServerUrl) : authorizationServerUrl;
694
694
  const hasPath = url.pathname !== "/";
695
+ const rootIssuer = url.origin;
695
696
  const urlsToTry = [];
696
697
  if (!hasPath) {
697
698
  urlsToTry.push({
698
699
  url: new URL("/.well-known/oauth-authorization-server", url.origin),
699
- type: "oauth"
700
+ type: "oauth",
701
+ expectedIssuer: rootIssuer
700
702
  });
701
703
  urlsToTry.push({
702
704
  url: new URL("/.well-known/openid-configuration", url.origin),
703
- type: "oidc"
705
+ type: "oidc",
706
+ expectedIssuer: rootIssuer
704
707
  });
705
708
  return urlsToTry;
706
709
  }
@@ -708,27 +711,39 @@ function buildDiscoveryUrls(authorizationServerUrl) {
708
711
  if (pathname.endsWith("/")) {
709
712
  pathname = pathname.slice(0, -1);
710
713
  }
714
+ const pathIssuer = `${url.origin}${pathname}`;
711
715
  urlsToTry.push({
712
716
  url: new URL(
713
717
  `/.well-known/oauth-authorization-server${pathname}`,
714
718
  url.origin
715
719
  ),
716
- type: "oauth"
720
+ type: "oauth",
721
+ expectedIssuer: pathIssuer
717
722
  });
718
723
  urlsToTry.push({
719
724
  url: new URL("/.well-known/oauth-authorization-server", url.origin),
720
- type: "oauth"
725
+ type: "oauth",
726
+ expectedIssuer: rootIssuer
721
727
  });
722
728
  urlsToTry.push({
723
729
  url: new URL(`/.well-known/openid-configuration${pathname}`, url.origin),
724
- type: "oidc"
730
+ type: "oidc",
731
+ expectedIssuer: pathIssuer
725
732
  });
726
733
  urlsToTry.push({
727
734
  url: new URL(`${pathname}/.well-known/openid-configuration`, url.origin),
728
- type: "oidc"
735
+ type: "oidc",
736
+ expectedIssuer: pathIssuer
729
737
  });
730
738
  return urlsToTry;
731
739
  }
740
+ function assertMetadataIssuerMatches(metadata, expectedIssuer) {
741
+ if (metadata.issuer !== expectedIssuer) {
742
+ throw new MCPClientOAuthError({
743
+ message: `OAuth authorization server metadata issuer ${metadata.issuer} does not match expected issuer ${expectedIssuer}`
744
+ });
745
+ }
746
+ }
732
747
  async function discoverAuthorizationServerMetadata(authorizationServerUrl, {
733
748
  fetchFn = fetch,
734
749
  protocolVersion = LATEST_PROTOCOL_VERSION
@@ -736,7 +751,7 @@ async function discoverAuthorizationServerMetadata(authorizationServerUrl, {
736
751
  var _a3;
737
752
  const headers = { "MCP-Protocol-Version": protocolVersion };
738
753
  const urlsToTry = buildDiscoveryUrls(authorizationServerUrl);
739
- for (const { url: endpointUrl, type } of urlsToTry) {
754
+ for (const { url: endpointUrl, type, expectedIssuer } of urlsToTry) {
740
755
  const response = await fetchWithCorsRetry(endpointUrl, headers, fetchFn);
741
756
  if (!response) {
742
757
  continue;
@@ -750,11 +765,14 @@ async function discoverAuthorizationServerMetadata(authorizationServerUrl, {
750
765
  );
751
766
  }
752
767
  if (type === "oauth") {
753
- return OAuthMetadataSchema.parse(await response.json());
768
+ const metadata = OAuthMetadataSchema.parse(await response.json());
769
+ assertMetadataIssuerMatches(metadata, expectedIssuer);
770
+ return metadata;
754
771
  } else {
755
772
  const metadata = OpenIdProviderDiscoveryMetadataSchema.parse(
756
773
  await response.json()
757
774
  );
775
+ assertMetadataIssuerMatches(metadata, expectedIssuer);
758
776
  if (!((_a3 = metadata.code_challenge_methods_supported) == null ? void 0 : _a3.includes("S256"))) {
759
777
  throw new Error(
760
778
  `Incompatible OIDC provider at ${endpointUrl}: does not support S256 code challenge method required by MCP specification`
@@ -1335,7 +1353,7 @@ var SseMCPTransport = class {
1335
1353
  const stream = response.body.pipeThrough(new TextDecoderStream()).pipeThrough(new EventSourceParserStream());
1336
1354
  const reader = stream.getReader();
1337
1355
  const processEvents = async () => {
1338
- var _a4, _b4, _c2;
1356
+ var _a4, _b4, _c2, _d2, _e2;
1339
1357
  try {
1340
1358
  while (true) {
1341
1359
  const { done, value } = await reader.read();
@@ -1350,24 +1368,32 @@ var SseMCPTransport = class {
1350
1368
  }
1351
1369
  const { event, data } = value;
1352
1370
  if (event === "endpoint") {
1353
- this.endpoint = new URL(data, this.url);
1354
- if (this.endpoint.origin !== this.url.origin) {
1371
+ if (this.endpoint) {
1372
+ continue;
1373
+ }
1374
+ const endpoint = new URL(data, this.url);
1375
+ if (endpoint.origin !== this.url.origin) {
1376
+ this.connected = false;
1377
+ this.endpoint = void 0;
1378
+ (_a4 = this.sseConnection) == null ? void 0 : _a4.close();
1379
+ (_b4 = this.abortController) == null ? void 0 : _b4.abort();
1355
1380
  throw new MCPClientError({
1356
- message: `MCP SSE Transport Error: Endpoint origin does not match connection origin: ${this.endpoint.origin}`
1381
+ message: `MCP SSE Transport Error: Endpoint origin does not match connection origin: ${endpoint.origin}`
1357
1382
  });
1358
1383
  }
1384
+ this.endpoint = endpoint;
1359
1385
  this.connected = true;
1360
1386
  resolve();
1361
1387
  } else if (event === "message") {
1362
1388
  try {
1363
1389
  const message = await parseJSONRPCMessage(data);
1364
- (_a4 = this.onmessage) == null ? void 0 : _a4.call(this, message);
1390
+ (_c2 = this.onmessage) == null ? void 0 : _c2.call(this, message);
1365
1391
  } catch (error) {
1366
1392
  const e = new MCPClientError({
1367
1393
  message: "MCP SSE Transport Error: Failed to parse message",
1368
1394
  cause: error
1369
1395
  });
1370
- (_b4 = this.onerror) == null ? void 0 : _b4.call(this, e);
1396
+ (_d2 = this.onerror) == null ? void 0 : _d2.call(this, e);
1371
1397
  }
1372
1398
  }
1373
1399
  }
@@ -1375,7 +1401,7 @@ var SseMCPTransport = class {
1375
1401
  if (error instanceof Error && error.name === "AbortError") {
1376
1402
  return;
1377
1403
  }
1378
- (_c2 = this.onerror) == null ? void 0 : _c2.call(this, error);
1404
+ (_e2 = this.onerror) == null ? void 0 : _e2.call(this, error);
1379
1405
  reject(error);
1380
1406
  }
1381
1407
  };
@@ -1397,6 +1423,7 @@ var SseMCPTransport = class {
1397
1423
  async close() {
1398
1424
  var _a3, _b3, _c;
1399
1425
  this.connected = false;
1426
+ this.endpoint = void 0;
1400
1427
  (_a3 = this.sseConnection) == null ? void 0 : _a3.close();
1401
1428
  (_b3 = this.abortController) == null ? void 0 : _b3.abort();
1402
1429
  (_c = this.onclose) == null ? void 0 : _c.call(this);
@@ -2173,7 +2200,7 @@ var DefaultMCPClient = class {
2173
2200
  _meta
2174
2201
  } of definitions.tools) {
2175
2202
  const resolvedTitle = title != null ? title : annotations == null ? void 0 : annotations.title;
2176
- if (schemas !== "automatic" && !(name3 in schemas)) {
2203
+ if (schemas !== "automatic" && !Object.prototype.hasOwnProperty.call(schemas, name3)) {
2177
2204
  continue;
2178
2205
  }
2179
2206
  const self = this;