@ai-sdk/mcp 2.0.0-canary.54 → 2.0.0-canary.56
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 +21 -0
- package/dist/index.js +40 -13
- package/dist/index.js.map +1 -1
- package/dist/mcp-stdio/index.js +7 -1
- package/dist/mcp-stdio/index.js.map +1 -1
- package/package.json +1 -1
- package/src/error/mcp-client-error.ts +40 -0
- package/src/tool/mcp-client.ts +9 -0
- package/src/tool/mcp-http-transport.ts +19 -6
- package/src/tool/oauth-types.ts +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
# @ai-sdk/mcp
|
|
2
2
|
|
|
3
|
+
## 2.0.0-canary.56
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- dcefad3: fix(mcp): respond to ping requests with an empty result per JSON-RPC spec (closes #6282)
|
|
8
|
+
|
|
9
|
+
## 2.0.0-canary.55
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- f7bc0b4: feat(mcp): expose `statusCode`, `url`, and `responseBody` on `MCPClientError` for HTTP transport failures
|
|
14
|
+
|
|
15
|
+
`MCPClientError` now carries structured HTTP context when it originates from the
|
|
16
|
+
streamable HTTP transport. This lets downstream consumers (e.g. agent frameworks
|
|
17
|
+
that need to decide whether to fall back from streamable HTTP to legacy SSE
|
|
18
|
+
transport per the MCP spec) branch on the actual response status without parsing
|
|
19
|
+
the error message string.
|
|
20
|
+
|
|
21
|
+
Fields are optional — they remain `undefined` for stdio transport errors and for
|
|
22
|
+
non-response failures (network errors, aborts).
|
|
23
|
+
|
|
3
24
|
## 2.0.0-canary.54
|
|
4
25
|
|
|
5
26
|
### Patch Changes
|
package/dist/index.js
CHANGED
|
@@ -20,12 +20,18 @@ var MCPClientError = class extends (_b = AISDKError, _a = symbol, _b) {
|
|
|
20
20
|
message,
|
|
21
21
|
cause,
|
|
22
22
|
data,
|
|
23
|
-
code
|
|
23
|
+
code,
|
|
24
|
+
statusCode,
|
|
25
|
+
url,
|
|
26
|
+
responseBody
|
|
24
27
|
}) {
|
|
25
28
|
super({ name: name3, message, cause });
|
|
26
29
|
this[_a] = true;
|
|
27
30
|
this.data = data;
|
|
28
31
|
this.code = code;
|
|
32
|
+
this.statusCode = statusCode;
|
|
33
|
+
this.url = url;
|
|
34
|
+
this.responseBody = responseBody;
|
|
29
35
|
}
|
|
30
36
|
static isInstance(error) {
|
|
31
37
|
return AISDKError.hasMarker(error, marker);
|
|
@@ -326,8 +332,8 @@ var SafeUrlSchema = z3.string().url().superRefine((val, ctx) => {
|
|
|
326
332
|
}
|
|
327
333
|
}).refine(
|
|
328
334
|
(url) => {
|
|
329
|
-
const
|
|
330
|
-
return
|
|
335
|
+
const parsedUrl = new URL(url);
|
|
336
|
+
return parsedUrl.protocol !== "javascript:" && parsedUrl.protocol !== "data:" && parsedUrl.protocol !== "vbscript:";
|
|
331
337
|
},
|
|
332
338
|
{ message: "URL cannot use javascript:, data:, or vbscript: scheme" }
|
|
333
339
|
);
|
|
@@ -1417,7 +1423,10 @@ var HttpMCPTransport = class {
|
|
|
1417
1423
|
errorMessage += ". This server does not support HTTP transport. Try using `sse` transport instead";
|
|
1418
1424
|
}
|
|
1419
1425
|
const error2 = new MCPClientError({
|
|
1420
|
-
message: errorMessage
|
|
1426
|
+
message: errorMessage,
|
|
1427
|
+
statusCode: response.status,
|
|
1428
|
+
url: this.url.href,
|
|
1429
|
+
responseBody: text != null ? text : void 0
|
|
1421
1430
|
});
|
|
1422
1431
|
(_c = this.onerror) == null ? void 0 : _c.call(this, error2);
|
|
1423
1432
|
throw error2;
|
|
@@ -1429,14 +1438,20 @@ var HttpMCPTransport = class {
|
|
|
1429
1438
|
const contentType = response.headers.get("content-type") || "";
|
|
1430
1439
|
if (contentType.includes("application/json")) {
|
|
1431
1440
|
const data = await response.json();
|
|
1432
|
-
const messages = Array.isArray(data) ? data.map(
|
|
1433
|
-
|
|
1441
|
+
const messages = Array.isArray(data) ? data.map(
|
|
1442
|
+
(message2) => JSONRPCMessageSchema.parse(message2)
|
|
1443
|
+
) : [JSONRPCMessageSchema.parse(data)];
|
|
1444
|
+
for (const jsonRpcMessage of messages) {
|
|
1445
|
+
(_d = this.onmessage) == null ? void 0 : _d.call(this, jsonRpcMessage);
|
|
1446
|
+
}
|
|
1434
1447
|
return;
|
|
1435
1448
|
}
|
|
1436
1449
|
if (contentType.includes("text/event-stream")) {
|
|
1437
1450
|
if (!response.body) {
|
|
1438
1451
|
const error2 = new MCPClientError({
|
|
1439
|
-
message: "MCP HTTP Transport Error: text/event-stream response without body"
|
|
1452
|
+
message: "MCP HTTP Transport Error: text/event-stream response without body",
|
|
1453
|
+
statusCode: response.status,
|
|
1454
|
+
url: this.url.href
|
|
1440
1455
|
});
|
|
1441
1456
|
(_e = this.onerror) == null ? void 0 : _e.call(this, error2);
|
|
1442
1457
|
throw error2;
|
|
@@ -1452,8 +1467,8 @@ var HttpMCPTransport = class {
|
|
|
1452
1467
|
const { event, data } = value;
|
|
1453
1468
|
if (event === "message") {
|
|
1454
1469
|
try {
|
|
1455
|
-
const
|
|
1456
|
-
(_a4 = this.onmessage) == null ? void 0 : _a4.call(this,
|
|
1470
|
+
const jsonRpcMessage = await parseJSONRPCMessage(data);
|
|
1471
|
+
(_a4 = this.onmessage) == null ? void 0 : _a4.call(this, jsonRpcMessage);
|
|
1457
1472
|
} catch (error2) {
|
|
1458
1473
|
const e = new MCPClientError({
|
|
1459
1474
|
message: "MCP HTTP Transport Error: Failed to parse message",
|
|
@@ -1474,7 +1489,9 @@ var HttpMCPTransport = class {
|
|
|
1474
1489
|
return;
|
|
1475
1490
|
}
|
|
1476
1491
|
const error = new MCPClientError({
|
|
1477
|
-
message: `MCP HTTP Transport Error: Unexpected content type: ${contentType}
|
|
1492
|
+
message: `MCP HTTP Transport Error: Unexpected content type: ${contentType}`,
|
|
1493
|
+
statusCode: response.status,
|
|
1494
|
+
url: this.url.href
|
|
1478
1495
|
});
|
|
1479
1496
|
(_f = this.onerror) == null ? void 0 : _f.call(this, error);
|
|
1480
1497
|
throw error;
|
|
@@ -1556,7 +1573,9 @@ var HttpMCPTransport = class {
|
|
|
1556
1573
|
}
|
|
1557
1574
|
if (!response.ok || !response.body) {
|
|
1558
1575
|
const error = new MCPClientError({
|
|
1559
|
-
message: `MCP HTTP Transport Error: GET SSE failed: ${response.status} ${response.statusText}
|
|
1576
|
+
message: `MCP HTTP Transport Error: GET SSE failed: ${response.status} ${response.statusText}`,
|
|
1577
|
+
statusCode: response.status,
|
|
1578
|
+
url: this.url.href
|
|
1560
1579
|
});
|
|
1561
1580
|
(_d = this.onerror) == null ? void 0 : _d.call(this, error);
|
|
1562
1581
|
return;
|
|
@@ -1575,8 +1594,8 @@ var HttpMCPTransport = class {
|
|
|
1575
1594
|
}
|
|
1576
1595
|
if (event === "message") {
|
|
1577
1596
|
try {
|
|
1578
|
-
const
|
|
1579
|
-
(_a4 = this.onmessage) == null ? void 0 : _a4.call(this,
|
|
1597
|
+
const jsonRpcMessage = await parseJSONRPCMessage(data);
|
|
1598
|
+
(_a4 = this.onmessage) == null ? void 0 : _a4.call(this, jsonRpcMessage);
|
|
1580
1599
|
} catch (error) {
|
|
1581
1600
|
const e = new MCPClientError({
|
|
1582
1601
|
message: "MCP HTTP Transport Error: Failed to parse message",
|
|
@@ -2213,6 +2232,14 @@ var DefaultMCPClient = class {
|
|
|
2213
2232
|
}
|
|
2214
2233
|
async onRequestMessage(request) {
|
|
2215
2234
|
try {
|
|
2235
|
+
if (request.method === "ping") {
|
|
2236
|
+
await this.transport.send({
|
|
2237
|
+
jsonrpc: "2.0",
|
|
2238
|
+
id: request.id,
|
|
2239
|
+
result: {}
|
|
2240
|
+
});
|
|
2241
|
+
return;
|
|
2242
|
+
}
|
|
2216
2243
|
if (request.method !== "elicitation/create") {
|
|
2217
2244
|
await this.transport.send({
|
|
2218
2245
|
jsonrpc: "2.0",
|