@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 +12 -0
- package/dist/index.js +35 -11
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +35 -11
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/tool/mcp-http-transport.ts +6 -2
- package/src/tool/mcp-sse-transport.ts +5 -1
- package/src/tool/oauth.ts +30 -4
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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);
|