@agentionai/agents 1.0.2 → 1.2.0

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,5 +1,33 @@
1
+ import EventEmitter from "events";
1
2
  import { Tool } from "../tools/Tool";
2
- import { MCPStdioConfig, MCPHttpConfig, MCPClientOptions } from "./types";
3
+ import { MCPCallOptionsSource, MCPCallToolResult, MCPClientEventMap, MCPClientOptions, MCPConnectionState, MCPHttpConfig, MCPStdioConfig, MCPToolCallOptions } from "./types";
4
+ /**
5
+ * Names of the events an {@link MCPClient} emits.
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * mcp.on(MCPClientEvent.DISCONNECTED, ({ willReconnect }) => {
10
+ * if (!willReconnect) scheduleManualReconnect();
11
+ * });
12
+ * ```
13
+ */
14
+ export declare class MCPClientEvent {
15
+ /** Emitted after a successful {@link MCPClient.connect}. */
16
+ static CONNECTED: "connected";
17
+ /** Emitted whenever the connection is lost, deliberately or not. */
18
+ static DISCONNECTED: "disconnected";
19
+ /** Emitted before each automatic reconnect attempt. */
20
+ static RECONNECTING: "reconnecting";
21
+ /** Emitted when an automatic reconnect succeeds. */
22
+ static RECONNECTED: "reconnected";
23
+ /** Emitted when the server's tool list changes. */
24
+ static TOOLS_CHANGED: "toolsChanged";
25
+ /**
26
+ * Emitted for out-of-band transport errors and for failures inside background
27
+ * work such as reconnection or tool refresh.
28
+ */
29
+ static ERROR: "error";
30
+ }
3
31
  /**
4
32
  * MCPClient connects to an MCP (Model Context Protocol) server and converts its
5
33
  * tools into agention-lib {@link Tool} instances that can be passed to any agent.
@@ -8,6 +36,9 @@ import { MCPStdioConfig, MCPHttpConfig, MCPClientOptions } from "./types";
8
36
  * - **stdio** — spawns a local process and communicates over stdin/stdout
9
37
  * - **http** — connects to a remote MCP server over Streamable HTTP
10
38
  *
39
+ * The client is an `EventEmitter`; see {@link MCPClientEvent} for the lifecycle
40
+ * events a host can watch.
41
+ *
11
42
  * @requires @modelcontextprotocol/sdk - Install as a peer dependency:
12
43
  * ```
13
44
  * npm install @modelcontextprotocol/sdk
@@ -46,6 +77,20 @@ import { MCPStdioConfig, MCPHttpConfig, MCPClientOptions } from "./types";
46
77
  * agent.addTools(mcp.getTools());
47
78
  * ```
48
79
  *
80
+ * @example Cancellable, time-boxed tool calls
81
+ * ```typescript
82
+ * let turn = new AbortController();
83
+ *
84
+ * const mcp = MCPClient.fromUrl("https://my-mcp-server.com/mcp", {
85
+ * // Resolved per call, so each agent turn gets the current signal
86
+ * callOptions: () => ({ signal: turn.signal, timeout: 20_000 }),
87
+ * reconnect: { enabled: true },
88
+ * });
89
+ *
90
+ * // Interrupting the turn now aborts any in-flight MCP call
91
+ * turn.abort();
92
+ * ```
93
+ *
49
94
  * @example HTTP with OAuth
50
95
  * ```typescript
51
96
  * import type { OAuthClientProvider } from "@modelcontextprotocol/sdk/client/auth.js";
@@ -55,19 +100,34 @@ import { MCPStdioConfig, MCPHttpConfig, MCPClientOptions } from "./types";
55
100
  * });
56
101
  * ```
57
102
  */
