@livx.cc/agentx 0.99.47 → 0.99.48

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.
@@ -1,4 +1,4 @@
1
- import { A as AgentTool } from './tools-BqL8Lk4J.js';
1
+ import { A as AgentTool } from './tools-MNdqlJIa.js';
2
2
 
3
3
  /**
4
4
  * MCP bridge — adapt a Model Context Protocol tool list into the agent's AgentTool[],
@@ -14,8 +14,17 @@ interface McpToolSpec {
14
14
  /** JSON Schema for the tool's arguments (MCP's `inputSchema`). */
15
15
  inputSchema?: object;
16
16
  }
17
+ /** Liveness + cancellation for one call: `onProgress` ⇒ the client requests MCP progress notifications. */
18
+ interface McpCallOptions {
19
+ signal?: AbortSignal;
20
+ onProgress?: (p: {
21
+ progress?: number;
22
+ total?: number;
23
+ message?: string;
24
+ }) => void;
25
+ }
17
26
  /** Perform an MCP tool call; return its textual result. Throw to surface an error to the model. */
18
- type McpCall = (name: string, args: any) => Promise<unknown>;
27
+ type McpCall = (name: string, args: any, opts?: McpCallOptions) => Promise<unknown>;
19
28
  interface McpImage {
20
29
  mimeType: string;
21
30
  data: string;
@@ -54,7 +63,7 @@ interface MountedMcpLike {
54
63
  name: string;
55
64
  specs: McpToolSpec[];
56
65
  client: {
57
- callTool(name: string, args: unknown): Promise<unknown>;
66
+ callTool(name: string, args: unknown, opts?: McpCallOptions): Promise<unknown>;
58
67
  };
59
68
  }
60
69
  /** A flattened catalog entry's origin: which server owns it + the un-prefixed raw tool name. */
@@ -73,7 +82,7 @@ declare function buildMcpCatalog(servers: {
73
82
  routes: Map<string, McpRoute>;
74
83
  };
75
84
  /** Resolve a routed MCP call to its result. Throw to surface an error to the model. */
76
- type McpRouteResolver = (server: string, rawName: string, args: any) => Promise<unknown>;
85
+ type McpRouteResolver = (server: string, rawName: string, args: any, opts?: McpCallOptions) => Promise<unknown>;
77
86
  /**
78
87
  * Ergonomic deferred-mount over already-mounted MCP servers: flattens their specs into one
79
88
  * `mcp__<server>__<tool>` namespace and wires a single `ToolSearch`/`McpCall` pair that routes
@@ -1,11 +1,27 @@
1
- import { e as McpToolSearchOptions, f as McpToolSpec } from './mcp-kgG6rtsd.js';
2
- import { A as AgentTool } from './tools-BqL8Lk4J.js';
1
+ import { e as McpToolSearchOptions, f as McpToolSpec } from './mcp-DjYZzGGW.js';
2
+ import { A as AgentTool } from './tools-MNdqlJIa.js';
3
3
  import '@livx.cc/wcli/core';
4
4
 
5
+ /** Hard cap for `tools/call`. NOT the 30s protocol timeout: a tool call is real work (an image render, a crawl)
6
+ * that legitimately runs for minutes — the harness hands it to a job past its soft timeout and judges it by
7
+ * progress/idle liveness (src/tools.jobs.ts). This only bounds a call nothing else ever stops. */
8
+ declare const DEFAULT_CALL_TIMEOUT_MS: number;
9
+ /** An MCP `notifications/progress` payload. */
10
+ interface McpProgress {
11
+ progress?: number;
12
+ total?: number;
13
+ message?: string;
14
+ }
15
+ /** Per-request options: cancellation, progress (sends a `_meta.progressToken`), and a deadline override. */
16
+ interface McpRequestOptions {
17
+ signal?: AbortSignal;
18
+ onProgress?: (p: McpProgress) => void;
19
+ timeoutMs?: number;
20
+ }
5
21
  /** A JSON-RPC 2.0 transport: request (awaits a result), notify (fire-and-forget), close. */
6
22
  interface McpTransport {
7
23
  start(): Promise<void>;
8
- request(method: string, params?: unknown): Promise<any>;
24
+ request(method: string, params?: unknown, opts?: McpRequestOptions): Promise<any>;
9
25
  notify(method: string, params?: unknown): Promise<void>;
10
26
  close(): Promise<void>;
11
27
  }
@@ -14,7 +30,10 @@ interface StdioServerSpec {
14
30
  args?: string[];
15
31
  env?: Record<string, string>;
16
32
  cwd?: string;
33
+ /** Protocol request deadline (initialize, tools/list, …). Default 30s. */
17
34
  timeoutMs?: number;
35
+ /** `tools/call` hard cap. Default max(30 min, timeoutMs). */
36
+ callTimeoutMs?: number;
18
37
  }
19
38
  declare class StdioTransport implements McpTransport {
20
39
  private spec;
@@ -28,7 +47,7 @@ declare class StdioTransport implements McpTransport {
28
47
  private dispatch;
29
48
  private failAll;
30
49
  private write;
31
- request(method: string, params?: unknown): Promise<any>;
50
+ request(method: string, params?: unknown, opts?: McpRequestOptions): Promise<any>;
32
51
  notify(method: string, params?: unknown): Promise<void>;
33
52
  close(): Promise<void>;
34
53
  }
@@ -38,7 +57,10 @@ interface HttpServerSpec {
38
57
  /** Sugar over `headers` → `Authorization: Bearer <token>`. The headless-friendly path (no OAuth loopback);
39
58
  * inject a static token (from env / VFS secret) per our CLAUDE.md rule preferring API keys for cron/edge. */
40
59
  bearerToken?: string;
60
+ /** Protocol request deadline (initialize, tools/list, …). Default 30s. */
41
61
  timeoutMs?: number;
62
+ /** `tools/call` hard cap. Default max(30 min, timeoutMs). */
63
+ callTimeoutMs?: number;
42
64
  }
43
65
  /** Thrown when an HTTP MCP server rejects auth (401/403). Carries `needsAuth` so callers can surface a hint
44
66
  * ("set bearerToken / headers") instead of a generic mount failure — without attempting an interactive flow. */
@@ -55,7 +77,7 @@ declare class HttpTransport implements McpTransport {
55
77
  private fetchImpl;
56
78
  constructor(spec: HttpServerSpec, fetchImpl?: typeof fetch);
57
79
  start(): Promise<void>;
58
- request(method: string, params?: unknown): Promise<any>;
80
+ request(method: string, params?: unknown, opts?: McpRequestOptions): Promise<any>;
59
81
  notify(method: string, params?: unknown): Promise<void>;
60
82
  private post;
61
83
  close(): Promise<void>;
@@ -76,7 +98,8 @@ declare class McpClient {
76
98
  capabilities?: any;
77
99
  }>;
78
100
  listTools(): Promise<McpToolSpec[]>;
79
- callTool(name: string, args: unknown): Promise<unknown>;
101
+ /** `tools/call`. Pass `onProgress` to request progress notifications (liveness) and `signal` to cancel. */
102
+ callTool(name: string, args: unknown, opts?: McpRequestOptions): Promise<unknown>;
80
103
  listResources(): Promise<Array<{
81
104
  uri: string;
82
105
  name?: string;
@@ -98,7 +121,10 @@ interface McpServerConfig {
98
121
  /** Auth strategy for http servers. `'oauth'` → the CLI resolves a token via the attended OAuth flow
99
122
  * (cli/mcpOAuth.ts) and injects it as `bearerToken` at mount; the core never runs the flow. Default none. */
100
123
  auth?: 'oauth' | 'none';
124
+ /** Protocol request deadline (initialize, tools/list, …). Default 30s. */
101
125
  timeoutMs?: number;
126
+ /** `tools/call` hard cap (the call is handed to a job long before; this bounds what nothing else stops). Default 30 min. */
127
+ callTimeoutMs?: number;
102
128
  disabled?: boolean;
103
129
  }
104
130
  interface MountedMcp {
@@ -225,4 +251,4 @@ declare function warmMcpCatalog(servers?: Record<string, McpServerConfig>, opts?
225
251
  toolCount: number;
226
252
  }>;
227
253
 
228
- export { type HttpServerSpec, HttpTransport, McpAuthError, type McpCatalogOptions, type McpCatalogStore, McpClient, McpPool, type McpServerConfig, type McpTransport, MemMcpCatalog, type MountedMcp, type StdioServerSpec, StdioTransport, mcpConfigKey, mountMcpCatalog, mountMcpDeferred, mountMcpServer, mountMcpServers, warmMcpCatalog };
254
+ export { DEFAULT_CALL_TIMEOUT_MS, type HttpServerSpec, HttpTransport, McpAuthError, type McpCatalogOptions, type McpCatalogStore, McpClient, McpPool, type McpProgress, type McpRequestOptions, type McpServerConfig, type McpTransport, MemMcpCatalog, type MountedMcp, type StdioServerSpec, StdioTransport, mcpConfigKey, mountMcpCatalog, mountMcpDeferred, mountMcpServer, mountMcpServers, warmMcpCatalog };
@@ -106,17 +106,42 @@ async function withDeadline(p, ms) {
106
106
  }
107
107
  }
108
108
  var mcpTimedOut = (name, ms = MCP_CALL_TIMEOUT_MS) => `[${name}] no response after ${ms / 1e3}s \u2014 the MCP server never answered. The call's outcome is UNKNOWN: do not assume it ran or that it failed. Verify the state (or pick a bounded/narrower call) before retrying.`;
109
+ async function runMcpCall(name, call, ctx, timeoutMs) {
110
+ const jobs = ctx?.toolJobs;
111
+ const shape = (raw) => {
112
+ const r2 = toResult(raw);
113
+ return r2.images?.length ? r2 : r2.text;
114
+ };
115
+ if (!jobs) {
116
+ const raw = await withDeadline(call({}), timeoutMs);
117
+ return raw === TIMED_OUT ? mcpTimedOut(name, timeoutMs) : shape(raw);
118
+ }
119
+ const r = await jobs.runForeground(async ({ signal, touch, onChunk }) => {
120
+ const raw = await call({
121
+ signal,
122
+ onProgress: (p) => {
123
+ touch();
124
+ if (p?.message) onChunk(`[progress${p.progress != null ? ` ${p.progress}${p.total != null ? `/${p.total}` : ""}` : ""}] ${p.message}
125
+ `);
126
+ }
127
+ });
128
+ const res = toResult(raw);
129
+ onChunk(res.text + (res.images?.length ? `
130
+ [${res.images.length} image(s) in the result]` : ""));
131
+ return res;
132
+ }, { kind: "mcp", label: name, idleAfterActivity: true });
133
+ if (r.done) return r.value.images?.length ? r.value : r.value.text;
134
+ const soft = jobs.options.foregroundMs.mcp ?? 0;
135
+ return `[still running] MCP call ${name} is still working after ${soft >= 1e3 ? `${Math.round(soft / 1e3)}s` : `${soft}ms`}, so it was handed to background job ${r.id} \u2014 NOT cancelled, the server keeps going. Its result will be delivered to you when it finishes, so continue with other work; to block on it use JobWait({id:"${r.id}"}) instead of sleeping. JobStatus/JobOutput show its progress; JobKill({id:"${r.id}"}) cancels it. Do NOT re-issue the same call \u2014 that would run it twice.`;
136
+ }
109
137
  function mcpToolToAgentTool(spec, callTool, prefix = "mcp__", timeoutMs = MCP_CALL_TIMEOUT_MS) {
110
138
  return {
111
139
  name: `${prefix}${spec.name}`,
112
140
  description: spec.description ?? `MCP tool ${spec.name}`,
113
141
  parameters: spec.inputSchema ?? { type: "object", properties: {} },
114
142
  maxDurationMs: timeoutMs,
115
- async run(args, _ctx) {
116
- const raw = await withDeadline(callTool(spec.name, args ?? {}), timeoutMs);
117
- if (raw === TIMED_OUT) return mcpTimedOut(spec.name, timeoutMs);
118
- const r = toResult(raw);
119
- return r.images?.length ? r : r.text;
143
+ run(args, ctx) {
144
+ return runMcpCall(spec.name, (o) => callTool(spec.name, args ?? {}, o), ctx, timeoutMs);
120
145
  }
121
146
  };
122
147
  }
@@ -157,13 +182,10 @@ function makeMcpToolSearch(specs, callTool, options = {}) {
157
182
  }
158
183
  },
159
184
  maxDurationMs: callTimeoutMs,
160
- async run({ name, args }) {
185
+ async run({ name, args }, ctx) {
161
186
  const n = String(name ?? "");
162
187
  if (!byName.has(n)) return `Error: unknown MCP tool '${n}'. Use ToolSearch to find valid names.`;
163
- const raw = await withDeadline(callTool(n, args ?? {}), callTimeoutMs);
164
- if (raw === TIMED_OUT) return mcpTimedOut(n, callTimeoutMs);
165
- const r = toResult(raw);
166
- return r.images?.length ? r : r.text;
188
+ return runMcpCall(n, (o) => callTool(n, args ?? {}, o), ctx, callTimeoutMs);
167
189
  }
168
190
  };
169
191
  return [searchTool, callMcpTool];
@@ -183,17 +205,17 @@ function buildMcpCatalog(servers) {
183
205
  return { specs, routes };
184
206
  }
185
207
  function searchOverCatalog(servers, specs, routes, resolve, options) {
186
- const tools = specs.length ? makeMcpToolSearch(specs, (name, args) => {
208
+ const tools = specs.length ? makeMcpToolSearch(specs, (name, args, o) => {
187
209
  const r = routes.get(name);
188
210
  if (!r) throw new Error(`unknown MCP tool '${name}' \u2014 use ToolSearch to find valid names`);
189
- return resolve(r.server, r.rawName, args ?? {});
211
+ return resolve(r.server, r.rawName, args ?? {}, o);
190
212
  }, options) : [];
191
213
  return { tools, serverNames: servers, toolCount: specs.length };
192
214
  }
193
215
  function makeMcpToolSearchFromMounted(mounted, options) {
194
216
  const { specs, routes } = buildMcpCatalog(mounted);
195
217
  const byName = new Map(mounted.map((m) => [m.name, m]));
196
- return searchOverCatalog(mounted.map((m) => m.name), specs, routes, (server, rawName, args) => byName.get(server).client.callTool(rawName, args), options);
218
+ return searchOverCatalog(mounted.map((m) => m.name), specs, routes, (server, rawName, args, o) => byName.get(server).client.callTool(rawName, args, o), options);
197
219
  }
198
220
  function makeLazyMcpToolSearch(servers, resolve, options) {
199
221
  const { specs, routes } = buildMcpCatalog(servers);
@@ -204,6 +226,17 @@ function makeLazyMcpToolSearch(servers, resolve, options) {
204
226
  var log2 = forComponent("mcp");
205
227
  var PROTOCOL_VERSION = "2025-06-18";
206
228
  var DEFAULT_TIMEOUT_MS = 3e4;
229
+ var DEFAULT_CALL_TIMEOUT_MS = 30 * 6e4;
230
+ function deadlineFor(method, spec, opts) {
231
+ if (opts?.timeoutMs != null) return opts.timeoutMs;
232
+ if (method === "tools/call") return spec.callTimeoutMs ?? Math.max(DEFAULT_CALL_TIMEOUT_MS, spec.timeoutMs ?? 0);
233
+ return spec.timeoutMs ?? DEFAULT_TIMEOUT_MS;
234
+ }
235
+ function withProgressToken(params, token) {
236
+ const p = params && typeof params === "object" ? params : {};
237
+ return { ...p, _meta: { ...p._meta ?? {}, progressToken: token } };
238
+ }
239
+ var abortError = (signal) => signal.reason instanceof Error ? signal.reason : Object.assign(new Error("MCP request cancelled"), { name: "AbortError" });
207
240
  var StdioTransport = class {
208
241
  constructor(spec) {
209
242
  this.spec = spec;
@@ -239,16 +272,27 @@ var StdioTransport = class {
239
272
  }
240
273
  }
241
274
  dispatch(msg) {
275
+ if (msg?.method === "notifications/progress") {
276
+ const p2 = this.pending.get(msg.params?.progressToken);
277
+ try {
278
+ p2?.onProgress?.(msg.params ?? {});
279
+ } catch (e) {
280
+ log2.debug("onProgress handler threw", e);
281
+ }
282
+ return;
283
+ }
242
284
  if (msg?.id == null || !this.pending.has(msg.id)) return;
243
285
  const p = this.pending.get(msg.id);
244
286
  this.pending.delete(msg.id);
245
287
  clearTimeout(p.timer);
288
+ p.done?.();
246
289
  if (msg.error) p.reject(new Error(msg.error?.message ?? JSON.stringify(msg.error)));
247
290
  else p.resolve(msg.result);
248
291
  }
249
292
  failAll(e) {
250
293
  for (const p of this.pending.values()) {
251
294
  clearTimeout(p.timer);
295
+ p.done?.();
252
296
  p.reject(e);
253
297
  }
254
298
  this.pending.clear();
@@ -257,19 +301,31 @@ var StdioTransport = class {
257
301
  if (!this.proc?.stdin) throw new Error("MCP stdio transport not started");
258
302
  this.proc.stdin.write(JSON.stringify(msg) + "\n");
259
303
  }
260
- request(method, params) {
304
+ request(method, params, opts = {}) {
261
305
  const id = this.nextId++;
262
- const timeoutMs = this.spec.timeoutMs ?? DEFAULT_TIMEOUT_MS;
306
+ const timeoutMs = deadlineFor(method, this.spec, opts);
307
+ const { signal, onProgress } = opts;
263
308
  return new Promise((resolve, reject) => {
264
- const timer = setTimeout(() => {
309
+ if (signal?.aborted) return reject(abortError(signal));
310
+ const timer = timeoutMs > 0 ? setTimeout(() => {
265
311
  this.pending.delete(id);
312
+ done();
266
313
  reject(new Error(`MCP request "${method}" timed out after ${timeoutMs}ms`));
267
- }, timeoutMs);
268
- this.pending.set(id, { resolve, reject, timer });
314
+ }, timeoutMs) : void 0;
315
+ const onAbort = () => {
316
+ if (!this.pending.delete(id)) return;
317
+ clearTimeout(timer);
318
+ this.notify("notifications/cancelled", { requestId: id, reason: String(signal?.reason?.message ?? "cancelled") }).catch((e) => log2.debug("cancel notify failed", e));
319
+ reject(abortError(signal));
320
+ };
321
+ const done = () => signal?.removeEventListener("abort", onAbort);
322
+ signal?.addEventListener("abort", onAbort, { once: true });
323
+ this.pending.set(id, { resolve, reject, timer, onProgress, done });
269
324
  try {
270
- this.write({ jsonrpc: "2.0", id, method, params });
325
+ this.write({ jsonrpc: "2.0", id, method, params: onProgress ? withProgressToken(params, id) : params });
271
326
  } catch (e) {
272
327
  clearTimeout(timer);
328
+ done();
273
329
  this.pending.delete(id);
274
330
  reject(e);
275
331
  }
@@ -310,13 +366,24 @@ var HttpTransport = class {
310
366
  fetchImpl;
311
367
  async start() {
312
368
  }
313
- request(method, params) {
314
- return this.post({ jsonrpc: "2.0", id: this.nextId++, method, params }, false);
369
+ async request(method, params, opts = {}) {
370
+ const id = this.nextId++;
371
+ const deadline = AbortSignal.timeout(deadlineFor(method, this.spec, opts));
372
+ const signal = opts.signal ? AbortSignal.any([opts.signal, deadline]) : deadline;
373
+ try {
374
+ return await this.post({ jsonrpc: "2.0", id, method, params: opts.onProgress ? withProgressToken(params, id) : params }, false, signal, opts.onProgress);
375
+ } catch (e) {
376
+ if (opts.signal?.aborted) {
377
+ void this.notify("notifications/cancelled", { requestId: id, reason: String(opts.signal.reason?.message ?? "cancelled") }).catch((err) => log2.debug("cancel notify failed", err));
378
+ throw abortError(opts.signal);
379
+ }
380
+ throw e;
381
+ }
315
382
  }
316
383
  async notify(method, params) {
317
- await this.post({ jsonrpc: "2.0", method, params }, true);
384
+ await this.post({ jsonrpc: "2.0", method, params }, true, AbortSignal.timeout(this.spec.timeoutMs ?? DEFAULT_TIMEOUT_MS));
318
385
  }
319
- async post(msg, isNotify) {
386
+ async post(msg, isNotify, signal, onProgress) {
320
387
  const headers = {
321
388
  "content-type": "application/json",
322
389
  accept: "application/json, text/event-stream",
@@ -329,7 +396,7 @@ var HttpTransport = class {
329
396
  method: "POST",
330
397
  headers,
331
398
  body: JSON.stringify(msg),
332
- signal: AbortSignal.timeout(this.spec.timeoutMs ?? DEFAULT_TIMEOUT_MS)
399
+ signal
333
400
  });
334
401
  const sid = resp.headers.get("mcp-session-id");
335
402
  if (sid) this.sessionId = sid;
@@ -337,25 +404,63 @@ var HttpTransport = class {
337
404
  if (!resp.ok) throw new Error(`MCP HTTP ${resp.status} ${resp.statusText}`);
338
405
  if (isNotify) return;
339
406
  const ct = resp.headers.get("content-type") ?? "";
340
- const data = ct.includes("text/event-stream") ? parseSseResponse(await resp.text()) : await resp.json();
407
+ const data = ct.includes("text/event-stream") ? await readSseResponse(resp, msg.id, onProgress) : await resp.json();
341
408
  if (data?.error) throw new Error(data.error?.message ?? JSON.stringify(data.error));
342
409
  return data?.result;
343
410
  }
344
411
  async close() {
345
412
  }
346
413
  };
347
- function parseSseResponse(body) {
348
- for (const line of body.split("\n")) {
349
- const trimmed = line.trimStart();
350
- if (!trimmed.startsWith("data:")) continue;
351
- try {
352
- const obj = JSON.parse(trimmed.slice(5).trim());
353
- if (obj && (obj.result !== void 0 || obj.error !== void 0)) return obj;
354
- } catch (e) {
355
- log2.debug("skipping unparseable SSE data line", e);
414
+ function sseMessage(line) {
415
+ const trimmed = line.trimStart();
416
+ if (!trimmed.startsWith("data:")) return void 0;
417
+ try {
418
+ return JSON.parse(trimmed.slice(5).trim());
419
+ } catch (e) {
420
+ log2.debug("skipping unparseable SSE data line", e);
421
+ return void 0;
422
+ }
423
+ }
424
+ async function readSseResponse(resp, id, onProgress) {
425
+ const handle = (obj) => {
426
+ if (obj?.method === "notifications/progress") {
427
+ try {
428
+ onProgress?.(obj.params ?? {});
429
+ } catch (e) {
430
+ log2.debug("onProgress handler threw", e);
431
+ }
432
+ return void 0;
356
433
  }
434
+ if (obj && (obj.result !== void 0 || obj.error !== void 0) && (obj.id == null || id == null || obj.id === id)) return obj;
435
+ return void 0;
436
+ };
437
+ const reader = resp.body?.getReader?.();
438
+ if (!reader) {
439
+ for (const l of (await resp.text()).split("\n")) {
440
+ const r = handle(sseMessage(l));
441
+ if (r) return r;
442
+ }
443
+ return {};
444
+ }
445
+ const dec = new TextDecoder();
446
+ let buf = "";
447
+ try {
448
+ for (; ; ) {
449
+ const { value, done } = await reader.read();
450
+ buf += done ? dec.decode() : dec.decode(value, { stream: true });
451
+ let nl;
452
+ while ((nl = buf.indexOf("\n")) >= 0 || done && buf) {
453
+ const line = nl >= 0 ? buf.slice(0, nl) : buf;
454
+ buf = nl >= 0 ? buf.slice(nl + 1) : "";
455
+ const r = handle(sseMessage(line));
456
+ if (r) return r;
457
+ }
458
+ if (done) return {};
459
+ }
460
+ } finally {
461
+ reader.cancel().catch(() => {
462
+ });
357
463
  }
358
- return {};
359
464
  }
360
465
  var McpClient = class {
361
466
  constructor(transport, clientInfo = { name: "agentx", version: "0" }) {
@@ -379,8 +484,9 @@ var McpClient = class {
379
484
  const r = await this.transport.request("tools/list");
380
485
  return Array.isArray(r?.tools) ? r.tools : [];
381
486
  }
382
- async callTool(name, args) {
383
- return this.transport.request("tools/call", { name, arguments: args ?? {} });
487
+ /** `tools/call`. Pass `onProgress` to request progress notifications (liveness) and `signal` to cancel. */
488
+ async callTool(name, args, opts) {
489
+ return this.transport.request("tools/call", { name, arguments: args ?? {} }, opts);
384
490
  }
385
491
  async listResources() {
386
492
  const r = await this.transport.request("resources/list");
@@ -394,7 +500,7 @@ var McpClient = class {
394
500
  }
395
501
  };
396
502
  function buildTransport(cfg) {
397
- return cfg.url ? new HttpTransport({ url: cfg.url, headers: cfg.headers, bearerToken: cfg.bearerToken, timeoutMs: cfg.timeoutMs }) : new StdioTransport({ command: cfg.command, args: cfg.args, env: cfg.env, cwd: cfg.cwd, timeoutMs: cfg.timeoutMs });
503
+ return cfg.url ? new HttpTransport({ url: cfg.url, headers: cfg.headers, bearerToken: cfg.bearerToken, timeoutMs: cfg.timeoutMs, callTimeoutMs: cfg.callTimeoutMs }) : new StdioTransport({ command: cfg.command, args: cfg.args, env: cfg.env, cwd: cfg.cwd, timeoutMs: cfg.timeoutMs, callTimeoutMs: cfg.callTimeoutMs });
398
504
  }
399
505
  function withTimeout(p, ms, label) {
400
506
  if (!ms || ms <= 0) return p;
@@ -416,7 +522,7 @@ async function mountWithDeadline(name, cfg, mountTimeoutMs) {
416
522
  return await withTimeout((async () => {
417
523
  const init = await client.connect();
418
524
  const specs = await client.listTools();
419
- const tools = mcpToolsToAgentTools(specs, (tool, a) => client.callTool(tool, a), `mcp__${name}__`);
525
+ const tools = mcpToolsToAgentTools(specs, (tool, a, o) => client.callTool(tool, a, o), `mcp__${name}__`);
420
526
  return { name, client, tools, specs, serverInfo: init?.serverInfo, config: cfg };
421
527
  })(), mountTimeoutMs, name);
422
528
  } catch (e) {
@@ -599,7 +705,7 @@ async function mountMcpCatalog(servers = {}, opts = {}) {
599
705
  };
600
706
  const search = makeLazyMcpToolSearch(
601
707
  discovered.map((d) => ({ name: d.name, specs: d.specs })),
602
- async (server, rawName, args) => (await connect(server)).callTool(rawName, args),
708
+ async (server, rawName, args, o) => (await connect(server)).callTool(rawName, args, o),
603
709
  opts
604
710
  );
605
711
  const close = async () => {
@@ -621,6 +727,7 @@ async function warmMcpCatalog(servers = {}, opts = {}) {
621
727
  };
622
728
  }
623
729
  export {
730
+ DEFAULT_CALL_TIMEOUT_MS,
624
731
  HttpTransport,
625
732
  McpAuthError,
626
733
  McpClient,