@ai-sdk/mcp 1.0.56 → 1.0.58

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 CHANGED
@@ -1,5 +1,19 @@
1
1
  # @ai-sdk/mcp
2
2
 
3
+ ## 1.0.58
4
+
5
+ ### Patch Changes
6
+
7
+ - f12f0d3: feat(mcp): expose a json-rpc message validator
8
+
9
+ ## 1.0.57
10
+
11
+ ### Patch Changes
12
+
13
+ - ea1e95b: feat(mcp): add maxRetries option for failed mcp tool calls
14
+ - Updated dependencies [ea1e95b]
15
+ - @ai-sdk/provider-utils@4.0.35
16
+
3
17
  ## 1.0.56
4
18
 
5
19
  ### Patch Changes
package/dist/index.d.mts CHANGED
@@ -66,6 +66,7 @@ declare const JSONRPCMessageSchema: z.ZodUnion<readonly [z.ZodObject<{
66
66
  }, z.core.$strip>;
67
67
  }, z.core.$strict>]>;
68
68
  type JSONRPCMessage = z.infer<typeof JSONRPCMessageSchema>;
69
+ declare function validateJSONRPCMessage(message: unknown): JSONRPCMessage;
69
70
 
70
71
  /**
71
72
  * OAuth 2.1 token response
@@ -534,6 +535,15 @@ interface MCPClientConfig {
534
535
  transport: MCPTransportConfig | MCPTransport;
535
536
  /** Optional callback for uncaught errors */
536
537
  onUncaughtError?: (error: unknown) => void;
538
+ /**
539
+ * Maximum number of retries for transient MCP tool call failures.
540
+ *
541
+ * Set to 0 to disable retries. Retries only apply to tools/call requests.
542
+ * JSON-RPC application errors, such as invalid params, are not retried.
543
+ *
544
+ * @default 0
545
+ */
546
+ maxRetries?: number;
537
547
  /** Optional client name, defaults to 'ai-sdk-mcp-client' */
538
548
  clientName?: string;
539
549
  /**
@@ -610,4 +620,4 @@ interface MCPClient {
610
620
  close: () => Promise<void>;
611
621
  }
612
622
 
613
- export { type CallToolResult, type CompleteRequestParams, type CompleteResult, type Configuration, type ElicitResult, ElicitResultSchema, type ElicitationRequest, ElicitationRequestSchema, type JSONRPCError, type JSONRPCMessage, type JSONRPCNotification, type JSONRPCRequest, type JSONRPCResponse, type ListToolsResult, type MCPClient, type ClientCapabilities as MCPClientCapabilities, type MCPClientConfig, type MCPTransport, type OAuthAuthorizationServerInformation, type OAuthClientInformation, type OAuthClientMetadata, type OAuthClientProvider, type OAuthTokens, UnauthorizedError, auth, createMCPClient, type MCPClient as experimental_MCPClient, type ClientCapabilities as experimental_MCPClientCapabilities, type MCPClientConfig as experimental_MCPClientConfig, createMCPClient as experimental_createMCPClient };
623
+ export { type CallToolResult, type CompleteRequestParams, type CompleteResult, type Configuration, type ElicitResult, ElicitResultSchema, type ElicitationRequest, ElicitationRequestSchema, type JSONRPCError, type JSONRPCMessage, type JSONRPCNotification, type JSONRPCRequest, type JSONRPCResponse, type ListToolsResult, type MCPClient, type ClientCapabilities as MCPClientCapabilities, type MCPClientConfig, type MCPTransport, type OAuthAuthorizationServerInformation, type OAuthClientInformation, type OAuthClientMetadata, type OAuthClientProvider, type OAuthTokens, UnauthorizedError, auth, createMCPClient, type MCPClient as experimental_MCPClient, type ClientCapabilities as experimental_MCPClientCapabilities, type MCPClientConfig as experimental_MCPClientConfig, createMCPClient as experimental_createMCPClient, validateJSONRPCMessage };
package/dist/index.d.ts CHANGED
@@ -66,6 +66,7 @@ declare const JSONRPCMessageSchema: z.ZodUnion<readonly [z.ZodObject<{
66
66
  }, z.core.$strip>;
67
67
  }, z.core.$strict>]>;
68
68
  type JSONRPCMessage = z.infer<typeof JSONRPCMessageSchema>;
69
+ declare function validateJSONRPCMessage(message: unknown): JSONRPCMessage;
69
70
 
70
71
  /**
71
72
  * OAuth 2.1 token response
@@ -534,6 +535,15 @@ interface MCPClientConfig {
534
535
  transport: MCPTransportConfig | MCPTransport;
535
536
  /** Optional callback for uncaught errors */
