@ai-sdk/mcp 2.0.3 → 2.0.5
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 +16 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +79 -4
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/src/tool/mcp-client.ts +122 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# @ai-sdk/mcp
|
|
2
2
|
|
|
3
|
+
## 2.0.5
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 8c616f0: feat(mcp): add maxRetries option for failed mcp tool calls
|
|
8
|
+
- Updated dependencies [8c616f0]
|
|
9
|
+
- @ai-sdk/provider-utils@5.0.3
|
|
10
|
+
|
|
11
|
+
## 2.0.4
|
|
12
|
+
|
|
13
|
+
### Patch Changes
|
|
14
|
+
|
|
15
|
+
- Updated dependencies [0274f34]
|
|
16
|
+
- @ai-sdk/provider@4.0.1
|
|
17
|
+
- @ai-sdk/provider-utils@5.0.2
|
|
18
|
+
|
|
3
19
|
## 2.0.3
|
|
4
20
|
|
|
5
21
|
### Patch Changes
|
package/dist/index.d.ts
CHANGED
|
@@ -600,6 +600,15 @@ interface MCPClientConfig {
|
|
|
600
600
|
transport: MCPTransportConfig | MCPTransport;
|
|
601
601
|
/** Optional callback for uncaught errors */
|
|
602
602
|
onUncaughtError?: (error: unknown) => void;
|
|
603
|
+
/**
|
|
604
|
+
* Maximum number of retries for transient MCP tool call failures.
|
|
605
|
+
*
|
|
606
|
+
* Set to 0 to disable retries. Retries only apply to tools/call requests.
|
|
607
|
+
* JSON-RPC application errors, such as invalid params, are not retried.
|
|
608
|
+
*
|
|
609
|
+
* @default 0
|
|
610
|
+
*/
|
|
611
|
+
maxRetries?: number;
|
|
603
612
|
/**
|
|
604
613
|
* Initialize result from a previous MCP session. When provided, the client
|
|
605
614
|
* starts the transport and reuses this metadata without sending a new
|
package/dist/index.js
CHANGED
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
asSchema,
|
|
4
4
|
dynamicTool,
|
|
5
5
|
jsonSchema,
|
|
6
|
+
retryWithExponentialBackoff,
|
|
6
7
|
safeParseJSON,
|
|
7
8
|
safeValidateTypes,
|
|
8
9
|
tool
|
|
@@ -2042,6 +2043,55 @@ async function readMCPAppResource({
|
|
|
2042
2043
|
|
|
2043
2044
|
// src/tool/mcp-client.ts
|
|
2044
2045
|
var CLIENT_VERSION = "1.0.0";
|
|
2046
|
+
var DEFAULT_MAX_TOOL_CALL_RETRIES = 0;
|
|
2047
|
+
var DEFAULT_RETRY_ERROR_CODES = [
|
|
2048
|
+
"ConnectionRefused",
|
|
2049
|
+
"ConnectionClosed",
|
|
2050
|
+
"FailedToOpenSocket",
|
|
2051
|
+
"ECONNRESET",
|
|
2052
|
+
"ECONNREFUSED",
|
|
2053
|
+
"ETIMEDOUT",
|
|
2054
|
+
"EPIPE"
|
|
2055
|
+
];
|
|
2056
|
+
function getErrorStatusCode(error) {
|
|
2057
|
+
if (error != null && typeof error === "object" && "statusCode" in error && typeof error.statusCode === "number") {
|
|
2058
|
+
return error.statusCode;
|
|
2059
|
+
}
|
|
2060
|
+
return void 0;
|
|
2061
|
+
}
|
|
2062
|
+
function getStringErrorCode(error) {
|
|
2063
|
+
if (error != null && typeof error === "object" && "code" in error && typeof error.code === "string") {
|
|
2064
|
+
return error.code;
|
|
2065
|
+
}
|
|
2066
|
+
return void 0;
|
|
2067
|
+
}
|
|
2068
|
+
function isRetryableMCPToolCallError(error) {
|
|
2069
|
+
const statusCode = getErrorStatusCode(error);
|
|
2070
|
+
if (statusCode != null) {
|
|
2071
|
+
return statusCode === 408 || statusCode === 409 || statusCode === 429 || statusCode >= 500;
|
|
2072
|
+
}
|
|
2073
|
+
if (MCPClientError.isInstance(error) && error.code != null) {
|
|
2074
|
+
return false;
|
|
2075
|
+
}
|
|
2076
|
+
const errorCode = getStringErrorCode(error);
|
|
2077
|
+
return errorCode != null && DEFAULT_RETRY_ERROR_CODES.includes(errorCode);
|
|
2078
|
+
}
|
|
2079
|
+
function prepareMaxRetries(maxRetries) {
|
|
2080
|
+
if (maxRetries == null) {
|
|
2081
|
+
return DEFAULT_MAX_TOOL_CALL_RETRIES;
|
|
2082
|
+
}
|
|
2083
|
+
if (!Number.isInteger(maxRetries)) {
|
|
2084
|
+
throw new MCPClientError({
|
|
2085
|
+
message: "maxRetries must be an integer"
|
|
2086
|
+
});
|
|
2087
|
+
}
|
|
2088
|
+
if (maxRetries < 0) {
|
|
2089
|
+
throw new MCPClientError({
|
|
2090
|
+
message: "maxRetries must be >= 0"
|
|
2091
|
+
});
|
|
2092
|
+
}
|
|
2093
|
+
return maxRetries;
|
|
2094
|
+
}
|
|
2045
2095
|
function mcpToModelOutput({
|
|
2046
2096
|
output
|
|
2047
2097
|
}) {
|
|
@@ -2078,6 +2128,7 @@ var DefaultMCPClient = class {
|
|
|
2078
2128
|
clientName = name3 != null ? name3 : "ai-sdk-mcp-client",
|
|
2079
2129
|
version = CLIENT_VERSION,
|
|
2080
2130
|
onUncaughtError,
|
|
2131
|
+
maxRetries,
|
|
2081
2132
|
capabilities,
|
|
2082
2133
|
initialInitializeResult
|
|
2083
2134
|
}) {
|
|
@@ -2092,6 +2143,7 @@ var DefaultMCPClient = class {
|
|
|
2092
2143
|
};
|
|
2093
2144
|
this.isClosed = true;
|
|
2094
2145
|
this.onUncaughtError = onUncaughtError;
|
|
2146
|
+
this.maxRetries = prepareMaxRetries(maxRetries);
|
|
2095
2147
|
this.clientCapabilities = capabilities != null ? capabilities : {};
|
|
2096
2148
|
this.initialInitializeResult = initialInitializeResult;
|
|
2097
2149
|
if (isCustomMcpTransport(transportConfig)) {
|
|
@@ -2295,16 +2347,39 @@ var DefaultMCPClient = class {
|
|
|
2295
2347
|
options
|
|
2296
2348
|
});
|
|
2297
2349
|
}
|
|
2350
|
+
async callToolWithRetry({
|
|
2351
|
+
options,
|
|
2352
|
+
execute
|
|
2353
|
+
}) {
|
|
2354
|
+
if (this.maxRetries === 0) {
|
|
2355
|
+
return execute();
|
|
2356
|
+
}
|
|
2357
|
+
return retryWithExponentialBackoff({
|
|
2358
|
+
maxRetries: this.maxRetries,
|
|
2359
|
+
abortSignal: options == null ? void 0 : options.signal,
|
|
2360
|
+
shouldRetry: isRetryableMCPToolCallError,
|
|
2361
|
+
createRetryError: ({ message, errors }) => new MCPClientError({
|
|
2362
|
+
message,
|
|
2363
|
+
cause: errors[errors.length - 1]
|
|
2364
|
+
})
|
|
2365
|
+
})(execute);
|
|
2366
|
+
}
|
|
2298
2367
|
async callTool({
|
|
2299
2368
|
name: name3,
|
|
2300
2369
|
arguments: args = {},
|
|
2301
2370
|
options
|
|
2302
2371
|
}) {
|
|
2303
2372
|
try {
|
|
2304
|
-
return this.
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2373
|
+
return this.callToolWithRetry({
|
|
2374
|
+
options,
|
|
2375
|
+
execute: () => this.request({
|
|
2376
|
+
request: {
|
|
2377
|
+
method: "tools/call",
|
|
2378
|
+
params: { name: name3, arguments: args }
|
|
2379
|
+
},
|
|
2380
|
+
resultSchema: CallToolResultSchema,
|
|
2381
|
+
options
|
|
2382
|
+
})
|
|
2308
2383
|
});
|
|
2309
2384
|
} catch (error) {
|
|
2310
2385
|
throw error;
|