@ai-sdk/mcp 2.0.18 → 2.0.20

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,22 @@
1
1
  # @ai-sdk/mcp
2
2
 
3
+ ## 2.0.20
4
+
5
+ ### Patch Changes
6
+
7
+ - 97f0565: Honor MCP request deadlines and support bounding or aborting client initialization.
8
+ - Updated dependencies [d8210b6]
9
+ - Updated dependencies [b192878]
10
+ - @ai-sdk/provider-utils@5.0.16
11
+
12
+ ## 2.0.19
13
+
14
+ ### Patch Changes
15
+
16
+ - Updated dependencies [1659cd5]
17
+ - Updated dependencies [6a5bdff]
18
+ - @ai-sdk/provider-utils@5.0.15
19
+
3
20
  ## 2.0.18
4
21
 
5
22
  ### Patch Changes
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
  */
@@ -599,6 +625,10 @@ type ElicitResult = z.infer<typeof ElicitResultSchema>;
599
625
  interface MCPClientConfig {
600
626
  /** Transport configuration for connecting to the MCP server */
601
627
  transport: MCPTransportConfig | MCPTransport;
628
+ /**
629
+ * Options that bound or cancel transport startup and the initialize request.
630
+ */
631
+ initializationOptions?: RequestOptions;
602
632
  /** Optional callback for uncaught errors */
603
633
  onUncaughtError?: (error: unknown) => void;
604
634
  /**
@@ -777,4 +807,4 @@ declare function fingerprintMCPAppResource(resource: MCPAppResource): Promise<st
777
807
  */
778
808
  declare function detectMCPAppResourceDrift(current: string, baseline: string): boolean;
779
809
 
780
- export { type CallToolResult, type CompleteRequestParams, type CompleteResult, type Configuration, type ElicitResult, ElicitResultSchema, type ElicitationRequest, ElicitationRequestSchema, type InitializeResult, type JSONRPCError, type JSONRPCMessage, type JSONRPCNotification, type JSONRPCRequest, type JSONRPCResponse, type ListToolsResult, type MCPAppResource, type MCPAppResourceCSP, type MCPAppResourceMeta, type MCPClient, type ClientCapabilities as MCPClientCapabilities, type MCPClientConfig, type MCPTransport, MCP_APP_MIME_TYPE, type McpProviderMetadata, type OAuthAuthorizationServerInformation, type OAuthClientInformation, type OAuthClientMetadata, type OAuthClientProvider, type OAuthTokens, UnauthorizedError, auth, createMCPClient, detectMCPAppResourceDrift, type MCPClient as experimental_MCPClient, type ClientCapabilities as experimental_MCPClientCapabilities, type MCPClientConfig as experimental_MCPClientConfig, createMCPClient as experimental_createMCPClient, fingerprintMCPAppResource, mcpAppClientCapabilities, readMCPAppResource, splitMCPAppTools, validateJSONRPCMessage };
810
+ export { type CallToolResult, type CompleteRequestParams, type CompleteResult, type Configuration, type ElicitResult, ElicitResultSchema, type ElicitationRequest, ElicitationRequestSchema, type InitializeResult, type JSONRPCError, type JSONRPCMessage, type JSONRPCNotification, type JSONRPCRequest, type JSONRPCResponse, type ListToolsResult, type MCPAppResource, type MCPAppResourceCSP, type MCPAppResourceMeta, type MCPClient, type ClientCapabilities as MCPClientCapabilities, type MCPClientConfig, type MCPTransport, type MCPTransportCloseOptions, type MCPTransportSendOptions, MCP_APP_MIME_TYPE, type McpProviderMetadata, type OAuthAuthorizationServerInformation, type OAuthClientInformation, type OAuthClientMetadata, type OAuthClientProvider, type OAuthTokens, UnauthorizedError, auth, createMCPClient, detectMCPAppResourceDrift, type MCPClient as experimental_MCPClient, type ClientCapabilities as experimental_MCPClientCapabilities, type MCPClientConfig as experimental_MCPClientConfig, createMCPClient as experimental_createMCPClient, fingerprintMCPAppResource, mcpAppClientCapabilities, readMCPAppResource, splitMCPAppTools, validateJSONRPCMessage };
package/dist/index.js CHANGED
@@ -1464,15 +1464,19 @@ var SseMCPTransport = class {
1464
1464
  (_b3 = this.abortController) == null ? void 0 : _b3.abort();
1465
1465
  (_c = this.onclose) == null ? void 0 : _c.call(this);
1466
1466
  }
1467
- async send(message) {
1467
+ async send(message, options) {
1468
+ var _a3, _b3;
1469
+ (_a3 = options == null ? void 0 : options.signal) == null ? void 0 : _a3.throwIfAborted();
1468
1470
  if (!this.endpoint || !this.connected) {
1469
1471
  throw new MCPClientError({
1470
1472
  message: "MCP SSE Transport Error: Not connected"
1471
1473
  });
1472
1474
  }
1473
1475
  const endpoint = this.endpoint;
1476
+ const transportSignal = (_b3 = this.abortController) == null ? void 0 : _b3.signal;
1477
+ const requestSignal = (options == null ? void 0 : options.signal) == null ? transportSignal : transportSignal == null ? options.signal : AbortSignal.any([transportSignal, options.signal]);
1474
1478
  const attempt = async (triedAuth = false) => {
1475
- var _a3, _b3, _c, _d, _e;
1479
+ var _a4, _b4, _c, _d, _e;
1476
1480
  try {
1477
1481
  const headers = await this.commonHeaders({
1478
1482
  "Content-Type": "application/json"
@@ -1481,7 +1485,7 @@ var SseMCPTransport = class {
1481
1485
  method: "POST",
1482
1486
  headers,
1483
1487
  body: JSON.stringify(message),
1484
- signal: (_a3 = this.abortController) == null ? void 0 : _a3.signal,
1488
+ signal: requestSignal,
1485
1489
  redirect: this.redirectMode
1486
1490
  };
1487
1491
  const response = await this.fetchFn(endpoint.href, init);
@@ -1495,11 +1499,11 @@ var SseMCPTransport = class {
1495
1499
  });
1496
1500
  if (result !== "AUTHORIZED") {
1497
1501
  const error = new UnauthorizedError();
1498
- (_b3 = this.onerror) == null ? void 0 : _b3.call(this, error);
1502
+ (_a4 = this.onerror) == null ? void 0 : _a4.call(this, error);
1499
1503
  return;
1500
1504
  }
1501
1505
  } catch (error) {
1502
- (_c = this.onerror) == null ? void 0 : _c.call(this, error);
1506
+ (_b4 = this.onerror) == null ? void 0 : _b4.call(this, error);
1503
1507
  return;
1504
1508
  }
1505
1509
  return attempt(true);
@@ -1509,10 +1513,13 @@ var SseMCPTransport = class {
1509
1513
  const error = new MCPClientError({
1510
1514
  message: `MCP SSE Transport Error: POSTing to endpoint (HTTP ${response.status}): ${text}`
1511
1515
  });
1512
- (_d = this.onerror) == null ? void 0 : _d.call(this, error);
1516
+ (_c = this.onerror) == null ? void 0 : _c.call(this, error);
1513
1517
  return;
1514
1518
  }
1515
1519
  } catch (error) {
1520
+ if ((_d = options == null ? void 0 : options.signal) == null ? void 0 : _d.aborted) {
1521
+ throw error;
1522
+ }
1516
1523
  (_e = this.onerror) == null ? void 0 : _e.call(this, error);
1517
1524
  return;
1518
1525
  }
@@ -1637,27 +1644,33 @@ var HttpMCPTransport = class {
1637
1644
  this.abortController = new AbortController();
1638
1645
  this.startInboundSse();
1639
1646
  }
1640
- async close() {
1641
- var _a3, _b3, _c;
1647
+ async close(options) {
1648
+ var _a3, _b3, _c, _d, _e;
1642
1649
  (_a3 = this.inboundSseConnection) == null ? void 0 : _a3.close();
1650
+ (_b3 = this.abortController) == null ? void 0 : _b3.abort();
1643
1651
  try {
1644
- if (this.sessionId && this.terminateSessionOnClose && this.abortController && !this.abortController.signal.aborted) {
1652
+ if (this.sessionId && this.terminateSessionOnClose && this.abortController) {
1653
+ (_c = options == null ? void 0 : options.signal) == null ? void 0 : _c.throwIfAborted();
1645
1654
  const headers = await this.commonHeaders({ base: {} });
1655
+ (_d = options == null ? void 0 : options.signal) == null ? void 0 : _d.throwIfAborted();
1646
1656
  await this.fetchFn(this.url.href, {
1647
1657
  method: "DELETE",
1648
1658
  headers,
1649
- signal: this.abortController.signal,
1659
+ signal: options == null ? void 0 : options.signal,
1650
1660
  redirect: this.redirectMode
1651
1661
  }).catch(() => void 0);
1652
1662
  }
1653
1663
  } catch (e) {
1654
1664
  }
1655
- (_b3 = this.abortController) == null ? void 0 : _b3.abort();
1656
- (_c = this.onclose) == null ? void 0 : _c.call(this);
1665
+ (_e = this.onclose) == null ? void 0 : _e.call(this);
1657
1666
  }
1658
- async send(message) {
1667
+ async send(message, options) {
1668
+ var _a3, _b3;
1669
+ (_a3 = options == null ? void 0 : options.signal) == null ? void 0 : _a3.throwIfAborted();
1670
+ const transportSignal = (_b3 = this.abortController) == null ? void 0 : _b3.signal;
1671
+ const requestSignal = (options == null ? void 0 : options.signal) == null ? transportSignal : transportSignal == null ? options.signal : AbortSignal.any([transportSignal, options.signal]);
1659
1672
  const attempt = async (triedAuth = false) => {
1660
- var _a3, _b3, _c, _d, _e, _f, _g;
1673
+ var _a4, _b4, _c, _d, _e, _f, _g;
1661
1674
  try {
1662
1675
  const isInitializeRequest = "method" in message && message.method === "initialize";
1663
1676
  const sessionIdForRequest = isInitializeRequest ? void 0 : this.sessionId;
@@ -1672,7 +1685,7 @@ var HttpMCPTransport = class {
1672
1685
  method: "POST",
1673
1686
  headers,
1674
1687
  body: JSON.stringify(message),
1675
- signal: (_a3 = this.abortController) == null ? void 0 : _a3.signal,
1688
+ signal: requestSignal,
1676
1689
  redirect: this.redirectMode
1677
1690
  };
1678
1691
  const response = await this.fetchFn(this.url.href, init);
@@ -1686,7 +1699,7 @@ var HttpMCPTransport = class {
1686
1699
  throw error2;
1687
1700
  }
1688
1701
  } catch (error2) {
1689
- (_b3 = this.onerror) == null ? void 0 : _b3.call(this, error2);
1702
+ (_a4 = this.onerror) == null ? void 0 : _a4.call(this, error2);
1690
1703
  throw error2;
1691
1704
  }
1692
1705
  return attempt(true);
@@ -1714,7 +1727,7 @@ var HttpMCPTransport = class {
1714
1727
  url: this.url.href,
1715
1728
  responseBody: text != null ? text : void 0
1716
1729
  });
1717
- (_c = this.onerror) == null ? void 0 : _c.call(this, error2);
1730
+ (_b4 = this.onerror) == null ? void 0 : _b4.call(this, error2);
1718
1731
  throw error2;
1719
1732
  }
1720
1733
  const isNotification = !("id" in message);
@@ -1726,7 +1739,7 @@ var HttpMCPTransport = class {
1726
1739
  const data = await response.json();
1727
1740
  const messages = Array.isArray(data) ? data.map((message2) => validateJSONRPCMessage(message2)) : [validateJSONRPCMessage(data)];
1728
1741
  for (const jsonRpcMessage of messages) {
1729
- (_d = this.onmessage) == null ? void 0 : _d.call(this, jsonRpcMessage);
1742
+ (_c = this.onmessage) == null ? void 0 : _c.call(this, jsonRpcMessage);
1730
1743
  }
1731
1744
  return;
1732
1745
  }
@@ -1737,13 +1750,13 @@ var HttpMCPTransport = class {
1737
1750
  statusCode: response.status,
1738
1751
  url: this.url.href
1739
1752
  });
1740
- (_e = this.onerror) == null ? void 0 : _e.call(this, error2);
1753
+ (_d = this.onerror) == null ? void 0 : _d.call(this, error2);
1741
1754
  throw error2;
1742
1755
  }
1743
1756
  const stream = response.body.pipeThrough(new TextDecoderStream()).pipeThrough(new EventSourceParserStream2());
1744
1757
  const reader = stream.getReader();
1745
1758
  const processEvents = async () => {
1746
- var _a4, _b4, _c2;
1759
+ var _a5, _b5, _c2, _d2;
1747
1760
  try {
1748
1761
  while (true) {
1749
1762
  const { done, value } = await reader.read();
@@ -1752,29 +1765,29 @@ var HttpMCPTransport = class {
1752
1765
  if (isMessageEvent2(event)) {
1753
1766
  try {
1754
1767
  const jsonRpcMessage = await parseJSONRPCMessage(data);
1755
- (_a4 = this.onmessage) == null ? void 0 : _a4.call(this, jsonRpcMessage);
1768
+ (_a5 = this.onmessage) == null ? void 0 : _a5.call(this, jsonRpcMessage);
1756
1769
  } catch (error2) {
1757
1770
  const e = new MCPClientError({
1758
1771
  message: "MCP HTTP Transport Error: Failed to parse message",
1759
1772
  cause: error2
1760
1773
  });
1761
- (_b4 = this.onerror) == null ? void 0 : _b4.call(this, e);
1774
+ (_b5 = this.onerror) == null ? void 0 : _b5.call(this, e);
1762
1775
  }
1763
1776
  }
1764
1777
  }
1765
1778
  } catch (error2) {
1766
- if (error2 instanceof Error && error2.name === "AbortError") {
1779
+ if (((_c2 = options == null ? void 0 : options.signal) == null ? void 0 : _c2.aborted) || error2 instanceof Error && error2.name === "AbortError") {
1767
1780
  return;
1768
1781
  }
1769
- (_c2 = this.onerror) == null ? void 0 : _c2.call(this, error2);
1782
+ (_d2 = this.onerror) == null ? void 0 : _d2.call(this, error2);
1770
1783
  }
1771
1784
  };
1772
1785
  void processEvents().catch((error2) => {
1773
- var _a4;
1774
- if (error2 instanceof Error && error2.name === "AbortError") {
1786
+ var _a5, _b5;
1787
+ if (((_a5 = options == null ? void 0 : options.signal) == null ? void 0 : _a5.aborted) || error2 instanceof Error && error2.name === "AbortError") {
1775
1788
  return;
1776
1789
  }
1777
- (_a4 = this.onerror) == null ? void 0 : _a4.call(this, error2);
1790
+ (_b5 = this.onerror) == null ? void 0 : _b5.call(this, error2);
1778
1791
  });
1779
1792
  return;
1780
1793
  }
@@ -1783,9 +1796,12 @@ var HttpMCPTransport = class {
1783
1796
  statusCode: response.status,
1784
1797
  url: this.url.href
1785
1798
  });
1786
- (_f = this.onerror) == null ? void 0 : _f.call(this, error);
1799
+ (_e = this.onerror) == null ? void 0 : _e.call(this, error);
1787
1800
  throw error;
1788
1801
  } catch (error) {
1802
+ if ((_f = options == null ? void 0 : options.signal) == null ? void 0 : _f.aborted) {
1803
+ throw error;
1804
+ }
1789
1805
  (_g = this.onerror) == null ? void 0 : _g.call(this, error);
1790
1806
  throw error;
1791
1807
  }
@@ -2140,6 +2156,44 @@ function prepareMaxRetries(maxRetries) {
2140
2156
  }
2141
2157
  return maxRetries;
2142
2158
  }
2159
+ function getEffectiveTimeout({
2160
+ timeout,
2161
+ maxTotalTimeout
2162
+ }) {
2163
+ if (timeout == null) {
2164
+ return maxTotalTimeout;
2165
+ }
2166
+ if (maxTotalTimeout == null) {
2167
+ return timeout;
2168
+ }
2169
+ return Math.min(timeout, maxTotalTimeout);
2170
+ }
2171
+ function waitForAbort(promise, signal) {
2172
+ if (signal == null) {
2173
+ return promise;
2174
+ }
2175
+ return new Promise((resolve, reject) => {
2176
+ const cleanup = () => {
2177
+ signal.removeEventListener("abort", onAbort);
2178
+ };
2179
+ const onAbort = () => {
2180
+ cleanup();
2181
+ reject(signal.reason);
2182
+ };
2183
+ if (signal.aborted) {
2184
+ onAbort();
2185
+ return;
2186
+ }
2187
+ signal.addEventListener("abort", onAbort, { once: true });
2188
+ promise.then((value) => {
2189
+ cleanup();
2190
+ resolve(value);
2191
+ }).catch((error) => {
2192
+ cleanup();
2193
+ reject(error);
2194
+ });
2195
+ });
2196
+ }
2143
2197
  function mcpToModelOutput({
2144
2198
  output
2145
2199
  }) {
@@ -2178,7 +2232,8 @@ var DefaultMCPClient = class {
2178
2232
  onUncaughtError,
2179
2233
  maxRetries,
2180
2234
  capabilities,
2181
- initialInitializeResult
2235
+ initialInitializeResult,
2236
+ initializationOptions
2182
2237
  }) {
2183
2238
  this.requestMessageId = 0;
2184
2239
  this.responseHandlers = /* @__PURE__ */ new Map();
@@ -2194,6 +2249,7 @@ var DefaultMCPClient = class {
2194
2249
  this.maxRetries = prepareMaxRetries(maxRetries);
2195
2250
  this.clientCapabilities = capabilities != null ? capabilities : {};
2196
2251
  this.initialInitializeResult = initialInitializeResult;
2252
+ this.initializationOptions = initializationOptions;
2197
2253
  if (isCustomMcpTransport(transportConfig)) {
2198
2254
  this.transport = transportConfig;
2199
2255
  } else {
@@ -2231,9 +2287,25 @@ var DefaultMCPClient = class {
2231
2287
  return this._serverInstructions;
2232
2288
  }
2233
2289
  async init() {
2290
+ var _a3;
2291
+ const externalSignal = (_a3 = this.initializationOptions) == null ? void 0 : _a3.signal;
2292
+ const timeout = this.initializationOptions ? getEffectiveTimeout(this.initializationOptions) : void 0;
2293
+ const timeoutController = timeout == null ? void 0 : new AbortController();
2294
+ const signal = externalSignal == null ? timeoutController == null ? void 0 : timeoutController.signal : timeoutController == null ? externalSignal : AbortSignal.any([externalSignal, timeoutController.signal]);
2295
+ let timeoutId;
2296
+ let timeoutError;
2297
+ if (timeout != null) {
2298
+ timeoutId = setTimeout(() => {
2299
+ timeoutError = new MCPClientError({
2300
+ message: `MCP client initialization timed out after ${timeout}ms`
2301
+ });
2302
+ timeoutController == null ? void 0 : timeoutController.abort(timeoutError);
2303
+ }, timeout);
2304
+ }
2234
2305
  try {
2235
- await this.transport.start();
2236
2306
  this.isClosed = false;
2307
+ signal == null ? void 0 : signal.throwIfAborted();
2308
+ await waitForAbort(this.transport.start(), signal);
2237
2309
  if (this.initialInitializeResult) {
2238
2310
  const result2 = InitializeResultSchema.parse(
2239
2311
  this.initialInitializeResult
@@ -2250,7 +2322,8 @@ var DefaultMCPClient = class {
2250
2322
  clientInfo: this.clientInfo
2251
2323
  }
2252
2324
  },
2253
- resultSchema: InitializeResultSchema
2325
+ resultSchema: InitializeResultSchema,
2326
+ options: { signal }
2254
2327
  });
2255
2328
  if (result === void 0) {
2256
2329
  throw new MCPClientError({
@@ -2258,13 +2331,33 @@ var DefaultMCPClient = class {
2258
2331
  });
2259
2332
  }
2260
2333
  this.applyInitializeResult(result);
2261
- await this.notification({
2262
- method: "notifications/initialized"
2263
- });
2334
+ await this.notification(
2335
+ {
2336
+ method: "notifications/initialized"
2337
+ },
2338
+ { signal }
2339
+ );
2264
2340
  return this;
2265
2341
  } catch (error) {
2266
- await this.close();
2342
+ try {
2343
+ await waitForAbort(this.transport.close({ signal }), signal);
2344
+ } catch (e) {
2345
+ }
2346
+ this.onClose();
2347
+ if (timeoutError != null) {
2348
+ throw timeoutError;
2349
+ }
2350
+ if (externalSignal == null ? void 0 : externalSignal.aborted) {
2351
+ throw new MCPClientError({
2352
+ message: "MCP client initialization was aborted",
2353
+ cause: externalSignal.reason
2354
+ });
2355
+ }
2267
2356
  throw error;
2357
+ } finally {
2358
+ if (timeoutId != null) {
2359
+ clearTimeout(timeoutId);
2360
+ }
2268
2361
  }
2269
2362
  }
2270
2363
  applyInitializeResult(result) {
@@ -2289,6 +2382,12 @@ var DefaultMCPClient = class {
2289
2382
  await ((_a3 = this.transport) == null ? void 0 : _a3.close());
2290
2383
  this.onClose();
2291
2384
  }
2385
+ send(message, signal) {
2386
+ return this.transport.send(
2387
+ message,
2388
+ signal == null ? void 0 : { signal }
2389
+ );
2390
+ }
2292
2391
  assertCapability(method) {
2293
2392
  switch (method) {
2294
2393
  case "initialize":
@@ -2347,6 +2446,10 @@ var DefaultMCPClient = class {
2347
2446
  this.assertCapability(request.method);
2348
2447
  const signal = options == null ? void 0 : options.signal;
2349
2448
  signal == null ? void 0 : signal.throwIfAborted();
2449
+ const timeout = options == null ? void 0 : getEffectiveTimeout(options);
2450
+ const timeoutController = timeout == null ? void 0 : new AbortController();
2451
+ const transportSignal = signal == null ? timeoutController == null ? void 0 : timeoutController.signal : timeoutController == null ? signal : AbortSignal.any([signal, timeoutController.signal]);
2452
+ let timeoutId;
2350
2453
  const messageId = this.requestMessageId++;
2351
2454
  const jsonrpcRequest = {
2352
2455
  ...request,
@@ -2364,6 +2467,9 @@ var DefaultMCPClient = class {
2364
2467
  const cleanup = () => {
2365
2468
  this.responseHandlers.delete(messageId);
2366
2469
  signal == null ? void 0 : signal.removeEventListener("abort", onAbort);
2470
+ if (timeoutId != null) {
2471
+ clearTimeout(timeoutId);
2472
+ }
2367
2473
  };
2368
2474
  const rejectAndCleanup = (error) => {
2369
2475
  cleanup();
@@ -2373,6 +2479,13 @@ var DefaultMCPClient = class {
2373
2479
  cleanup();
2374
2480
  rejectWithAbortError();
2375
2481
  };
2482
+ const onTimeout = () => {
2483
+ const error = new MCPClientError({
2484
+ message: `Request timed out after ${timeout}ms`
2485
+ });
2486
+ timeoutController == null ? void 0 : timeoutController.abort(error);
2487
+ rejectAndCleanup(error);
2488
+ };
2376
2489
  this.responseHandlers.set(messageId, (response) => {
2377
2490
  if (signal == null ? void 0 : signal.aborted) {
2378
2491
  cleanup();
@@ -2394,7 +2507,11 @@ var DefaultMCPClient = class {
2394
2507
  }
2395
2508
  });
2396
2509
  signal == null ? void 0 : signal.addEventListener("abort", onAbort, { once: true });
2397
- this.transport.send(jsonrpcRequest).catch((error) => {
2510
+ if (timeout != null) {
2511
+ timeoutId = setTimeout(onTimeout, timeout);
2512
+ }
2513
+ const sendPromise = transportSignal == null ? this.transport.send(jsonrpcRequest) : this.send(jsonrpcRequest, transportSignal);
2514
+ sendPromise.catch((error) => {
2398
2515
  rejectAndCleanup(error);
2399
2516
  });
2400
2517
  });
@@ -2527,12 +2644,15 @@ var DefaultMCPClient = class {
2527
2644
  options
2528
2645
  });
2529
2646
  }
2530
- async notification(notification) {
2647
+ async notification(notification, options) {
2531
2648
  const jsonrpcNotification = {
2532
2649
  ...notification,
2533
2650
  jsonrpc: "2.0"
2534
2651
  };
2535
- await this.transport.send(jsonrpcNotification);
2652
+ await waitForAbort(
2653
+ this.send(jsonrpcNotification, options == null ? void 0 : options.signal),
2654
+ options == null ? void 0 : options.signal
2655
+ );
2536
2656
  }
2537
2657
  /**
2538
2658
  * Returns a set of AI SDK tools from the MCP server.