536
537
  onUncaughtError?: (error: unknown) => void;
538
+ /**
539
+ * Maximum number of retries for transient MCP tool call failures.
540
+ *
541
+ * Set to 0 to disable retries. Retries only apply to tools/call requests.
542
+ * JSON-RPC application errors, such as invalid params, are not retried.
543
+ *
544
+ * @default 0
545
+ */
546
+ maxRetries?: number;
537
547
  /** Optional client name, defaults to 'ai-sdk-mcp-client' */
538
548
  clientName?: string;
539
549
  /**
@@ -610,4 +620,4 @@ interface MCPClient {
610
620
  close: () => Promise<void>;
611
621
  }
612
622
 
613
- export { type CallToolResult, type CompleteRequestParams, type CompleteResult, type Configuration, type ElicitResult, ElicitResultSchema, type ElicitationRequest, ElicitationRequestSchema, type JSONRPCError, type JSONRPCMessage, type JSONRPCNotification, type JSONRPCRequest, type JSONRPCResponse, type ListToolsResult, type MCPClient, type ClientCapabilities as MCPClientCapabilities, type MCPClientConfig, type MCPTransport, type OAuthAuthorizationServerInformation, type OAuthClientInformation, type OAuthClientMetadata, type OAuthClientProvider, type OAuthTokens, UnauthorizedError, auth, createMCPClient, type MCPClient as experimental_MCPClient, type ClientCapabilities as experimental_MCPClientCapabilities, type MCPClientConfig as experimental_MCPClientConfig, createMCPClient as experimental_createMCPClient };
623
+ export { type CallToolResult, type CompleteRequestParams, type CompleteResult, type Configuration, type ElicitResult, ElicitResultSchema, type ElicitationRequest, ElicitationRequestSchema, type JSONRPCError, type JSONRPCMessage, type JSONRPCNotification, type JSONRPCRequest, type JSONRPCResponse, type ListToolsResult, type MCPClient, type ClientCapabilities as MCPClientCapabilities, type MCPClientConfig, type MCPTransport, type OAuthAuthorizationServerInformation, type OAuthClientInformation, type OAuthClientMetadata, type OAuthClientProvider, type OAuthTokens, UnauthorizedError, auth, createMCPClient, type MCPClient as experimental_MCPClient, type ClientCapabilities as experimental_MCPClientCapabilities, type MCPClientConfig as experimental_MCPClientConfig, createMCPClient as experimental_createMCPClient, validateJSONRPCMessage };
package/dist/index.js CHANGED
@@ -35,46 +35,11 @@ __export(index_exports, {
35
35
  UnauthorizedError: () => UnauthorizedError,
36
36
  auth: () => auth,
37
37
  createMCPClient: () => createMCPClient,
38
- experimental_createMCPClient: () => createMCPClient
38
+ experimental_createMCPClient: () => createMCPClient,
39
+ validateJSONRPCMessage: () => validateJSONRPCMessage
39
40
  });
40
41
  module.exports = __toCommonJS(index_exports);
41
42
 
42
- // src/tool/mcp-client.ts
43
- var import_provider_utils5 = require("@ai-sdk/provider-utils");
44
-
45
- // src/error/mcp-client-error.ts
46
- var import_provider = require("@ai-sdk/provider");
47
- var name = "AI_MCPClientError";
48
- var marker = `vercel.ai.error.${name}`;
49
- var symbol = Symbol.for(marker);
50
- var _a, _b;
51
- var MCPClientError = class extends (_b = import_provider.AISDKError, _a = symbol, _b) {
52
- constructor({
53
- name: name3 = "MCPClientError",
54
- message,
55
- cause,
56
- data,
57
- code,
58
- statusCode,
59
- url,
60
- responseBody
61
- }) {
62
- super({ name: name3, message, cause });
63
- this[_a] = true;
64
- this.data = data;
65
- this.code = code;
66
- this.statusCode = statusCode;
67
- this.url = url;
68
- this.responseBody = responseBody;
69
- }
70
- static isInstance(error) {
71
- return import_provider.AISDKError.hasMarker(error, marker);
72
- }
73
- };
74
-
75
- // src/tool/mcp-sse-transport.ts
76
- var import_provider_utils3 = require("@ai-sdk/provider-utils");
77
-
78
43
  // src/tool/json-rpc-message.ts
79
44
  var import_provider_utils = require("@ai-sdk/provider-utils");
80
45
  var import_v42 = require("zod/v4");
@@ -359,10 +324,49 @@ var JSONRPCMessageSchema = import_v42.z.union([
359
324
  JSONRPCResponseSchema,
360
325
  JSONRPCErrorSchema
361
326
  ]);
327
+ function validateJSONRPCMessage(message) {
328
+ return JSONRPCMessageSchema.parse(message);
329
+ }
362
330
  async function parseJSONRPCMessage(text) {
363
- return JSONRPCMessageSchema.parse(await (0, import_provider_utils.parseJSON)({ text }));
331
+ return validateJSONRPCMessage(await (0, import_provider_utils.parseJSON)({ text }));
364
332
  }
365
333
 
334
+ // src/tool/mcp-client.ts
335
+ var import_provider_utils5 = require("@ai-sdk/provider-utils");
336
+
337
+ // src/error/mcp-client-error.ts
338
+ var import_provider = require("@ai-sdk/provider");
339
+ var name = "AI_MCPClientError";
340
+ var marker = `vercel.ai.error.${name}`;
341
+ var symbol = Symbol.for(marker);
342
+ var _a, _b;
343
+ var MCPClientError = class extends (_b = import_provider.AISDKError, _a = symbol, _b) {
344
+ constructor({
345
+ name: name3 = "MCPClientError",
346
+ message,
347
+ cause,
348
+ data,
349
+ code,
350
+ statusCode,
351
+ url,
352
+ responseBody
353
+ }) {
354
+ super({ name: name3, message, cause });
355
+ this[_a] = true;
356
+ this.data = data;
357
+ this.code = code;
358
+ this.statusCode = statusCode;
359
+ this.url = url;
360
+ this.responseBody = responseBody;
361
+ }
362
+ static isInstance(error) {
363
+ return import_provider.AISDKError.hasMarker(error, marker);
364
+ }
365
+ };
366
+
367
+ // src/tool/mcp-sse-transport.ts
368
+ var import_provider_utils3 = require("@ai-sdk/provider-utils");
369
+
366
370
  // src/version.ts
367
371
  var VERSION = typeof __PACKAGE_VERSION__ !== "undefined" ? __PACKAGE_VERSION__ : "0.0.0-test";
368
372
 
@@ -1705,8 +1709,10 @@ var HttpMCPTransport = class {
1705
1709
  const contentType = response.headers.get("content-type") || "";
1706
1710
  if (contentType.includes("application/json")) {
1707
1711
  const data = await response.json();
1708
- const messages = Array.isArray(data) ? data.map((m) => JSONRPCMessageSchema.parse(m)) : [JSONRPCMessageSchema.parse(data)];
1709
- for (const m of messages) (_d = this.onmessage) == null ? void 0 : _d.call(this, m);
1712
+ const messages = Array.isArray(data) ? data.map((message2) => validateJSONRPCMessage(message2)) : [validateJSONRPCMessage(data)];
1713
+ for (const jsonRpcMessage of messages) {
1714
+ (_d = this.onmessage) == null ? void 0 : _d.call(this, jsonRpcMessage);
1715
+ }
1710
1716
  return;
1711
1717
  }
1712
1718
  if (contentType.includes("text/event-stream")) {
@@ -1914,6 +1920,55 @@ function isCustomMcpTransport(transport) {
1914
1920
 
1915
1921
  // src/tool/mcp-client.ts
1916
1922
  var CLIENT_VERSION = "1.0.0";
1923
+ var DEFAULT_MAX_TOOL_CALL_RETRIES = 0;
1924
+ var DEFAULT_RETRY_ERROR_CODES = [
1925
+ "ConnectionRefused",
1926
+ "ConnectionClosed",
1927
+ "FailedToOpenSocket",
1928
+ "ECONNRESET",
1929
+ "ECONNREFUSED",
1930
+ "ETIMEDOUT",
1931
+ "EPIPE"
1932
+ ];
1933
+ function getErrorStatusCode(error) {
1934
+ if (error != null && typeof error === "object" && "statusCode" in error && typeof error.statusCode === "number") {
1935
+ return error.statusCode;
1936
+ }
1937
+ return void 0;
1938
+ }
1939
+ function getStringErrorCode(error) {
1940
+ if (error != null && typeof error === "object" && "code" in error && typeof error.code === "string") {
1941
+ return error.code;
1942
+ }
1943
+ return void 0;
1944
+ }
1945
+ function isRetryableMCPToolCallError(error) {
1946
+ const statusCode = getErrorStatusCode(error);
1947
+ if (statusCode != null) {
1948
+ return statusCode === 408 || statusCode === 409 || statusCode === 429 || statusCode >= 500;
1949
+ }
1950
+ if (MCPClientError.isInstance(error) && error.code != null) {
1951
+ return false;
1952
+ }
1953
+ const errorCode = getStringErrorCode(error);
1954
+ return errorCode != null && DEFAULT_RETRY_ERROR_CODES.includes(errorCode);
1955
+ }
1956
+ function prepareMaxRetries(maxRetries) {
1957
+ if (maxRetries == null) {
1958
+ return DEFAULT_MAX_TOOL_CALL_RETRIES;
1959
+ }
1960
+ if (!Number.isInteger(maxRetries)) {
1961
+ throw new MCPClientError({
1962
+ message: "maxRetries must be an integer"
1963
+ });
1964
+ }
1965
+ if (maxRetries < 0) {
1966
+ throw new MCPClientError({
1967
+ message: "maxRetries must be >= 0"
1968
+ });
1969
+ }
1970
+ return maxRetries;
1971
+ }
1917
1972
  function mcpToModelOutput({
1918
1973
  output
1919
1974
  }) {
@@ -1950,6 +2005,7 @@ var DefaultMCPClient = class {
1950
2005
  clientName = name3 != null ? name3 : "ai-sdk-mcp-client",
1951
2006
  version = CLIENT_VERSION,
1952
2007
  onUncaughtError,
2008
+ maxRetries,
1953
2009
  capabilities
1954
2010
  }) {
1955
2011
  this.requestMessageId = 0;
@@ -1958,6 +2014,7 @@ var DefaultMCPClient = class {
1958
2014
  this._serverInfo = { name: "", version: "" };
1959
2015
  this.isClosed = true;
1960
2016
  this.onUncaughtError = onUncaughtError;
2017
+ this.maxRetries = prepareMaxRetries(maxRetries);
1961
2018
  this.clientCapabilities = capabilities != null ? capabilities : {};
1962
2019
  if (isCustomMcpTransport(transportConfig)) {
1963
2020
  this.transport = transportConfig;
@@ -2146,18 +2203,41 @@ var DefaultMCPClient = class {
2146
2203
  options
2147
2204
  });
2148
2205
  }
2206
+ async callToolWithRetry({
2207
+ options,
2208
+ execute
2209
+ }) {
2210
+ if (this.maxRetries === 0) {
2211
+ return execute();
2212
+ }
2213
+ return (0, import_provider_utils5.retryWithExponentialBackoff)({
2214
+ maxRetries: this.maxRetries,
2215
+ abortSignal: options == null ? void 0 : options.abortSignal,
2216
+ shouldRetry: isRetryableMCPToolCallError,
2217
+ createRetryError: ({ message, errors }) => new MCPClientError({
2218
+ message,
2219
+ cause: errors[errors.length - 1]
2220
+ })
2221
+ })(execute);
2222
+ }
2149
2223
  async callTool({
2150
2224
  name: name3,
2151
2225
  args,
2152
2226
  options
2153
2227
  }) {
2154
2228
  try {
2155
- return this.request({
2156
- request: { method: "tools/call", params: { name: name3, arguments: args } },
2157
- resultSchema: CallToolResultSchema,
2158
- options: {
2159
- signal: options == null ? void 0 : options.abortSignal
2160
- }
2229
+ return this.callToolWithRetry({
2230
+ options,
2231
+ execute: () => this.request({
2232
+ request: {
2233
+ method: "tools/call",
2234
+ params: { name: name3, arguments: args }
2235
+ },
2236
+ resultSchema: CallToolResultSchema,
2237
+ options: {
2238
+ signal: options == null ? void 0 : options.abortSignal
2239
+ }
2240
+ })
2161
2241
  });
2162
2242
  } catch (error) {
2163
2243
  throw error;
@@ -2516,6 +2596,7 @@ var DefaultMCPClient = class {
2516
2596
  UnauthorizedError,
2517
2597
  auth,
2518
2598
  createMCPClient,
2519
- experimental_createMCPClient
2599
+ experimental_createMCPClient,
2600
+ validateJSONRPCMessage
2520
2601
  });
2521
2602
  //# sourceMappingURL=index.js.map