@ai-sdk/mcp 1.0.49 → 1.0.51

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 CHANGED
@@ -1,5 +1,17 @@
1
1
  # @ai-sdk/mcp
2
2
 
3
+ ## 1.0.51
4
+
5
+ ### Patch Changes
6
+
7
+ - aa39fc8: fix (mcp): handle SSE messages without explicit event fields
8
+
9
+ ## 1.0.50
10
+
11
+ ### Patch Changes
12
+
13
+ - ac40275: fix(mcp): validate oauth metadata issuer during discovery
14
+
3
15
  ## 1.0.49
4
16
 
5
17
  ### Patch Changes
package/dist/index.js CHANGED
@@ -722,15 +722,18 @@ async function discoverOAuthProtectedResourceMetadata(serverUrl, opts, fetchFn =
722
722
  function buildDiscoveryUrls(authorizationServerUrl) {
723
723
  const url = typeof authorizationServerUrl === "string" ? new URL(authorizationServerUrl) : authorizationServerUrl;
724
724
  const hasPath = url.pathname !== "/";
725
+ const rootIssuer = url.origin;
725
726
  const urlsToTry = [];
726
727
  if (!hasPath) {
727
728
  urlsToTry.push({
728
729
  url: new URL("/.well-known/oauth-authorization-server", url.origin),
729
- type: "oauth"
730
+ type: "oauth",
731
+ expectedIssuer: rootIssuer
730
732
  });
731
733
  urlsToTry.push({
732
734
  url: new URL("/.well-known/openid-configuration", url.origin),
733
- type: "oidc"
735
+ type: "oidc",
736
+ expectedIssuer: rootIssuer
734
737
  });
735
738
  return urlsToTry;
736
739
  }
@@ -738,27 +741,39 @@ function buildDiscoveryUrls(authorizationServerUrl) {
738
741
  if (pathname.endsWith("/")) {
739
742
  pathname = pathname.slice(0, -1);
740
743
  }
744
+ const pathIssuer = `${url.origin}${pathname}`;
741
745
  urlsToTry.push({
742
746
  url: new URL(
743
747
  `/.well-known/oauth-authorization-server${pathname}`,
744
748
  url.origin
745
749
  ),
746
- type: "oauth"
750
+ type: "oauth",
751
+ expectedIssuer: pathIssuer
747
752
  });
748
753
  urlsToTry.push({
749
754
  url: new URL("/.well-known/oauth-authorization-server", url.origin),
750
- type: "oauth"
755
+ type: "oauth",
756
+ expectedIssuer: rootIssuer
751
757
  });
752
758
  urlsToTry.push({
753
759
  url: new URL(`/.well-known/openid-configuration${pathname}`, url.origin),
754
- type: "oidc"
760
+ type: "oidc",
761
+ expectedIssuer: pathIssuer
755
762
  });
756
763
  urlsToTry.push({
757
764
  url: new URL(`${pathname}/.well-known/openid-configuration`, url.origin),
758
- type: "oidc"
765
+ type: "oidc",
766
+ expectedIssuer: pathIssuer
759
767
  });
760
768
  return urlsToTry;
761
769
  }
770
+ function assertMetadataIssuerMatches(metadata, expectedIssuer) {
771
+ if (metadata.issuer !== expectedIssuer) {
772
+ throw new MCPClientOAuthError({
773
+ message: `OAuth authorization server metadata issuer ${metadata.issuer} does not match expected issuer ${expectedIssuer}`
774
+ });
775
+ }
776
+ }
762
777
  async function discoverAuthorizationServerMetadata(authorizationServerUrl, {
763
778
  fetchFn = fetch,
764
779
  protocolVersion = LATEST_PROTOCOL_VERSION
@@ -766,7 +781,7 @@ async function discoverAuthorizationServerMetadata(authorizationServerUrl, {
766
781
  var _a3;
767
782
  const headers = { "MCP-Protocol-Version": protocolVersion };
768
783
  const urlsToTry = buildDiscoveryUrls(authorizationServerUrl);
769
- for (const { url: endpointUrl, type } of urlsToTry) {
784
+ for (const { url: endpointUrl, type, expectedIssuer } of urlsToTry) {
770
785
  const response = await fetchWithCorsRetry(endpointUrl, headers, fetchFn);
771
786
  if (!response) {
772
787
  continue;
@@ -780,11 +795,14 @@ async function discoverAuthorizationServerMetadata(authorizationServerUrl, {
780
795
  );
781
796
  }
782
797
  if (type === "oauth") {
783
- return OAuthMetadataSchema.parse(await response.json());
798
+ const metadata = OAuthMetadataSchema.parse(await response.json());
799
+ assertMetadataIssuerMatches(metadata, expectedIssuer);
800
+ return metadata;
784
801
  } else {
785
802
  const metadata = OpenIdProviderDiscoveryMetadataSchema.parse(
786
803
  await response.json()
787
804
  );
805
+ assertMetadataIssuerMatches(metadata, expectedIssuer);
788
806
  if (!((_a3 = metadata.code_challenge_methods_supported) == null ? void 0 : _a3.includes("S256"))) {
789
807
  throw new Error(
790
808
  `Incompatible OIDC provider at ${endpointUrl}: does not support S256 code challenge method required by MCP specification`
@@ -1278,6 +1296,9 @@ async function authInternal(provider, {
1278
1296
  }
1279
1297
 
1280
1298
  // src/tool/mcp-sse-transport.ts
1299
+ function isMessageEvent(event) {
1300
+ return event === void 0 || event === "message";
1301
+ }
1281
1302
  var SseMCPTransport = class {
1282
1303
  constructor({
1283
1304
  url,
@@ -1396,7 +1417,7 @@ var SseMCPTransport = class {
1396
1417
  this.endpoint = endpoint;
1397
1418
  this.connected = true;
1398
1419
  resolve();
1399
- } else if (event === "message") {
1420
+ } else if (isMessageEvent(event)) {
1400
1421
  try {
1401
1422
  const message = await parseJSONRPCMessage(data);
1402
1423
  (_c2 = this.onmessage) == null ? void 0 : _c2.call(this, message);
@@ -1499,6 +1520,9 @@ var SseMCPTransport = class {
1499
1520
 
1500
1521
  // src/tool/mcp-http-transport.ts
1501
1522
  var import_provider_utils4 = require("@ai-sdk/provider-utils");
1523
+ function isMessageEvent2(event) {
1524
+ return event === void 0 || event === "message";
1525
+ }
1502
1526
  var HttpMCPTransport = class {
1503
1527
  constructor({
1504
1528
  url,
@@ -1675,7 +1699,7 @@ var HttpMCPTransport = class {
1675
1699
  const { done, value } = await reader.read();
1676
1700
  if (done) return;
1677
1701
  const { event, data } = value;
1678
- if (event === "message") {
1702
+ if (isMessageEvent2(event)) {
1679
1703
  try {
1680
1704
  const msg = await parseJSONRPCMessage(data);
1681
1705
  (_a4 = this.onmessage) == null ? void 0 : _a4.call(this, msg);
@@ -1802,7 +1826,7 @@ var HttpMCPTransport = class {
1802
1826
  if (id) {
1803
1827
  this.lastInboundEventId = id;
1804
1828
  }
1805
- if (event === "message") {
1829
+ if (isMessageEvent2(event)) {
1806
1830
  try {
1807
1831
  const msg = await parseJSONRPCMessage(data);
1808
1832
  (_a4 = this.onmessage) == null ? void 0 : _a4.call(this, msg);