@ai-sdk/mcp 1.0.64 → 1.0.66

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,18 @@
1
1
  # @ai-sdk/mcp
2
2
 
3
+ ## 1.0.66
4
+
5
+ ### Patch Changes
6
+
7
+ - e8d2654: Honor MCP request deadlines and support bounding or aborting client initialization.
8
+
9
+ ## 1.0.65
10
+
11
+ ### Patch Changes
12
+
13
+ - Updated dependencies [9ecdefe]
14
+ - @ai-sdk/provider-utils@4.0.41
15
+
3
16
  ## 1.0.64
4
17
 
5
18
  ### Patch Changes
package/dist/index.d.mts CHANGED
@@ -218,6 +218,30 @@ declare function auth(provider: OAuthClientProvider, options: {
218
218
  * Transport interface for MCP (Model Context Protocol) communication.
219
219
  * Maps to the `Transport` interface in the MCP spec.
220
220
  */
221
+ type MCPTransportSendOptions = {
222
+ /**
223
+ * Cancels the transport operation for this message.
224
+ */
225
+ signal?: AbortSignal;
226
+ /**
227
+ * Associates an outgoing message with an incoming request.
228
+ */
229
+ relatedRequestId?: string | number;
230
+ /**
231
+ * Resumes a previously interrupted request.
232
+ */
233
+ resumptionToken?: string;
234
+ /**
235
+ * Receives updated resumption tokens from transports that support them.
236
+ */
237
+ onresumptiontoken?: (token: string) => void;
238
+ };
239
+ type MCPTransportCloseOptions = {
240
+ /**
241
+ * Cancels transport cleanup.
242
+ */
243
+ signal?: AbortSignal;
244
+ };
221
245
  interface MCPTransport {
222
246
  /**
223
247
  * Initialize and start the transport
@@ -226,12 +250,14 @@ interface MCPTransport {
226
250
  /**
227
251
  * Send a JSON-RPC message through the transport
228
252
  * @param message The JSON-RPC message to send
253
+ * @param options Optional request-scoped cancellation options
229
254
  */
230
- send(message: JSONRPCMessage): Promise<void>;
255
+ send(message: JSONRPCMessage, options?: MCPTransportSendOptions): Promise<void>;
231
256
  /**
232
257
  * Clean up and close the transport
258
+ * @param options Optional cancellation options for transport cleanup
233
259
  */
234
- close(): Promise<void>;
260
+ close(options?: MCPTransportCloseOptions): Promise<void>;
235
261
  /**
236
262
  * Event handler for transport closure
237
263
  */
@@ -533,6 +559,10 @@ type ElicitResult = z.infer<typeof ElicitResultSchema>;
533
559
  interface MCPClientConfig {
534
560
  /** Transport configuration for connecting to the MCP server */
535
561
  transport: MCPTransportConfig | MCPTransport;
562
+ /**
563
+ * Options that bound or cancel transport startup and the initialize request.
564
+ */
565
+ initializationOptions?: RequestOptions;
536
566
  /** Optional callback for uncaught errors */
537
567
  onUncaughtError?: (error: unknown) => void;
538
568
  /**
@@ -620,4 +650,4 @@ interface MCPClient {
620
650
  close: () => Promise<void>;
621
651
  }
622
652
 
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 };
653
+ 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 MCPTransportCloseOptions, type MCPTransportSendOptions, 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
@@ -218,6 +218,30 @@ declare function auth(provider: OAuthClientProvider, options: {
218
218
  * Transport interface for MCP (Model Context Protocol) communication.
219
219
  * Maps to the `Transport` interface in the MCP spec.
220
220
  */
221
+ type MCPTransportSendOptions = {
222
+ /**
223
+ * Cancels the transport operation for this message.
224
+ */
225
+ signal?: AbortSignal;
226
+ /**
227
+ * Associates an outgoing message with an incoming request.
228
+ */
229
+ relatedRequestId?: string | number;
230
+ /**
231
+ * Resumes a previously interrupted request.
232
+ */
233
+ resumptionToken?: string;
234
+ /**
235
+ * Receives updated resumption tokens from transports that support them.
236
+ */
237
+ onresumptiontoken?: (token: string) => void;
238
+ };
239
+ type MCPTransportCloseOptions = {
240
+ /**
241
+ * Cancels transport cleanup.
242
+ */
243
+ signal?: AbortSignal;
244
+ };
221
245
  interface MCPTransport {
222
246
  /**
223
247
  * Initialize and start the transport
@@ -226,12 +250,14 @@ interface MCPTransport {
226
250
  /**
227
251
  * Send a JSON-RPC message through the transport
228
252
  * @param message The JSON-RPC message to send
253
+ * @param options Optional request-scoped cancellation options
229
254
  */
230
- send(message: JSONRPCMessage): Promise<void>;
255
+ send(message: JSONRPCMessage, options?: MCPTransportSendOptions): Promise<void>;
231
256
  /**
232
257
  * Clean up and close the transport
258
+ * @param options Optional cancellation options for transport cleanup
233
259
  */
234
- close(): Promise<void>;
260
+ close(options?: MCPTransportCloseOptions): Promise<void>;
235
261
  /**
236
262
  * Event handler for transport closure
237
263
  */
@@ -533,6 +559,10 @@ type ElicitResult = z.infer<typeof ElicitResultSchema>;
533
559
  interface MCPClientConfig {
534
560
  /** Transport configuration for connecting to the MCP server */
535
561
  transport: MCPTransportConfig | MCPTransport;
562
+ /**
563
+ * Options that bound or cancel transport startup and the initialize request.
564
+ */
565
+ initializationOptions?: RequestOptions;
536
566
  /** Optional callback for uncaught errors */
537
567
  onUncaughtError?: (error: unknown) => void;
538
568
  /**
@@ -620,4 +650,4 @@ interface MCPClient {
620
650
  close: () => Promise<void>;
621
651
  }
622
652
 
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 };
653
+ 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 MCPTransportCloseOptions, type MCPTransportSendOptions, 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
@@ -1494,15 +1494,19 @@ var SseMCPTransport = class {
1494
1494
  (_b3 = this.abortController) == null ? void 0 : _b3.abort();
1495
1495
  (_c = this.onclose) == null ? void 0 : _c.call(this);
1496
1496
  }
1497
- async send(message) {
1497
+ async send(message, options) {
1498
+ var _a3, _b3;
1499
+ (_a3 = options == null ? void 0 : options.signal) == null ? void 0 : _a3.throwIfAborted();
1498
1500
  if (!this.endpoint || !this.connected) {
1499
1501
  throw new MCPClientError({
1500
1502
  message: "MCP SSE Transport Error: Not connected"
1501
1503
  });
1502
1504
  }
1503
1505
  const endpoint = this.endpoint;
1506
+ const transportSignal = (_b3 = this.abortController) == null ? void 0 : _b3.signal;
1507
+ const requestSignal = (options == null ? void 0 : options.signal) == null ? transportSignal : transportSignal == null ? options.signal : AbortSignal.any([transportSignal, options.signal]);
1504
1508
  const attempt = async (triedAuth = false) => {
1505
- var _a3, _b3, _c, _d, _e;
1509
+ var _a4, _b4, _c, _d, _e;
1506
1510
  try {
1507
1511
  const headers = await this.commonHeaders({
1508
1512
  "Content-Type": "application/json"
@@ -1511,7 +1515,7 @@ var SseMCPTransport = class {
1511
1515
  method: "POST",
1512
1516
  headers,
1513
1517
  body: JSON.stringify(message),
1514
- signal: (_a3 = this.abortController) == null ? void 0 : _a3.signal,
1518
+ signal: requestSignal,
1515
1519
  redirect: this.redirectMode
1516
1520
  };
1517
1521
  const response = await this.fetchFn(endpoint.href, init);
@@ -1525,11 +1529,11 @@ var SseMCPTransport = class {
1525
1529
  });
1526
1530
  if (result !== "AUTHORIZED") {
1527
1531
  const error = new UnauthorizedError();
1528
- (_b3 = this.onerror) == null ? void 0 : _b3.call(this, error);
1532
+ (_a4 = this.onerror) == null ? void 0 : _a4.call(this, error);
1529
1533
  return;
1530
1534
  }
1531
1535
  } catch (error) {
1532
- (_c = this.onerror) == null ? void 0 : _c.call(this, error);
1536
+ (_b4 = this.onerror) == null ? void 0 : _b4.call(this, error);
1533
1537
  return;
1534
1538
  }
1535
1539
  return attempt(true);
@@ -1539,10 +1543,13 @@ var SseMCPTransport = class {
1539
1543
  const error = new MCPClientError({
1540
1544
  message: `MCP SSE Transport Error: POSTing to endpoint (HTTP ${response.status}): ${text}`
1541
1545
  });
1542
- (_d = this.onerror) == null ? void 0 : _d.call(this, error);
1546
+ (_c = this.onerror) == null ? void 0 : _c.call(this, error);
1543
1547
  return;
1544
1548
  }
1545
1549
  } catch (error) {
1550
+ if ((_d = options == null ? void 0 : options.signal) == null ? void 0 : _d.aborted) {
1551
+ throw error;
1552
+ }
1546
1553
  (_e = this.onerror) == null ? void 0 : _e.call(this, error);
1547
1554
  return;
1548
1555
  }
@@ -1629,27 +1636,33 @@ var HttpMCPTransport = class {
1629
1636
  this.abortController = new AbortController();
1630
1637
  this.startInboundSse();
1631
1638
  }
1632
- async close() {
1633
- var _a3, _b3, _c;
1639
+ async close(options) {
1640
+ var _a3, _b3, _c, _d, _e;
1634
1641
  (_a3 = this.inboundSseConnection) == null ? void 0 : _a3.close();
1642
+ (_b3 = this.abortController) == null ? void 0 : _b3.abort();
1635
1643
  try {
1636
- if (this.sessionId && this.abortController && !this.abortController.signal.aborted) {
1644
+ if (this.sessionId && this.abortController) {
1645
+ (_c = options == null ? void 0 : options.signal) == null ? void 0 : _c.throwIfAborted();
1637
1646
  const headers = await this.commonHeaders({});
1647
+ (_d = options == null ? void 0 : options.signal) == null ? void 0 : _d.throwIfAborted();
1638
1648
  await this.fetchFn(this.url.href, {
1639
1649
  method: "DELETE",
1640
1650
  headers,
1641
- signal: this.abortController.signal,
1651
+ signal: options == null ? void 0 : options.signal,
1642
1652
  redirect: this.redirectMode
1643
1653
  }).catch(() => void 0);
1644
1654
  }
1645
1655
  } catch (e) {
1646
1656
  }
1647
- (_b3 = this.abortController) == null ? void 0 : _b3.abort();
1648
- (_c = this.onclose) == null ? void 0 : _c.call(this);
1657
+ (_e = this.onclose) == null ? void 0 : _e.call(this);
1649
1658
  }
1650
- async send(message) {
1659
+ async send(message, options) {
1660
+ var _a3, _b3;
1661
+ (_a3 = options == null ? void 0 : options.signal) == null ? void 0 : _a3.throwIfAborted();
1662
+ const transportSignal = (_b3 = this.abortController) == null ? void 0 : _b3.signal;
1663
+ const requestSignal = (options == null ? void 0 : options.signal) == null ? transportSignal : transportSignal == null ? options.signal : AbortSignal.any([transportSignal, options.signal]);
1651
1664
  const attempt = async (triedAuth = false) => {
1652
- var _a3, _b3, _c, _d, _e, _f, _g;
1665
+ var _a4, _b4, _c, _d, _e, _f, _g;
1653
1666
  try {
1654
1667
  const headers = await this.commonHeaders({
1655
1668
  "Content-Type": "application/json",
@@ -1659,7 +1672,7 @@ var HttpMCPTransport = class {
1659
1672
  method: "POST",
1660
1673
  headers,
1661
1674
  body: JSON.stringify(message),
1662
- signal: (_a3 = this.abortController) == null ? void 0 : _a3.signal,
1675
+ signal: requestSignal,
1663
1676
  redirect: this.redirectMode
1664
1677
  };
1665
1678
  const response = await this.fetchFn(this.url.href, init);
@@ -1676,7 +1689,7 @@ var HttpMCPTransport = class {
1676
1689
  throw error2;
1677
1690
  }
1678
1691
  } catch (error2) {
1679
- (_b3 = this.onerror) == null ? void 0 : _b3.call(this, error2);
1692
+ (_a4 = this.onerror) == null ? void 0 : _a4.call(this, error2);
1680
1693
  throw error2;
1681
1694
  }
1682
1695
  return attempt(true);
@@ -1699,7 +1712,7 @@ var HttpMCPTransport = class {
1699
1712
  url: this.url.href,
1700
1713
  responseBody: text != null ? text : void 0
1701
1714
  });
1702
- (_c = this.onerror) == null ? void 0 : _c.call(this, error2);
1715
+ (_b4 = this.onerror) == null ? void 0 : _b4.call(this, error2);
1703
1716
  throw error2;
1704
1717
  }
1705
1718
  const isNotification = !("id" in message);
@@ -1711,7 +1724,7 @@ var HttpMCPTransport = class {
1711
1724
  const data = await response.json();
1712
1725
  const messages = Array.isArray(data) ? data.map((message2) => validateJSONRPCMessage(message2)) : [validateJSONRPCMessage(data)];
1713
1726
  for (const jsonRpcMessage of messages) {
1714
- (_d = this.onmessage) == null ? void 0 : _d.call(this, jsonRpcMessage);
1727
+ (_c = this.onmessage) == null ? void 0 : _c.call(this, jsonRpcMessage);
1715
1728
  }
1716
1729
  return;
1717
1730
  }
@@ -1722,13 +1735,13 @@ var HttpMCPTransport = class {
1722
1735
  statusCode: response.status,
1723
1736
  url: this.url.href
1724
1737
  });
1725
- (_e = this.onerror) == null ? void 0 : _e.call(this, error2);
1738
+ (_d = this.onerror) == null ? void 0 : _d.call(this, error2);
1726
1739
  throw error2;
1727
1740
  }
1728
1741
  const stream = response.body.pipeThrough(new TextDecoderStream()).pipeThrough(new import_provider_utils4.EventSourceParserStream());
1729
1742
  const reader = stream.getReader();
1730
1743
  const processEvents = async () => {
1731
- var _a4, _b4, _c2;
1744
+ var _a5, _b5, _c2, _d2;
1732
1745
  try {
1733
1746
  while (true) {
1734
1747
  const { done, value } = await reader.read();
@@ -1737,29 +1750,29 @@ var HttpMCPTransport = class {
1737
1750
  if (isMessageEvent2(event)) {
1738
1751
  try {
1739
1752
  const msg = await parseJSONRPCMessage(data);
1740
- (_a4 = this.onmessage) == null ? void 0 : _a4.call(this, msg);
1753
+ (_a5 = this.onmessage) == null ? void 0 : _a5.call(this, msg);
1741
1754
  } catch (error2) {
1742
1755
  const e = new MCPClientError({
1743
1756
  message: "MCP HTTP Transport Error: Failed to parse message",
1744
1757
  cause: error2
1745
1758
  });
1746
- (_b4 = this.onerror) == null ? void 0 : _b4.call(this, e);
1759
+ (_b5 = this.onerror) == null ? void 0 : _b5.call(this, e);
1747
1760
  }
1748
1761
  }
1749
1762
  }
1750
1763
  } catch (error2) {
1751
- if (error2 instanceof Error && error2.name === "AbortError") {
1764
+ if (((_c2 = options == null ? void 0 : options.signal) == null ? void 0 : _c2.aborted) || error2 instanceof Error && error2.name === "AbortError") {
1752
1765
  return;
1753
1766
  }
1754
- (_c2 = this.onerror) == null ? void 0 : _c2.call(this, error2);
1767
+ (_d2 = this.onerror) == null ? void 0 : _d2.call(this, error2);
1755
1768
  }
1756
1769
  };
1757
1770
  void processEvents().catch((error2) => {
1758
- var _a4;
1759
- if (error2 instanceof Error && error2.name === "AbortError") {
1771
+ var _a5, _b5;
1772
+ if (((_a5 = options == null ? void 0 : options.signal) == null ? void 0 : _a5.aborted) || error2 instanceof Error && error2.name === "AbortError") {
1760
1773
  return;
1761
1774
  }
1762
- (_a4 = this.onerror) == null ? void 0 : _a4.call(this, error2);
1775
+ (_b5 = this.onerror) == null ? void 0 : _b5.call(this, error2);
1763
1776
  });
1764
1777
  return;
1765
1778
  }
@@ -1768,9 +1781,12 @@ var HttpMCPTransport = class {
1768
1781
  statusCode: response.status,
1769
1782
  url: this.url.href
1770
1783
  });
1771
- (_f = this.onerror) == null ? void 0 : _f.call(this, error);
1784
+ (_e = this.onerror) == null ? void 0 : _e.call(this, error);
1772
1785
  throw error;
1773
1786
  } catch (error) {
1787
+ if ((_f = options == null ? void 0 : options.signal) == null ? void 0 : _f.aborted) {
1788
+ throw error;
1789
+ }
1774
1790
  (_g = this.onerror) == null ? void 0 : _g.call(this, error);
1775
1791
  throw error;
1776
1792
  }
@@ -2001,6 +2017,44 @@ function prepareMaxRetries(maxRetries) {
2001
2017
  }
2002
2018
  return maxRetries;
2003
2019
  }
2020
+ function getEffectiveTimeout({
2021
+ timeout,
2022
+ maxTotalTimeout
2023
+ }) {
2024
+ if (timeout == null) {
2025
+ return maxTotalTimeout;
2026
+ }
2027
+ if (maxTotalTimeout == null) {
2028
+ return timeout;
2029
+ }
2030
+ return Math.min(timeout, maxTotalTimeout);
2031
+ }
2032
+ function waitForAbort(promise, signal) {
2033
+ if (signal == null) {
2034
+ return promise;
2035
+ }
2036
+ return new Promise((resolve, reject) => {
2037
+ const cleanup = () => {
2038
+ signal.removeEventListener("abort", onAbort);
2039
+ };
2040
+ const onAbort = () => {
2041
+ cleanup();
2042
+ reject(signal.reason);
2043
+ };
2044
+ if (signal.aborted) {
2045
+ onAbort();
2046
+ return;
2047
+ }
2048
+ signal.addEventListener("abort", onAbort, { once: true });
2049
+ promise.then((value) => {
2050
+ cleanup();
2051
+ resolve(value);
2052
+ }).catch((error) => {
2053
+ cleanup();
2054
+ reject(error);
2055
+ });
2056
+ });
2057
+ }
2004
2058
  function mcpToModelOutput({
2005
2059
  output
2006
2060
  }) {
@@ -2038,7 +2092,8 @@ var DefaultMCPClient = class {
2038
2092
  version = CLIENT_VERSION,
2039
2093
  onUncaughtError,
2040
2094
  maxRetries,
2041
- capabilities
2095
+ capabilities,
2096
+ initializationOptions
2042
2097
  }) {
2043
2098
  this.requestMessageId = 0;
2044
2099
  this.responseHandlers = /* @__PURE__ */ new Map();
@@ -2048,6 +2103,7 @@ var DefaultMCPClient = class {
2048
2103
  this.onUncaughtError = onUncaughtError;
2049
2104
  this.maxRetries = prepareMaxRetries(maxRetries);
2050
2105
  this.clientCapabilities = capabilities != null ? capabilities : {};
2106
+ this.initializationOptions = initializationOptions;
2051
2107
  if (isCustomMcpTransport(transportConfig)) {
2052
2108
  this.transport = transportConfig;
2053
2109
  } else {
@@ -2082,9 +2138,25 @@ var DefaultMCPClient = class {
2082
2138
  return this._serverInstructions;
2083
2139
  }
2084
2140
  async init() {
2141
+ var _a3;
2142
+ const externalSignal = (_a3 = this.initializationOptions) == null ? void 0 : _a3.signal;
2143
+ const timeout = this.initializationOptions ? getEffectiveTimeout(this.initializationOptions) : void 0;
2144
+ const timeoutController = timeout == null ? void 0 : new AbortController();
2145
+ const signal = externalSignal == null ? timeoutController == null ? void 0 : timeoutController.signal : timeoutController == null ? externalSignal : AbortSignal.any([externalSignal, timeoutController.signal]);
2146
+ let timeoutId;
2147
+ let timeoutError;
2148
+ if (timeout != null) {
2149
+ timeoutId = setTimeout(() => {
2150
+ timeoutError = new MCPClientError({
2151
+ message: `MCP client initialization timed out after ${timeout}ms`
2152
+ });
2153
+ timeoutController == null ? void 0 : timeoutController.abort(timeoutError);
2154
+ }, timeout);
2155
+ }
2085
2156
  try {
2086
- await this.transport.start();
2087
2157
  this.isClosed = false;
2158
+ signal == null ? void 0 : signal.throwIfAborted();
2159
+ await waitForAbort(this.transport.start(), signal);
2088
2160
  const result = await this.request({
2089
2161
  request: {
2090
2162
  method: "initialize",
@@ -2094,7 +2166,8 @@ var DefaultMCPClient = class {
2094
2166
  clientInfo: this.clientInfo
2095
2167
  }
2096
2168
  },
2097
- resultSchema: InitializeResultSchema
2169
+ resultSchema: InitializeResultSchema,
2170
+ options: { signal }
2098
2171
  });
2099
2172
  if (result === void 0) {
2100
2173
  throw new MCPClientError({
@@ -2114,13 +2187,33 @@ var DefaultMCPClient = class {
2114
2187
  this.transport.protocolVersion = result.protocolVersion;
2115
2188
  }
2116
2189
  this._serverInstructions = result.instructions;
2117
- await this.notification({
2118
- method: "notifications/initialized"
2119
- });
2190
+ await this.notification(
2191
+ {
2192
+ method: "notifications/initialized"
2193
+ },
2194
+ { signal }
2195
+ );
2120
2196
  return this;
2121
2197
  } catch (error) {
2122
- await this.close();
2198
+ try {
2199
+ await waitForAbort(this.transport.close({ signal }), signal);
2200
+ } catch (e) {
2201
+ }
2202
+ this.onClose();
2203
+ if (timeoutError != null) {
2204
+ throw timeoutError;
2205
+ }
2206
+ if (externalSignal == null ? void 0 : externalSignal.aborted) {
2207
+ throw new MCPClientError({
2208
+ message: "MCP client initialization was aborted",
2209
+ cause: externalSignal.reason
2210
+ });
2211
+ }
2123
2212
  throw error;
2213
+ } finally {
2214
+ if (timeoutId != null) {
2215
+ clearTimeout(timeoutId);
2216
+ }
2124
2217
  }
2125
2218
  }
2126
2219
  async close() {
@@ -2129,6 +2222,12 @@ var DefaultMCPClient = class {
2129
2222
  await ((_a3 = this.transport) == null ? void 0 : _a3.close());
2130
2223
  this.onClose();
2131
2224
  }
2225
+ send(message, signal) {
2226
+ return this.transport.send(
2227
+ message,
2228
+ signal == null ? void 0 : { signal }
2229
+ );
2230
+ }
2132
2231
  assertCapability(method) {
2133
2232
  switch (method) {
2134
2233
  case "initialize":
@@ -2187,6 +2286,10 @@ var DefaultMCPClient = class {
2187
2286
  this.assertCapability(request.method);
2188
2287
  const signal = options == null ? void 0 : options.signal;
2189
2288
  signal == null ? void 0 : signal.throwIfAborted();
2289
+ const timeout = options == null ? void 0 : getEffectiveTimeout(options);
2290
+ const timeoutController = timeout == null ? void 0 : new AbortController();
2291
+ const transportSignal = signal == null ? timeoutController == null ? void 0 : timeoutController.signal : timeoutController == null ? signal : AbortSignal.any([signal, timeoutController.signal]);
2292
+ let timeoutId;
2190
2293
  const messageId = this.requestMessageId++;
2191
2294
  const jsonrpcRequest = {
2192
2295
  ...request,
@@ -2204,6 +2307,9 @@ var DefaultMCPClient = class {
2204
2307
  const cleanup = () => {
2205
2308
  this.responseHandlers.delete(messageId);
2206
2309
  signal == null ? void 0 : signal.removeEventListener("abort", onAbort);
2310
+ if (timeoutId != null) {
2311
+ clearTimeout(timeoutId);
2312
+ }
2207
2313
  };
2208
2314
  const rejectAndCleanup = (error) => {
2209
2315
  cleanup();
@@ -2213,6 +2319,13 @@ var DefaultMCPClient = class {
2213
2319
  cleanup();
2214
2320
  rejectWithAbortError();
2215
2321
  };
2322
+ const onTimeout = () => {
2323
+ const error = new MCPClientError({
2324
+ message: `Request timed out after ${timeout}ms`
2325
+ });
2326
+ timeoutController == null ? void 0 : timeoutController.abort(error);
2327
+ rejectAndCleanup(error);
2328
+ };
2216
2329
  this.responseHandlers.set(messageId, (response) => {
2217
2330
  if (signal == null ? void 0 : signal.aborted) {
2218
2331
  cleanup();
@@ -2234,7 +2347,11 @@ var DefaultMCPClient = class {
2234
2347
  }
2235
2348
  });
2236
2349
  signal == null ? void 0 : signal.addEventListener("abort", onAbort, { once: true });
2237
- this.transport.send(jsonrpcRequest).catch((error) => {
2350
+ if (timeout != null) {
2351
+ timeoutId = setTimeout(onTimeout, timeout);
2352
+ }
2353
+ const sendPromise = transportSignal == null ? this.transport.send(jsonrpcRequest) : this.send(jsonrpcRequest, transportSignal);
2354
+ sendPromise.catch((error) => {
2238
2355
  rejectAndCleanup(error);
2239
2356
  });
2240
2357
  });
@@ -2369,12 +2486,15 @@ var DefaultMCPClient = class {
2369
2486
  options
2370
2487
  });
2371
2488
  }
2372
- async notification(notification) {
2489
+ async notification(notification, options) {
2373
2490
  const jsonrpcNotification = {
2374
2491
  ...notification,
2375
2492
  jsonrpc: "2.0"
2376
2493
  };
2377
- await this.transport.send(jsonrpcNotification);
2494
+ await waitForAbort(
2495
+ this.send(jsonrpcNotification, options == null ? void 0 : options.signal),
2496
+ options == null ? void 0 : options.signal
2497
+ );
2378
2498
  }
2379
2499
  /**
2380
2500
  * Returns a set of AI SDK tools from the MCP server.