@ai-sdk/mcp 1.0.73 → 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 +15 -0
- package/dist/index.js +46 -11
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +50 -12
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
- package/src/tool/mcp-client.ts +11 -2
- package/src/tool/oauth.ts +61 -8
package/dist/index.mjs
CHANGED
|
@@ -524,7 +524,10 @@ function checkResourceAllowed({
|
|
|
524
524
|
}
|
|
525
525
|
|
|
526
526
|
// src/tool/oauth.ts
|
|
527
|
-
import {
|
|
527
|
+
import {
|
|
528
|
+
parseJSON as parseJSON2,
|
|
529
|
+
validateDownloadUrl
|
|
530
|
+
} from "@ai-sdk/provider-utils";
|
|
528
531
|
var UnauthorizedError = class extends Error {
|
|
529
532
|
constructor(message = "Unauthorized") {
|
|
530
533
|
super(message);
|
|
@@ -534,6 +537,23 @@ var UnauthorizedError = class extends Error {
|
|
|
534
537
|
function normalizeUrl(url) {
|
|
535
538
|
return new URL(url).href;
|
|
536
539
|
}
|
|
540
|
+
function isOAuthLoopbackHost(hostname) {
|
|
541
|
+
const normalized = hostname.toLowerCase().replace(/\.+$/, "");
|
|
542
|
+
return normalized === "localhost" || normalized.endsWith(".localhost") || normalized === "127.0.0.1" || normalized === "[::1]" || normalized === "::1";
|
|
543
|
+
}
|
|
544
|
+
function assertSafeOAuthEndpoint(endpointUrl) {
|
|
545
|
+
if ((endpointUrl.protocol === "http:" || endpointUrl.protocol === "https:") && isOAuthLoopbackHost(endpointUrl.hostname)) {
|
|
546
|
+
return;
|
|
547
|
+
}
|
|
548
|
+
try {
|
|
549
|
+
validateDownloadUrl(endpointUrl.href);
|
|
550
|
+
} catch (error) {
|
|
551
|
+
throw new MCPClientOAuthError({
|
|
552
|
+
message: `OAuth endpoint URL is not allowed: ${endpointUrl.href}`,
|
|
553
|
+
cause: error
|
|
554
|
+
});
|
|
555
|
+
}
|
|
556
|
+
}
|
|
537
557
|
function createAuthorizationServerInformation(authorizationServerUrl, metadata) {
|
|
538
558
|
return {
|
|
539
559
|
authorizationServerUrl: normalizeUrl(authorizationServerUrl),
|
|
@@ -966,6 +986,7 @@ async function exchangeAuthorization(authorizationServerUrl, {
|
|
|
966
986
|
var _a3;
|
|
967
987
|
const grantType = "authorization_code";
|
|
968
988
|
const tokenUrl = (metadata == null ? void 0 : metadata.token_endpoint) ? new URL(metadata.token_endpoint) : new URL("/token", authorizationServerUrl);
|
|
989
|
+
assertSafeOAuthEndpoint(tokenUrl);
|
|
969
990
|
if ((metadata == null ? void 0 : metadata.grant_types_supported) && !metadata.grant_types_supported.includes(grantType)) {
|
|
970
991
|
throw new Error(
|
|
971
992
|
`Incompatible auth server: does not support grant type ${grantType}`
|
|
@@ -1002,7 +1023,8 @@ async function exchangeAuthorization(authorizationServerUrl, {
|
|
|
1002
1023
|
const response = await (fetchFn != null ? fetchFn : fetch)(tokenUrl, {
|
|
1003
1024
|
method: "POST",
|
|
1004
1025
|
headers,
|
|
1005
|
-
body: params
|
|
1026
|
+
body: params,
|
|
1027
|
+
redirect: "error"
|
|
1006
1028
|
});
|
|
1007
1029
|
if (!response.ok) {
|
|
1008
1030
|
throw await parseErrorResponse(response);
|
|
@@ -1030,6 +1052,7 @@ async function refreshAuthorization(authorizationServerUrl, {
|
|
|
1030
1052
|
} else {
|
|
1031
1053
|
tokenUrl = new URL("/token", authorizationServerUrl);
|
|
1032
1054
|
}
|
|
1055
|
+
assertSafeOAuthEndpoint(tokenUrl);
|
|
1033
1056
|
const headers = new Headers({
|
|
1034
1057
|
"Content-Type": "application/x-www-form-urlencoded",
|
|
1035
1058
|
Accept: "application/json"
|
|
@@ -1059,7 +1082,8 @@ async function refreshAuthorization(authorizationServerUrl, {
|
|
|
1059
1082
|
const response = await (fetchFn != null ? fetchFn : fetch)(tokenUrl, {
|
|
1060
1083
|
method: "POST",
|
|
1061
1084
|
headers,
|
|
1062
|
-
body: params
|
|
1085
|
+
body: params,
|
|
1086
|
+
redirect: "error"
|
|
1063
1087
|
});
|
|
1064
1088
|
if (!response.ok) {
|
|
1065
1089
|
throw await parseErrorResponse(response);
|
|
@@ -1085,12 +1109,14 @@ async function registerClient(authorizationServerUrl, {
|
|
|
1085
1109
|
} else {
|
|
1086
1110
|
registrationUrl = new URL("/register", authorizationServerUrl);
|
|
1087
1111
|
}
|
|
1112
|
+
assertSafeOAuthEndpoint(registrationUrl);
|
|
1088
1113
|
const response = await (fetchFn != null ? fetchFn : fetch)(registrationUrl, {
|
|
1089
1114
|
method: "POST",
|
|
1090
1115
|
headers: {
|
|
1091
1116
|
"Content-Type": "application/json"
|
|
1092
1117
|
},
|
|
1093
|
-
body: JSON.stringify(clientMetadata)
|
|
1118
|
+
body: JSON.stringify(clientMetadata),
|
|
1119
|
+
redirect: "error"
|
|
1094
1120
|
});
|
|
1095
1121
|
if (!response.ok) {
|
|
1096
1122
|
throw await parseErrorResponse(response);
|
|
@@ -1176,6 +1202,12 @@ async function authInternal(provider, {
|
|
|
1176
1202
|
}
|
|
1177
1203
|
);
|
|
1178
1204
|
const currentAuthorizationServerInformation = createAuthorizationServerInformation(authorizationServerUrl, metadata);
|
|
1205
|
+
const clientMetadata = provider.clientMetadata;
|
|
1206
|
+
const selectedScope = selectScope({
|
|
1207
|
+
scope,
|
|
1208
|
+
resourceMetadata,
|
|
1209
|
+
clientMetadata
|
|
1210
|
+
});
|
|
1179
1211
|
let clientInformation = await Promise.resolve(provider.clientInformation());
|
|
1180
1212
|
if (!clientInformation) {
|
|
1181
1213
|
if (authorizationCode !== void 0) {
|
|
@@ -1190,7 +1222,10 @@ async function authInternal(provider, {
|
|
|
1190
1222
|
}
|
|
1191
1223
|
const fullInformation = await registerClient(authorizationServerUrl, {
|
|
1192
1224
|
metadata,
|
|
1193
|
-
clientMetadata:
|
|
1225
|
+
clientMetadata: {
|
|
1226
|
+
...clientMetadata,
|
|
1227
|
+
scope: selectedScope
|
|
1228
|
+
},
|
|
1194
1229
|
fetchFn
|
|
1195
1230
|
});
|
|
1196
1231
|
clientInformation = addAuthorizationServerInformationToClientInformation(
|
|
@@ -1294,11 +1329,7 @@ async function authInternal(provider, {
|
|
|
1294
1329
|
clientInformation,
|
|
1295
1330
|
state,
|
|
1296
1331
|
redirectUrl: provider.redirectUrl,
|
|
1297
|
-
scope:
|
|
1298
|
-
scope,
|
|
1299
|
-
resourceMetadata,
|
|
1300
|
-
clientMetadata: provider.clientMetadata
|
|
1301
|
-
}),
|
|
1332
|
+
scope: selectedScope,
|
|
1302
1333
|
resource
|
|
1303
1334
|
}
|
|
1304
1335
|
);
|
|
@@ -2505,8 +2536,15 @@ var DefaultMCPClient = class {
|
|
|
2505
2536
|
async tools({
|
|
2506
2537
|
schemas = "automatic"
|
|
2507
2538
|
} = {}) {
|
|
2508
|
-
|
|
2509
|
-
|
|
2539
|
+
let definitions = await this.listTools();
|
|
2540
|
+
const tools = [...definitions.tools];
|
|
2541
|
+
while (definitions.nextCursor != null) {
|
|
2542
|
+
definitions = await this.listTools({
|
|
2543
|
+
params: { cursor: definitions.nextCursor }
|
|
2544
|
+
});
|
|
2545
|
+
tools.push(...definitions.tools);
|
|
2546
|
+
}
|
|
2547
|
+
return this.toolsFromDefinitions({ ...definitions, tools }, {
|
|
2510
2548
|
schemas
|
|
2511
2549
|
});
|
|
2512
2550
|
}
|