@ai-sdk/mcp 1.0.74 → 1.0.75
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 +7 -0
- package/dist/index.js +37 -9
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +41 -10
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
- package/src/tool/oauth.ts +61 -8
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# @ai-sdk/mcp
|
|
2
2
|
|
|
3
|
+
## 1.0.75
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 878bdb9: Apply MCP scope selection to dynamic client registration as well as authorization.
|
|
8
|
+
- 204ce6c: fix(mcp): reject private OAuth endpoints before sending credentials
|
|
9
|
+
|
|
3
10
|
## 1.0.74
|
|
4
11
|
|
|
5
12
|
### Patch Changes
|
package/dist/index.js
CHANGED
|
@@ -564,6 +564,23 @@ var UnauthorizedError = class extends Error {
|
|
|
564
564
|
function normalizeUrl(url) {
|
|
565
565
|
return new URL(url).href;
|
|
566
566
|
}
|
|
567
|
+
function isOAuthLoopbackHost(hostname) {
|
|
568
|
+
const normalized = hostname.toLowerCase().replace(/\.+$/, "");
|
|
569
|
+
return normalized === "localhost" || normalized.endsWith(".localhost") || normalized === "127.0.0.1" || normalized === "[::1]" || normalized === "::1";
|
|
570
|
+
}
|
|
571
|
+
function assertSafeOAuthEndpoint(endpointUrl) {
|
|
572
|
+
if ((endpointUrl.protocol === "http:" || endpointUrl.protocol === "https:") && isOAuthLoopbackHost(endpointUrl.hostname)) {
|
|
573
|
+
return;
|
|
574
|
+
}
|
|
575
|
+
try {
|
|
576
|
+
(0, import_provider_utils2.validateDownloadUrl)(endpointUrl.href);
|
|
577
|
+
} catch (error) {
|
|
578
|
+
throw new MCPClientOAuthError({
|
|
579
|
+
message: `OAuth endpoint URL is not allowed: ${endpointUrl.href}`,
|
|
580
|
+
cause: error
|
|
581
|
+
});
|
|
582
|
+
}
|
|
583
|
+
}
|
|
567
584
|
function createAuthorizationServerInformation(authorizationServerUrl, metadata) {
|
|
568
585
|
return {
|
|
569
586
|
authorizationServerUrl: normalizeUrl(authorizationServerUrl),
|
|
@@ -996,6 +1013,7 @@ async function exchangeAuthorization(authorizationServerUrl, {
|
|
|
996
1013
|
var _a3;
|
|
997
1014
|
const grantType = "authorization_code";
|
|
998
1015
|
const tokenUrl = (metadata == null ? void 0 : metadata.token_endpoint) ? new URL(metadata.token_endpoint) : new URL("/token", authorizationServerUrl);
|
|
1016
|
+
assertSafeOAuthEndpoint(tokenUrl);
|
|
999
1017
|
if ((metadata == null ? void 0 : metadata.grant_types_supported) && !metadata.grant_types_supported.includes(grantType)) {
|
|
1000
1018
|
throw new Error(
|
|
1001
1019
|
`Incompatible auth server: does not support grant type ${grantType}`
|
|
@@ -1032,7 +1050,8 @@ async function exchangeAuthorization(authorizationServerUrl, {
|
|
|
1032
1050
|
const response = await (fetchFn != null ? fetchFn : fetch)(tokenUrl, {
|
|
1033
1051
|
method: "POST",
|
|
1034
1052
|
headers,
|
|
1035
|
-
body: params
|
|
1053
|
+
body: params,
|
|
1054
|
+
redirect: "error"
|
|
1036
1055
|
});
|
|
1037
1056
|
if (!response.ok) {
|
|
1038
1057
|
throw await parseErrorResponse(response);
|
|
@@ -1060,6 +1079,7 @@ async function refreshAuthorization(authorizationServerUrl, {
|
|
|
1060
1079
|
} else {
|
|
1061
1080
|
tokenUrl = new URL("/token", authorizationServerUrl);
|
|
1062
1081
|
}
|
|
1082
|
+
assertSafeOAuthEndpoint(tokenUrl);
|
|
1063
1083
|
const headers = new Headers({
|
|
1064
1084
|
"Content-Type": "application/x-www-form-urlencoded",
|
|
1065
1085
|
Accept: "application/json"
|
|
@@ -1089,7 +1109,8 @@ async function refreshAuthorization(authorizationServerUrl, {
|
|
|
1089
1109
|
const response = await (fetchFn != null ? fetchFn : fetch)(tokenUrl, {
|
|
1090
1110
|
method: "POST",
|
|
1091
1111
|
headers,
|
|
1092
|
-
body: params
|
|
1112
|
+
body: params,
|
|
1113
|
+
redirect: "error"
|
|
1093
1114
|
});
|
|
1094
1115
|
if (!response.ok) {
|
|
1095
1116
|
throw await parseErrorResponse(response);
|
|
@@ -1115,12 +1136,14 @@ async function registerClient(authorizationServerUrl, {
|
|
|
1115
1136
|
} else {
|
|
1116
1137
|
registrationUrl = new URL("/register", authorizationServerUrl);
|
|
1117
1138
|
}
|
|
1139
|
+
assertSafeOAuthEndpoint(registrationUrl);
|
|
1118
1140
|
const response = await (fetchFn != null ? fetchFn : fetch)(registrationUrl, {
|
|
1119
1141
|
method: "POST",
|
|
1120
1142
|
headers: {
|
|
1121
1143
|
"Content-Type": "application/json"
|
|
1122
1144
|
},
|
|
1123
|
-
body: JSON.stringify(clientMetadata)
|
|
1145
|
+
body: JSON.stringify(clientMetadata),
|
|
1146
|
+
redirect: "error"
|
|
1124
1147
|
});
|
|
1125
1148
|
if (!response.ok) {
|
|
1126
1149
|
throw await parseErrorResponse(response);
|
|
@@ -1206,6 +1229,12 @@ async function authInternal(provider, {
|
|
|
1206
1229
|
}
|
|
1207
1230
|
);
|
|
1208
1231
|
const currentAuthorizationServerInformation = createAuthorizationServerInformation(authorizationServerUrl, metadata);
|
|
1232
|
+
const clientMetadata = provider.clientMetadata;
|
|
1233
|
+
const selectedScope = selectScope({
|
|
1234
|
+
scope,
|
|
1235
|
+
resourceMetadata,
|
|
1236
|
+
clientMetadata
|
|
1237
|
+
});
|
|
1209
1238
|
let clientInformation = await Promise.resolve(provider.clientInformation());
|
|
1210
1239
|
if (!clientInformation) {
|
|
1211
1240
|
if (authorizationCode !== void 0) {
|
|
@@ -1220,7 +1249,10 @@ async function authInternal(provider, {
|
|
|
1220
1249
|
}
|
|
1221
1250
|
const fullInformation = await registerClient(authorizationServerUrl, {
|
|
1222
1251
|
metadata,
|
|
1223
|
-
clientMetadata:
|
|
1252
|
+
clientMetadata: {
|
|
1253
|
+
...clientMetadata,
|
|
1254
|
+
scope: selectedScope
|
|
1255
|
+
},
|
|
1224
1256
|
fetchFn
|
|
1225
1257
|
});
|
|
1226
1258
|
clientInformation = addAuthorizationServerInformationToClientInformation(
|
|
@@ -1324,11 +1356,7 @@ async function authInternal(provider, {
|
|
|
1324
1356
|
clientInformation,
|
|
1325
1357
|
state,
|
|
1326
1358
|
redirectUrl: provider.redirectUrl,
|
|
1327
|
-
scope:
|
|
1328
|
-
scope,
|
|
1329
|
-
resourceMetadata,
|
|
1330
|
-
clientMetadata: provider.clientMetadata
|
|
1331
|
-
}),
|
|
1359
|
+
scope: selectedScope,
|
|
1332
1360
|
resource
|
|
1333
1361
|
}
|
|
1334
1362
|
);
|