58
- export declare class MCPClient {
103
+ export declare class MCPClient extends EventEmitter {
59
104
  private readonly transportConfig;
60
- private readonly options;
105
+ private readonly clientName;
106
+ private readonly clientVersion;
107
+ private readonly throwOnToolError;
108
+ private readonly refreshToolsOnListChanged;
109
+ private readonly formatResult;
110
+ private readonly reconnectOptions;
111
+ private callOptions;
61
112
  private sdkClient;
62
113
  private sdkTransport;
63
114
  private _tools;
64
- private connected;
115
+ /** Signature per tool name, used to keep Tool identity stable across refreshes. */
116
+ private toolSignatures;
117
+ private _state;
118
+ private connectPromise;
119
+ private reconnectPromise;
120
+ private reconnectAttempts;
121
+ private reconnectTimer;
122
+ private reconnectWake;
123
+ private closedByUser;
124
+ private lastTransportError;
65
125
  private constructor();
66
126
  /**
67
127
  * Create an MCPClient that connects to a local MCP server process via stdio.
68
128
  *
69
129
  * @param config - Command and arguments to spawn the MCP server process
70
- * @param options - Optional client identification options
130
+ * @param options - Optional client identification and behaviour options
71
131
  */
72
132
  static fromStdio(config: MCPStdioConfig, options?: MCPClientOptions): MCPClient;
73
133
  /**
@@ -80,7 +140,8 @@ export declare class MCPClient {
80
140
  /**
81
141
  * Connect to the MCP server and discover all available tools.
82
142
  *
83
- * This method is idempotent — calling it when already connected is a no-op.
143
+ * This method is idempotent — calling it when already connected is a no-op, and
144
+ * concurrent calls share a single connection attempt.
84
145
  * Must be called before {@link getTools}.
85
146
  *
86
147
  * @throws If the MCP server cannot be reached or the SDK is not installed
@@ -92,15 +153,131 @@ export declare class MCPClient {
92
153
  * Returns an empty array if {@link connect} has not been called yet.
93
154
  * The returned tools can be passed directly to any agent via the `tools` config
94
155
  * option or {@link BaseAgent.addTools}.
156
+ *
157
+ * Tool instances are stable across reconnects and tool-list refreshes: a tool
158
+ * whose definition is unchanged keeps its identity, so agents already holding it
159
+ * keep working. Listen for {@link MCPClientEvent.TOOLS_CHANGED} to learn when the
160
+ * list itself changed.
95
161
  */
96
162
  getTools(): Tool<unknown>[];
163
+ /**
164
+ * Current connection state.
165
+ *
166
+ * @see {@link MCPConnectionState}
167
+ */
168
+ getState(): MCPConnectionState;
169
+ /** Whether the client currently has a usable connection. */
170
+ isConnected(): boolean;
171
+ /**
172
+ * Replace the default options applied to every tool call.
173
+ *
174
+ * Pass a function to have them resolved per call — the usual way to scope an
175
+ * `AbortSignal` to the current agent turn.
176
+ *
177
+ * @example
178
+ * ```typescript
179
+ * mcp.setCallOptions(() => ({ signal: currentTurn.signal, timeout: 15_000 }));
180
+ * ```
181
+ */
182
+ setCallOptions(options: MCPCallOptionsSource | undefined): void;
183
+ /**
184
+ * Call an MCP tool directly and receive the raw `CallToolResult`, including any
185
+ * image, audio or resource blocks and the `isError` flag.
186
+ *
187
+ * Unlike the wrapped {@link Tool} instances from {@link getTools}, this does not
188
+ * render the result or throw on `isError` — it is the escape hatch for hosts
189
+ * that want to handle MCP content themselves.
190
+ *
191
+ * @param name - Name of the tool as advertised by the server
192
+ * @param input - Arguments for the tool
193
+ * @param options - Per-call options, merged over the client defaults
194
+ */
195
+ callTool(name: string, input?: Record<string, unknown>, options?: MCPToolCallOptions): Promise<MCPCallToolResult>;
196
+ /**
197
+ * Re-run tool discovery against the connected server.
198
+ *
199
+ * Called automatically when the server sends `notifications/tools/list_changed`
200
+ * (unless `refreshToolsOnListChanged` is disabled) and after a successful
201
+ * reconnect. Emits {@link MCPClientEvent.TOOLS_CHANGED} when the list differs.
202
+ *
203
+ * @returns The refreshed tool list
204
+ */
205
+ refreshTools(): Promise<Tool<unknown>[]>;
97
206
  /**
98
207
  * Disconnect from the MCP server and release all resources.
99
208
  *
100
- * This method is idempotent — calling it when not connected is a no-op.
101
- * After disconnecting, {@link getTools} returns an empty array.
209
+ * This method is idempotent — calling it when not connected is a no-op. It also
210
+ * cancels any pending automatic reconnect. After disconnecting, {@link getTools}
211
+ * returns an empty array; call {@link connect} again to start over.
102
212
  */
103
213
  disconnect(): Promise<void>;
214
+ /**
215
+ * Subscribe to a client lifecycle event.
216
+ *
217
+ * @see {@link MCPClientEvent} for the available event names.
218
+ */
219
+ on<K extends keyof MCPClientEventMap>(event: K, listener: (payload: MCPClientEventMap[K]) => void): this;
220
+ on(event: string | symbol, listener: (...args: any[]) => void): this;
221
+ /** Subscribe to a client lifecycle event for a single emission. */
222
+ once<K extends keyof MCPClientEventMap>(event: K, listener: (payload: MCPClientEventMap[K]) => void): this;
223
+ once(event: string | symbol, listener: (...args: any[]) => void): this;
224
+ /**
225
+ * Open the SDK client and transport, wire up lifecycle handlers and discover
226
+ * tools. Shared by {@link connect} and the reconnect loop.
227
+ */
228
+ private establish;
229
+ /**
230
+ * Ask the server to notify us about tool list changes. Failures here are not
231
+ * fatal — an older SDK or a server without the capability simply means the
232
+ * cached list stays as it was at connect time.
233
+ */
234
+ private subscribeToToolListChanges;
235
+ /** Page through `tools/list` until the server stops handing back a cursor. */
236
+ private listAllTools;
237
+ /**
238
+ * Reconcile the cached tool list with a fresh set of definitions, reusing the
239
+ * existing {@link Tool} instance for every definition that has not changed so
240
+ * agents holding a reference keep working.
241
+ */
242
+ private applyToolDefinitions;
243
+ /**
244
+ * Handle the transport closing. Deliberate closes are reported by
245
+ * {@link disconnect} itself; everything else is an unexpected drop.
246
+ */
247
+ private handleClose;
248
+ private handleTransportError;
249
+ /**
250
+ * Retry {@link establish} with exponential backoff until it succeeds, the retry
251
+ * budget runs out, or {@link disconnect} is called.
252
+ */
253
+ private startReconnectLoop;
254
+ private waitBeforeReconnect;
255
+ private cancelReconnectWait;
256
+ /**
257
+ * `EventEmitter` throws when an `error` event has no listener, which would turn
258
+ * a background transport hiccup into a process crash. Only emit when someone is
259
+ * actually listening.
260
+ */
261
+ private emitError;
262
+ private emitEvent;
263
+ /**
264
+ * Resolve the effective request options for a call: client defaults (static or
265
+ * per-call), with explicit per-call options layered on top.
266
+ */
267
+ private resolveCallOptions;
268
+ /**
269
+ * Wait for the client to become usable, then issue the call. Wrapping every
270
+ * transport-level failure keeps the error surface stable, while `cause` lets a
271
+ * host tell an abort apart from a server error.
272
+ */
273
+ private invokeTool;
274
+ /**
275
+ * Return the SDK client once one is usable. While a reconnect is in flight the
276
+ * call waits for it rather than failing outright, so a transient drop does not
277
+ * surface as a tool error — but an aborted signal still wins immediately.
278
+ */
279
+ private awaitUsableClient;
280
+ private raceAbort;
104
281
  private wrapMcpTool;
105
282
  }
106
283
  //# sourceMappingURL=MCPClient.d.ts.map