@ai-sdk/mcp 0.0.17 → 0.0.19
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 +29 -0
- package/dist/index.js +41 -27
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +28 -14
- package/dist/index.mjs.map +1 -1
- package/dist/mcp-stdio/index.js +15 -10
- package/dist/mcp-stdio/index.js.map +1 -1
- package/dist/mcp-stdio/index.mjs +15 -10
- package/dist/mcp-stdio/index.mjs.map +1 -1
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,34 @@
|
|
|
1
1
|
# @ai-sdk/mcp
|
|
2
2
|
|
|
3
|
+
## 0.0.19
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- d872a7a: fix(mcp): lock first sse endpoint received via event
|
|
8
|
+
- f4cd468: fix(mcp): prevent prototype-named tools from bypassing the `schemas` allowlist
|
|
9
|
+
|
|
10
|
+
When using `client.tools({ schemas })` to expose only an explicitly allowed
|
|
11
|
+
subset of an MCP server's tools, the allowlist check used the `in` operator,
|
|
12
|
+
which also matches inherited `Object.prototype` properties. A server-advertised
|
|
13
|
+
tool named `constructor`, `toString`, `__proto__`, etc. would pass the check
|
|
14
|
+
even though the developer never defined it in `schemas`, and was then exposed to
|
|
15
|
+
the model and executable. The check now uses `Object.hasOwn`, so only
|
|
16
|
+
explicitly defined tools are returned.
|
|
17
|
+
|
|
18
|
+
- Updated dependencies [9f67efe]
|
|
19
|
+
- Updated dependencies [eea9166]
|
|
20
|
+
- @ai-sdk/provider-utils@3.0.26
|
|
21
|
+
|
|
22
|
+
## 0.0.18
|
|
23
|
+
|
|
24
|
+
### Patch Changes
|
|
25
|
+
|
|
26
|
+
- 783fa6c: chore: ensure consistent import handling and avoid import duplicates or cycles
|
|
27
|
+
- c327fb9: fix(mcp): prevent prototype pollution by using secureJsonParse
|
|
28
|
+
- Updated dependencies [783fa6c]
|
|
29
|
+
- @ai-sdk/provider-utils@3.0.25
|
|
30
|
+
- @ai-sdk/provider@2.0.3
|
|
31
|
+
|
|
3
32
|
## 0.0.17
|
|
4
33
|
|
|
5
34
|
### Patch Changes
|
package/dist/index.js
CHANGED
|
@@ -39,7 +39,7 @@ __export(index_exports, {
|
|
|
39
39
|
module.exports = __toCommonJS(index_exports);
|
|
40
40
|
|
|
41
41
|
// src/tool/mcp-client.ts
|
|
42
|
-
var
|
|
42
|
+
var import_provider_utils5 = require("@ai-sdk/provider-utils");
|
|
43
43
|
|
|
44
44
|
// src/error/mcp-client-error.ts
|
|
45
45
|
var import_provider = require("@ai-sdk/provider");
|
|
@@ -66,9 +66,10 @@ var MCPClientError = class extends (_b = import_provider.AISDKError, _a = symbol
|
|
|
66
66
|
};
|
|
67
67
|
|
|
68
68
|
// src/tool/mcp-sse-transport.ts
|
|
69
|
-
var
|
|
69
|
+
var import_provider_utils3 = require("@ai-sdk/provider-utils");
|
|
70
70
|
|
|
71
71
|
// src/tool/json-rpc-message.ts
|
|
72
|
+
var import_provider_utils = require("@ai-sdk/provider-utils");
|
|
72
73
|
var import_v42 = require("zod/v4");
|
|
73
74
|
|
|
74
75
|
// src/tool/types.ts
|
|
@@ -288,6 +289,9 @@ var JSONRPCMessageSchema = import_v42.z.union([
|
|
|
288
289
|
JSONRPCResponseSchema,
|
|
289
290
|
JSONRPCErrorSchema
|
|
290
291
|
]);
|
|
292
|
+
async function parseJSONRPCMessage(text) {
|
|
293
|
+
return JSONRPCMessageSchema.parse(await (0, import_provider_utils.parseJSON)({ text }));
|
|
294
|
+
}
|
|
291
295
|
|
|
292
296
|
// src/version.ts
|
|
293
297
|
var VERSION = typeof __PACKAGE_VERSION__ !== "undefined" ? __PACKAGE_VERSION__ : "0.0.0-test";
|
|
@@ -465,6 +469,7 @@ function checkResourceAllowed({
|
|
|
465
469
|
}
|
|
466
470
|
|
|
467
471
|
// src/tool/oauth.ts
|
|
472
|
+
var import_provider_utils2 = require("@ai-sdk/provider-utils");
|
|
468
473
|
var UnauthorizedError = class extends Error {
|
|
469
474
|
constructor(message = "Unauthorized") {
|
|
470
475
|
super(message);
|
|
@@ -743,7 +748,9 @@ async function parseErrorResponse(input) {
|
|
|
743
748
|
const statusCode = input instanceof Response ? input.status : void 0;
|
|
744
749
|
const body = input instanceof Response ? await input.text() : input;
|
|
745
750
|
try {
|
|
746
|
-
const result = OAuthErrorResponseSchema.parse(
|
|
751
|
+
const result = OAuthErrorResponseSchema.parse(
|
|
752
|
+
await (0, import_provider_utils2.parseJSON)({ text: body })
|
|
753
|
+
);
|
|
747
754
|
const { error, error_description, error_uri } = result;
|
|
748
755
|
const errorClass = OAUTH_ERRORS[error] || ServerError;
|
|
749
756
|
return new errorClass({
|
|
@@ -1057,10 +1064,10 @@ var SseMCPTransport = class {
|
|
|
1057
1064
|
headers["Authorization"] = `Bearer ${tokens.access_token}`;
|
|
1058
1065
|
}
|
|
1059
1066
|
}
|
|
1060
|
-
return (0,
|
|
1067
|
+
return (0, import_provider_utils3.withUserAgentSuffix)(
|
|
1061
1068
|
headers,
|
|
1062
1069
|
`ai-sdk/${VERSION}`,
|
|
1063
|
-
(0,
|
|
1070
|
+
(0, import_provider_utils3.getRuntimeEnvironmentUserAgent)()
|
|
1064
1071
|
);
|
|
1065
1072
|
}
|
|
1066
1073
|
async start() {
|
|
@@ -1108,10 +1115,10 @@ var SseMCPTransport = class {
|
|
|
1108
1115
|
(_d = this.onerror) == null ? void 0 : _d.call(this, error);
|
|
1109
1116
|
return reject(error);
|
|
1110
1117
|
}
|
|
1111
|
-
const stream = response.body.pipeThrough(new TextDecoderStream()).pipeThrough(new
|
|
1118
|
+
const stream = response.body.pipeThrough(new TextDecoderStream()).pipeThrough(new import_provider_utils3.EventSourceParserStream());
|
|
1112
1119
|
const reader = stream.getReader();
|
|
1113
1120
|
const processEvents = async () => {
|
|
1114
|
-
var _a4, _b4, _c2;
|
|
1121
|
+
var _a4, _b4, _c2, _d2, _e2;
|
|
1115
1122
|
try {
|
|
1116
1123
|
while (true) {
|
|
1117
1124
|
const { done, value } = await reader.read();
|
|
@@ -1126,26 +1133,32 @@ var SseMCPTransport = class {
|
|
|
1126
1133
|
}
|
|
1127
1134
|
const { event, data } = value;
|
|
1128
1135
|
if (event === "endpoint") {
|
|
1129
|
-
|
|
1130
|
-
|
|
1136
|
+
if (this.endpoint) {
|
|
1137
|
+
continue;
|
|
1138
|
+
}
|
|
1139
|
+
const endpoint = new URL(data, this.url);
|
|
1140
|
+
if (endpoint.origin !== this.url.origin) {
|
|
1141
|
+
this.connected = false;
|
|
1142
|
+
this.endpoint = void 0;
|
|
1143
|
+
(_a4 = this.sseConnection) == null ? void 0 : _a4.close();
|
|
1144
|
+
(_b4 = this.abortController) == null ? void 0 : _b4.abort();
|
|
1131
1145
|
throw new MCPClientError({
|
|
1132
|
-
message: `MCP SSE Transport Error: Endpoint origin does not match connection origin: ${
|
|
1146
|
+
message: `MCP SSE Transport Error: Endpoint origin does not match connection origin: ${endpoint.origin}`
|
|
1133
1147
|
});
|
|
1134
1148
|
}
|
|
1149
|
+
this.endpoint = endpoint;
|
|
1135
1150
|
this.connected = true;
|
|
1136
1151
|
resolve();
|
|
1137
1152
|
} else if (event === "message") {
|
|
1138
1153
|
try {
|
|
1139
|
-
const message =
|
|
1140
|
-
|
|
1141
|
-
);
|
|
1142
|
-
(_a4 = this.onmessage) == null ? void 0 : _a4.call(this, message);
|
|
1154
|
+
const message = await parseJSONRPCMessage(data);
|
|
1155
|
+
(_c2 = this.onmessage) == null ? void 0 : _c2.call(this, message);
|
|
1143
1156
|
} catch (error) {
|
|
1144
1157
|
const e = new MCPClientError({
|
|
1145
1158
|
message: "MCP SSE Transport Error: Failed to parse message",
|
|
1146
1159
|
cause: error
|
|
1147
1160
|
});
|
|
1148
|
-
(
|
|
1161
|
+
(_d2 = this.onerror) == null ? void 0 : _d2.call(this, e);
|
|
1149
1162
|
}
|
|
1150
1163
|
}
|
|
1151
1164
|
}
|
|
@@ -1153,7 +1166,7 @@ var SseMCPTransport = class {
|
|
|
1153
1166
|
if (error instanceof Error && error.name === "AbortError") {
|
|
1154
1167
|
return;
|
|
1155
1168
|
}
|
|
1156
|
-
(
|
|
1169
|
+
(_e2 = this.onerror) == null ? void 0 : _e2.call(this, error);
|
|
1157
1170
|
reject(error);
|
|
1158
1171
|
}
|
|
1159
1172
|
};
|
|
@@ -1175,6 +1188,7 @@ var SseMCPTransport = class {
|
|
|
1175
1188
|
async close() {
|
|
1176
1189
|
var _a3, _b3, _c;
|
|
1177
1190
|
this.connected = false;
|
|
1191
|
+
this.endpoint = void 0;
|
|
1178
1192
|
(_a3 = this.sseConnection) == null ? void 0 : _a3.close();
|
|
1179
1193
|
(_b3 = this.abortController) == null ? void 0 : _b3.abort();
|
|
1180
1194
|
(_c = this.onclose) == null ? void 0 : _c.call(this);
|
|
@@ -1235,7 +1249,7 @@ var SseMCPTransport = class {
|
|
|
1235
1249
|
};
|
|
1236
1250
|
|
|
1237
1251
|
// src/tool/mcp-http-transport.ts
|
|
1238
|
-
var
|
|
1252
|
+
var import_provider_utils4 = require("@ai-sdk/provider-utils");
|
|
1239
1253
|
var HttpMCPTransport = class {
|
|
1240
1254
|
constructor({
|
|
1241
1255
|
url,
|
|
@@ -1268,10 +1282,10 @@ var HttpMCPTransport = class {
|
|
|
1268
1282
|
headers["Authorization"] = `Bearer ${tokens.access_token}`;
|
|
1269
1283
|
}
|
|
1270
1284
|
}
|
|
1271
|
-
return (0,
|
|
1285
|
+
return (0, import_provider_utils4.withUserAgentSuffix)(
|
|
1272
1286
|
headers,
|
|
1273
1287
|
`ai-sdk/${VERSION}`,
|
|
1274
|
-
(0,
|
|
1288
|
+
(0, import_provider_utils4.getRuntimeEnvironmentUserAgent)()
|
|
1275
1289
|
);
|
|
1276
1290
|
}
|
|
1277
1291
|
async start() {
|
|
@@ -1369,7 +1383,7 @@ var HttpMCPTransport = class {
|
|
|
1369
1383
|
(_e = this.onerror) == null ? void 0 : _e.call(this, error2);
|
|
1370
1384
|
throw error2;
|
|
1371
1385
|
}
|
|
1372
|
-
const stream = response.body.pipeThrough(new TextDecoderStream()).pipeThrough(new
|
|
1386
|
+
const stream = response.body.pipeThrough(new TextDecoderStream()).pipeThrough(new import_provider_utils4.EventSourceParserStream());
|
|
1373
1387
|
const reader = stream.getReader();
|
|
1374
1388
|
const processEvents = async () => {
|
|
1375
1389
|
var _a4, _b4, _c2;
|
|
@@ -1380,7 +1394,7 @@ var HttpMCPTransport = class {
|
|
|
1380
1394
|
const { event, data } = value;
|
|
1381
1395
|
if (event === "message") {
|
|
1382
1396
|
try {
|
|
1383
|
-
const msg =
|
|
1397
|
+
const msg = await parseJSONRPCMessage(data);
|
|
1384
1398
|
(_a4 = this.onmessage) == null ? void 0 : _a4.call(this, msg);
|
|
1385
1399
|
} catch (error2) {
|
|
1386
1400
|
const e = new MCPClientError({
|
|
@@ -1491,7 +1505,7 @@ var HttpMCPTransport = class {
|
|
|
1491
1505
|
(_d = this.onerror) == null ? void 0 : _d.call(this, error);
|
|
1492
1506
|
return;
|
|
1493
1507
|
}
|
|
1494
|
-
const stream = response.body.pipeThrough(new TextDecoderStream()).pipeThrough(new
|
|
1508
|
+
const stream = response.body.pipeThrough(new TextDecoderStream()).pipeThrough(new import_provider_utils4.EventSourceParserStream());
|
|
1495
1509
|
const reader = stream.getReader();
|
|
1496
1510
|
const processEvents = async () => {
|
|
1497
1511
|
var _a4, _b4, _c2, _d2;
|
|
@@ -1505,7 +1519,7 @@ var HttpMCPTransport = class {
|
|
|
1505
1519
|
}
|
|
1506
1520
|
if (event === "message") {
|
|
1507
1521
|
try {
|
|
1508
|
-
const msg =
|
|
1522
|
+
const msg = await parseJSONRPCMessage(data);
|
|
1509
1523
|
(_a4 = this.onmessage) == null ? void 0 : _a4.call(this, msg);
|
|
1510
1524
|
} catch (error) {
|
|
1511
1525
|
const e = new MCPClientError({
|
|
@@ -1858,7 +1872,7 @@ var DefaultMCPClient = class {
|
|
|
1858
1872
|
try {
|
|
1859
1873
|
const listToolsResult = await this.listTools();
|
|
1860
1874
|
for (const { name: name3, description, inputSchema } of listToolsResult.tools) {
|
|
1861
|
-
if (schemas !== "automatic" && !(name3
|
|
1875
|
+
if (schemas !== "automatic" && !Object.prototype.hasOwnProperty.call(schemas, name3)) {
|
|
1862
1876
|
continue;
|
|
1863
1877
|
}
|
|
1864
1878
|
const self = this;
|
|
@@ -1867,15 +1881,15 @@ var DefaultMCPClient = class {
|
|
|
1867
1881
|
(_a4 = options == null ? void 0 : options.abortSignal) == null ? void 0 : _a4.throwIfAborted();
|
|
1868
1882
|
return self.callTool({ name: name3, args, options });
|
|
1869
1883
|
};
|
|
1870
|
-
const toolWithExecute = schemas === "automatic" ? (0,
|
|
1884
|
+
const toolWithExecute = schemas === "automatic" ? (0, import_provider_utils5.dynamicTool)({
|
|
1871
1885
|
description,
|
|
1872
|
-
inputSchema: (0,
|
|
1886
|
+
inputSchema: (0, import_provider_utils5.jsonSchema)({
|
|
1873
1887
|
...inputSchema,
|
|
1874
1888
|
properties: (_a3 = inputSchema.properties) != null ? _a3 : {},
|
|
1875
1889
|
additionalProperties: false
|
|
1876
1890
|
}),
|
|
1877
1891
|
execute
|
|
1878
|
-
}) : (0,
|
|
1892
|
+
}) : (0, import_provider_utils5.tool)({
|
|
1879
1893
|
description,
|
|
1880
1894
|
inputSchema: schemas[name3].inputSchema,
|
|
1881
1895
|
execute
|