@agentionai/agents 0.6.1 → 0.7.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.
@@ -4,11 +4,6 @@ import { History, HistoryEntry, MessageRole, MessageContent } from "../history/H
4
4
  import { AgentVendor, CommonAgentConfig, VendorSpecificConfig } from "./AgentConfig";
5
5
  export type { HistoryEntry, MessageRole, MessageContent };
6
6
  export type { AgentVendor };
7
- /**
8
- * Parses a `retry-after` header value (seconds as string) into milliseconds.
9
- */
10
- declare function parseRetryAfterHeader(header: string | undefined): number | undefined;
11
- export { parseRetryAfterHeader };
12
7
  /**
13
8
  * Agent config as used across all agents
14
9
  * @deprecated Use CommonAgentConfig with vendorConfig instead
@@ -38,16 +33,6 @@ export declare abstract class BaseAgent<TInput = unknown, TOutput = unknown> ext
38
33
  protected vendor: AgentVendor;
39
34
  /** The model identifier for this agent */
40
35
  protected model: string;
41
- /** Token usage from the last execution (for metrics tracking) */
42
- lastTokenUsage?: TokenUsage;
43
- /** Maximum number of retry attempts (0 = disabled) */
44
- protected maxRetries: number;
45
- /** Initial backoff delay in ms */
46
- private retryDelayMs;
47
- /** Multiplier applied to delay after each attempt */
48
- private retryBackoffFactor;
49
- /** Maximum backoff delay cap in ms */
50
- private retryMaxDelayMs;
51
36
  /**
52
37
  * An Agent is the primary LLM entity.
53
38
  *
@@ -83,30 +68,6 @@ export declare abstract class BaseAgent<TInput = unknown, TOutput = unknown> ext
83
68
  * Add a message with content blocks to history
84
69
  */
85
70
  protected addMessageToHistory(role: MessageRole, content: MessageContent[]): void;
86
- /**
87
- * Enable retry with exponential backoff for this agent.
88
- * @param options.maxRetries - Number of retry attempts (default: 3)
89
- * @param options.initialDelay - Initial backoff delay in ms (default: 1000)
90
- * @param options.backoffFactor - Multiplier per attempt (default: 2)
91
- * @param options.maxDelay - Maximum delay cap in ms (default: 30000)
92
- */
93
- withRetry(options?: {
94
- maxRetries?: number;
95
- initialDelay?: number;
96
- backoffFactor?: number;
97
- maxDelay?: number;
98
- }): this;
99
- /**
100
- * Executes a function with retry and exponential backoff.
101
- *
102
- * Retries on 429 (rate limit) and 5xx (server error) responses.
103
- * Never retries on MaxTokensExceededError or 4xx client errors.
104
- * Throws MaxRetriesExceededError when all attempts are exhausted.
105
- *
106
- * @param fn - The async function to execute
107
- * @param getRetryAfterMs - Optional extractor for retry-after header (returns ms to wait)
108
- */
109
- protected executeWithRetry<T>(fn: () => Promise<T>, getRetryAfterMs?: (error: unknown) => number | undefined): Promise<T>;
110
71
  addTools(tools: Tool<unknown>[]): void;
111
72
  getId(): string;
112
73
  getName(): string;
@@ -4,30 +4,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.BaseAgent = void 0;
7
- exports.parseRetryAfterHeader = parseRetryAfterHeader;
8
7
  const events_1 = __importDefault(require("events"));
9
8
  const Tool_1 = require("../tools/Tool");
10
9
  const History_1 = require("../history/History");
11
- const AgentEvent_1 = require("./AgentEvent");
12
- const AgentError_1 = require("./errors/AgentError");
13
- /**
14
- * Extracts an HTTP status code from a raw SDK error of any vendor shape.
15
- */
16
- function extractStatusCode(error) {
17
- if (error instanceof AgentError_1.ApiError)
18
- return error.statusCode;
19
- const e = error;
20
- return typeof e.status === "number" ? e.status : undefined;
21
- }
22
- /**
23
- * Parses a `retry-after` header value (seconds as string) into milliseconds.
24
- */
25
- function parseRetryAfterHeader(header) {
26
- if (!header)
27
- return undefined;
28
- const seconds = parseFloat(header);
29
- return isNaN(seconds) ? undefined : Math.ceil(seconds * 1000);
30
- }
31
10
  /**
32
11
  * The base agent is what the other agents are inheriting from
33
12
  * Handles the BaseConfig
@@ -45,15 +24,7 @@ class BaseAgent extends events_1.default {
45
24
  constructor(config, history = new History_1.History([], { transient: true })) {
46
25
  super();
47
26
  this.history = history;
48
- this.debug = false;
49
- /** Maximum number of retry attempts (0 = disabled) */
50
- this.maxRetries = 0;
51
- /** Initial backoff delay in ms */
52
- this.retryDelayMs = 1000;
53
- /** Multiplier applied to delay after each attempt */
54
- this.retryBackoffFactor = 2;
55
- /** Maximum backoff delay cap in ms */
56
- this.retryMaxDelayMs = 30000;
27
+ this.debug = true;
57
28
  this.id = config.id;
58
29
  this.debug = config.debug || false;
59
30
  this.name = config.name;
@@ -70,7 +41,6 @@ class BaseAgent extends events_1.default {
70
41
  }
71
42
  this.tools = new Map((config.tools || []).map((tool) => [tool.name, tool]));
72
43
  this.maxHistoryLength = config.maxHistoryLength || 100;
73
- this.maxRetries = config.maxRetries ?? 0;
74
44
  }
75
45
  getToolDefinitions() {
76
46
  return Array.from(this.tools.values()).map((tool) => tool.getPrompt());
@@ -111,75 +81,6 @@ class BaseAgent extends events_1.default {
111
81
  addMessageToHistory(role, content) {
112
82
  this.history.addMessage(role, content);
113
83
  }
114
- /**
115
- * Enable retry with exponential backoff for this agent.
116
- * @param options.maxRetries - Number of retry attempts (default: 3)
117
- * @param options.initialDelay - Initial backoff delay in ms (default: 1000)
118
- * @param options.backoffFactor - Multiplier per attempt (default: 2)
119
- * @param options.maxDelay - Maximum delay cap in ms (default: 30000)
120
- */
121
- withRetry(options) {
122
- this.maxRetries = options?.maxRetries ?? 3;
123
- if (options?.initialDelay !== undefined)
124
- this.retryDelayMs = options.initialDelay;
125
- if (options?.backoffFactor !== undefined)
126
- this.retryBackoffFactor = options.backoffFactor;
127
- if (options?.maxDelay !== undefined)
128
- this.retryMaxDelayMs = options.maxDelay;
129
- return this;
130
- }
131
- /**
132
- * Executes a function with retry and exponential backoff.
133
- *
134
- * Retries on 429 (rate limit) and 5xx (server error) responses.
135
- * Never retries on MaxTokensExceededError or 4xx client errors.
136
- * Throws MaxRetriesExceededError when all attempts are exhausted.
137
- *
138
- * @param fn - The async function to execute
139
- * @param getRetryAfterMs - Optional extractor for retry-after header (returns ms to wait)
140
- */
141
- async executeWithRetry(fn, getRetryAfterMs) {
142
- let attempt = 0;
143
- let delayMs = this.retryDelayMs;
144
- while (true) {
145
- try {
146
- return await fn();
147
- }
148
- catch (error) {
149
- // MaxTokensExceededError is never retryable
150
- if (error instanceof AgentError_1.MaxTokensExceededError)
151
- throw error;
152
- const statusCode = extractStatusCode(error);
153
- const isRetryable = statusCode === 429 ||
154
- (statusCode !== undefined && statusCode >= 500);
155
- if (!isRetryable || attempt >= this.maxRetries) {
156
- if (attempt > 0) {
157
- this.emit(AgentEvent_1.AgentEvent.MAX_RETRIES_EXCEEDED, {
158
- maxRetries: this.maxRetries,
159
- error,
160
- });
161
- throw new AgentError_1.MaxRetriesExceededError(`Max retries (${this.maxRetries}) exceeded`, this.maxRetries);
162
- }
163
- throw error;
164
- }
165
- attempt++;
166
- // Respect retry-after header if the SDK provides it
167
- const retryAfter = getRetryAfterMs?.(error);
168
- // Add ±10% jitter to avoid thundering herd
169
- const jitter = delayMs * 0.1 * (Math.random() * 2 - 1);
170
- const waitMs = Math.min(retryAfter ?? delayMs + jitter, this.retryMaxDelayMs);
171
- this.emit(AgentEvent_1.AgentEvent.RETRY, {
172
- attempt,
173
- maxRetries: this.maxRetries,
174
- delayMs: waitMs,
175
- statusCode,
176
- error,
177
- });
178
- await new Promise((resolve) => setTimeout(resolve, waitMs));
179
- delayMs = Math.min(delayMs * this.retryBackoffFactor, this.retryMaxDelayMs);
180
- }
181
- }
182
- }
183
84
  addTools(tools) {
184
85
  tools.forEach((tool) => {
185
86
  if (!this.tools.has(tool.name)) {
@@ -28,6 +28,8 @@ type AgentConfig = BaseAgentConfig & {
28
28
  export declare class ClaudeAgent extends BaseAgent {
29
29
  private client;
30
30
  protected config: Partial<AgentConfig>;
31
+ /** Token usage from the last execution (for metrics tracking) */
32
+ lastTokenUsage?: TokenUsage;
31
33
  /** Current visualization event ID for tracking */
32
34
  private vizEventId?;
33
35
  /** Count of tool calls in current execution */
@@ -77,7 +77,7 @@ class ClaudeAgent extends BaseAgent_1.BaseAgent {
77
77
  try {
78
78
  const messages = transformers_1.anthropicTransformer.toProvider(this.history.entries);
79
79
  const systemMessage = this.history.getSystemMessage();
80
- const response = await this.executeWithRetry(() => this.client.messages.create({
80
+ const response = await this.client.messages.create({
81
81
  model: this.config.model,
82
82
  system: systemMessage,
83
83
  max_tokens: this.config.maxTokens,
@@ -88,9 +88,7 @@ class ClaudeAgent extends BaseAgent_1.BaseAgent {
88
88
  top_k: this.config.topK,
89
89
  stop_sequences: this.config.stopSequences,
90
90
  metadata: this.config.metadata,
91
- }), (err) => err instanceof sdk_1.APIError
92
- ? (0, BaseAgent_1.parseRetryAfterHeader)(err.headers?.["retry-after"])
93
- : undefined);
91
+ });
94
92
  this.emit(AgentEvent_1.AgentEvent.AFTER_EXECUTE, response);
95
93
  return await this.handleResponse(response);
96
94
  }
@@ -180,7 +178,7 @@ class ClaudeAgent extends BaseAgent_1.BaseAgent {
180
178
  // Continue conversation with tool results
181
179
  try {
182
180
  const messages = transformers_1.anthropicTransformer.toProvider(this.history.entries);
183
- const newResponse = await this.executeWithRetry(() => this.client.messages.create({
181
+ const newResponse = await this.client.messages.create({
184
182
  model: this.config.model,
185
183
  max_tokens: this.config.maxTokens,
186
184
  messages,
@@ -190,9 +188,7 @@ class ClaudeAgent extends BaseAgent_1.BaseAgent {
190
188
  top_k: this.config.topK,
191
189
  stop_sequences: this.config.stopSequences,
192
190
  metadata: this.config.metadata,
193
- }), (err) => err instanceof sdk_1.APIError
194
- ? (0, BaseAgent_1.parseRetryAfterHeader)(err.headers?.["retry-after"])
195
- : undefined);
191
+ });
196
192
  this.emit(AgentEvent_1.AgentEvent.AFTER_EXECUTE, newResponse);
197
193
  return this.handleResponse(newResponse);
198
194
  }
@@ -29,6 +29,8 @@ export declare class GeminiAgent extends BaseAgent {
29
29
  private client;
30
30
  private generativeModel;
31
31
  protected config: Partial<AgentConfig>;
32
+ /** Token usage from the last execution (for metrics tracking) */
33
+ lastTokenUsage?: TokenUsage;
32
34
  /** Current visualization event ID for tracking */
33
35
  private vizEventId?;
34
36
  /** Count of tool calls in current execution */
@@ -179,7 +179,7 @@ class GeminiAgent extends BaseAgent_1.BaseAgent {
179
179
  const contents = transformers_1.geminiTransformer.toProvider(this.history.entries);
180
180
  const systemMessage = this.history.getSystemMessage();
181
181
  const tools = this.getToolDefinitionsForGemini();
182
- const response = await this.executeWithRetry(() => this.generativeModel.generateContent({
182
+ const response = await this.generativeModel.generateContent({
183
183
  contents,
184
184
  systemInstruction: systemMessage,
185
185
  tools: tools ? [tools] : undefined,
@@ -193,7 +193,7 @@ class GeminiAgent extends BaseAgent_1.BaseAgent {
193
193
  responseMimeType: this.config.responseMimeType,
194
194
  responseSchema: this.config.responseSchema,
195
195
  },
196
- }));
196
+ });
197
197
  this.emit(AgentEvent_1.AgentEvent.AFTER_EXECUTE, response);
198
198
  return await this.handleResponse(response);
199
199
  }
@@ -293,7 +293,7 @@ class GeminiAgent extends BaseAgent_1.BaseAgent {
293
293
  const newContents = transformers_1.geminiTransformer.toProvider(this.history.entries);
294
294
  const systemMessage = this.history.getSystemMessage();
295
295
  const tools = this.getToolDefinitionsForGemini();
296
- const newResponse = await this.executeWithRetry(() => this.generativeModel.generateContent({
296
+ const newResponse = await this.generativeModel.generateContent({
297
297
  contents: newContents,
298
298
  systemInstruction: systemMessage,
299
299
  tools: tools ? [tools] : undefined,
@@ -307,7 +307,7 @@ class GeminiAgent extends BaseAgent_1.BaseAgent {
307
307
  responseMimeType: this.config.responseMimeType,
308
308
  responseSchema: this.config.responseSchema,
309
309
  },
310
- }));
310
+ });
311
311
  this.emit(AgentEvent_1.AgentEvent.AFTER_EXECUTE, newResponse);
312
312
  return this.handleResponse(newResponse);
313
313
  }
@@ -29,6 +29,8 @@ type AgentConfig = BaseAgentConfig & {
29
29
  export declare class MistralAgent extends BaseAgent {
30
30
  private client;
31
31
  protected config: Partial<AgentConfig>;
32
+ /** Token usage from the last execution (for metrics tracking) */
33
+ lastTokenUsage?: TokenUsage;
32
34
  /** Current visualization event ID for tracking */
33
35
  private vizEventId?;
34
36
  /** Count of tool calls in current execution */
@@ -87,7 +87,7 @@ class MistralAgent extends BaseAgent_1.BaseAgent {
87
87
  this.addTextToHistory("user", input);
88
88
  try {
89
89
  const messages = transformers_1.mistralTransformer.toProvider(this.history.entries);
90
- const response = await this.executeWithRetry(() => this.client.chat.complete({
90
+ const response = await this.client.chat.complete({
91
91
  model: this.config.model,
92
92
  messages: messages,
93
93
  tools: this.getToolDefinitions(),
@@ -97,7 +97,7 @@ class MistralAgent extends BaseAgent_1.BaseAgent {
97
97
  randomSeed: this.config.randomSeed,
98
98
  safePrompt: this.config.safePrompt,
99
99
  stop: this.config.stopSequences,
100
- }));
100
+ });
101
101
  this.emit(AgentEvent_1.AgentEvent.AFTER_EXECUTE, response);
102
102
  return await this.handleResponse(response);
103
103
  }
@@ -203,7 +203,7 @@ class MistralAgent extends BaseAgent_1.BaseAgent {
203
203
  // Continue conversation
204
204
  try {
205
205
  const messages = transformers_1.mistralTransformer.toProvider(this.history.entries);
206
- const newResponse = await this.executeWithRetry(() => this.client.chat.complete({
206
+ const newResponse = await this.client.chat.complete({
207
207
  model: this.config.model,
208
208
  messages: messages,
209
209
  tools: this.getToolDefinitions(),
@@ -213,7 +213,7 @@ class MistralAgent extends BaseAgent_1.BaseAgent {
213
213
  randomSeed: this.config.randomSeed,
214
214
  safePrompt: this.config.safePrompt,
215
215
  stop: this.config.stopSequences,
216
- }));
216
+ });
217
217
  this.emit(AgentEvent_1.AgentEvent.AFTER_EXECUTE, newResponse);
218
218
  return this.handleResponse(newResponse);
219
219
  }
@@ -30,6 +30,8 @@ type AgentConfig = BaseAgentConfig & {
30
30
  export declare class OpenAiAgent extends BaseAgent {
31
31
  private client;
32
32
  protected config: Partial<AgentConfig>;
33
+ /** Token usage from the last execution (for metrics tracking) */
34
+ lastTokenUsage?: TokenUsage;
33
35
  /** Current visualization event ID for tracking */
34
36
  private vizEventId?;
35
37
  /** Count of tool calls in current execution */
@@ -98,7 +98,7 @@ class OpenAiAgent extends BaseAgent_1.BaseAgent {
98
98
  this.addTextToHistory("user", input);
99
99
  try {
100
100
  const inputMessages = transformers_1.openAiTransformer.toProvider(this.history.entries);
101
- const response = await this.executeWithRetry(() => this.client.responses.create({
101
+ const response = await this.client.responses.create({
102
102
  model: this.config.model,
103
103
  max_output_tokens: this.config.maxTokens,
104
104
  input: inputMessages,
@@ -110,7 +110,7 @@ class OpenAiAgent extends BaseAgent_1.BaseAgent {
110
110
  user: this.config.user,
111
111
  ...(this.config.disableReasoning && { reasoning: { effort: null } }),
112
112
  reasoning: { effort: this.config.reasoningEffort },
113
- }));
113
+ });
114
114
  this.emit(AgentEvent_1.AgentEvent.AFTER_EXECUTE, response);
115
115
  return await this.handleResponse(response);
116
116
  }
@@ -217,7 +217,7 @@ class OpenAiAgent extends BaseAgent_1.BaseAgent {
217
217
  // Continue conversation
218
218
  try {
219
219
  const inputMessages = transformers_1.openAiTransformer.toProvider(this.history.entries);
220
- const newResponse = await this.executeWithRetry(() => this.client.responses.create({
220
+ const newResponse = await this.client.responses.create({
221
221
  model: this.config.model,
222
222
  max_output_tokens: this.config.maxTokens,
223
223
  input: inputMessages,
@@ -234,7 +234,7 @@ class OpenAiAgent extends BaseAgent_1.BaseAgent {
234
234
  !this.config.disableReasoning && {
235
235
  reasoning: { effort: this.config.reasoningEffort },
236
236
  }),
237
- }));
237
+ });
238
238
  this.emit(AgentEvent_1.AgentEvent.AFTER_EXECUTE, newResponse);
239
239
  return this.handleResponse(newResponse);
240
240
  }
package/dist/core.d.ts CHANGED
@@ -7,6 +7,7 @@ export * from "./history/History";
7
7
  export * from "./history/types";
8
8
  export * from "./graph/AgentGraph";
9
9
  export * from "./tools/Tool";
10
+ export * from "./mcp";
10
11
  export * from "./viz";
11
12
  export * from "./vectorstore";
12
13
  export * from "./chunkers";
package/dist/core.js CHANGED
@@ -29,6 +29,8 @@ __exportStar(require("./history/types"), exports);
29
29
  __exportStar(require("./graph/AgentGraph"), exports);
30
30
  // Tools
31
31
  __exportStar(require("./tools/Tool"), exports);
32
+ // MCP (Model Context Protocol)
33
+ __exportStar(require("./mcp"), exports);
32
34
  // Visualization
33
35
  __exportStar(require("./viz"), exports);
34
36
  // Vector Store
@@ -23,14 +23,6 @@ export interface PlanExecutorOptions {
23
23
  * @default true
24
24
  */
25
25
  stopOnFailure?: boolean;
26
- /**
27
- * Maximum number of previous step results to include in worker context.
28
- * This prevents context overflow by limiting how much history is passed to each step.
29
- * Set to 0 to include no previous steps (workers should use context_get to retrieve data).
30
- * Set to a small number (1-3) to include only recent context.
31
- * @default 0 (workers request context explicitly)
32
- */
33
- maxContextSteps?: number;
34
26
  /**
35
27
  * Callback invoked when planning phase completes.
36
28
  */
@@ -153,10 +145,6 @@ export declare class PlanExecutor extends BaseExecutor<string, string> {
153
145
  private createPlanningPrompt;
154
146
  /**
155
147
  * Create input for a step execution.
156
- *
157
- * By default, only includes the current step information.
158
- * Workers should use context_get to retrieve data from previous steps.
159
- * This prevents token overflow from accumulating context.
160
148
  */
161
149
  private createStepInput;
162
150
  /**
@@ -57,7 +57,6 @@ class PlanExecutor extends BaseExecutor_1.BaseExecutor {
57
57
  maxSteps: options.maxSteps ?? 50,
58
58
  concurrency: options.concurrency ?? 1,
59
59
  stopOnFailure: options.stopOnFailure ?? true,
60
- maxContextSteps: options.maxContextSteps ?? 0, // Default: no auto context
61
60
  onPlanCreated: options.onPlanCreated,
62
61
  onStepStart: options.onStepStart,
63
62
  onStepComplete: options.onStepComplete,
@@ -151,16 +150,11 @@ class PlanExecutor extends BaseExecutor_1.BaseExecutor {
151
150
  const results = [];
152
151
  let stepNumber = 0;
153
152
  const activePromises = new Map();
154
- let stopError;
155
153
  while (stepNumber < this.options.maxSteps) {
156
154
  // Wait if we've reached concurrency limit
157
155
  if (activePromises.size >= this.options.concurrency) {
158
156
  await Promise.race(activePromises.values());
159
157
  }
160
- // If a step failed and stopOnFailure is set, drain remaining promises then throw
161
- if (stopError) {
162
- break;
163
- }
164
158
  const nextStep = this.planStore.getNextStep();
165
159
  if (!nextStep) {
166
160
  // No more pending steps
@@ -208,9 +202,9 @@ class PlanExecutor extends BaseExecutor_1.BaseExecutor {
208
202
  });
209
203
  // Notify step failure
210
204
  this.options.onStepFailed?.(nextStep, error instanceof Error ? error : new Error(errorMessage), stepNumber);
211
- // Record error to stop after in-flight steps complete
205
+ // Stop if configured to do so
212
206
  if (this.options.stopOnFailure) {
213
- stopError = new Error(`Step ${stepNumber} failed: ${errorMessage}`);
207
+ throw new Error(`Step ${stepNumber} failed: ${errorMessage}`);
214
208
  }
215
209
  }
216
210
  finally {
@@ -226,12 +220,9 @@ class PlanExecutor extends BaseExecutor_1.BaseExecutor {
226
220
  await promise;
227
221
  }
228
222
  }
229
- // Always wait for all in-flight promises to finish before returning/throwing
223
+ // Wait for all remaining promises to complete
230
224
  if (activePromises.size > 0) {
231
- await Promise.allSettled(activePromises.values());
232
- }
233
- if (stopError) {
234
- throw stopError;
225
+ await Promise.all(activePromises.values());
235
226
  }
236
227
  if (stepNumber >= this.options.maxSteps) {
237
228
  const plan = this.planStore.getActivePlan();
@@ -250,81 +241,34 @@ class PlanExecutor extends BaseExecutor_1.BaseExecutor {
250
241
 
251
242
  Task: ${task}
252
243
 
253
- CRITICAL: You can create a maximum of ${this.options.maxSteps} steps. Plan accordingly and prioritize the most important subtasks.
254
-
255
- CONTEXT LIMIT WARNING: Each step will be executed independently with limited context. To avoid rate limits and context overflow:
256
- - Break work into VERY SMALL, ATOMIC steps
257
- - Each step should process only 1-3 items at a time
258
- - Never create steps that say "analyze all", "process everything", "read all files", etc.
259
- - Instead, break into multiple steps: "Read file1", "Read file2", "Read file3"
260
-
261
- Use the create_plan tool to create a plan with clear, actionable steps. Each step MUST be:
262
-
263
- 1. MICRO-SIZED - Can be completed in under 10 seconds with minimal tokens
264
- 2. SINGLE ACTION - Exactly ONE thing to do (read ONE file, list ONE directory, etc.)
265
- 3. SPECIFIC - Mention exact file names, directories, or items (not "all files")
266
- 4. NO BATCH OPERATIONS - Process items one-by-one, not in bulk
267
- 5. SEQUENTIAL - Let each step's output inform the next step
268
-
269
- GOOD EXAMPLES (SMALL STEPS):
270
- ✓ "List files in the lib/graph directory"
271
- ✓ "Read the first 50 lines of PlanExecutor.ts"
272
- ✓ "Search for the definition of 'createPlan' function"
273
- ✓ "Summarize the purpose of SequentialExecutor class in 2 sentences"
274
-
275
- BAD EXAMPLES (TOO LARGE):
276
- ✗ "Read and analyze all files in lib/graph" (reads too much, use multiple steps)
277
- ✗ "Analyze the entire codebase architecture" (too broad, break into 5+ steps)
278
- ✗ "Review all test files and identify issues" (batch operation, do one at a time)
279
- ✗ "Research best practices and implement them" (vague, multi-step)
244
+ IMPORTANT: You can create a maximum of ${this.options.maxSteps} steps. Plan accordingly and prioritize the most important subtasks.
280
245
 
281
- STRATEGY FOR AVOIDING RATE LIMITS:
282
- - If analyzing multiple files: Create one step per file
283
- - If processing a list: Create one step per item
284
- - If researching: Create steps for: 1) identify what to research, 2) research item 1, 3) research item 2, etc.
285
- - If the task seems large: Create 2x as many steps as you initially think
286
-
287
- Break down complex tasks into the SMALLEST possible steps. Having ${this.options.maxSteps} small steps is much better than having ${Math.floor(this.options.maxSteps / 2)} larger ones.
246
+ Use the create_plan tool to create a plan with clear, actionable steps. Each step should be:
247
+ - Specific and focused on a single subtask
248
+ - Ordered logically (dependencies should be addressed)
249
+ - Achievable by a worker agent
288
250
 
289
251
  After creating the plan, respond with a brief confirmation.`;
290
252
  }
291
253
  /**
292
254
  * Create input for a step execution.
293
- *
294
- * By default, only includes the current step information.
295
- * Workers should use context_get to retrieve data from previous steps.
296
- * This prevents token overflow from accumulating context.
297
255
  */
298
256
  createStepInput(step, stepNumber) {
299
257
  const plan = this.planStore.getActivePlan();
300
258
  const completedSteps = plan?.steps.filter((s) => s.status === "completed") || [];
301
- // Limit context to prevent token overflow
302
- // Only include the most recent N steps based on maxContextSteps option
303
- const recentSteps = this.options.maxContextSteps > 0
304
- ? completedSteps.slice(-this.options.maxContextSteps)
305
- : [];
306
- const input = {
259
+ return JSON.stringify({
307
260
  stepNumber,
308
261
  totalSteps: plan?.steps.length,
309
262
  currentStep: {
310
263
  id: step.id,
311
264
  description: step.description,
312
265
  },
313
- planGoal: plan?.goal,
314
- };
315
- // Only add previous steps if maxContextSteps > 0
316
- if (this.options.maxContextSteps > 0 && recentSteps.length > 0) {
317
- input.previousSteps = recentSteps.map((s) => ({
266
+ previousSteps: completedSteps.map((s) => ({
318
267
  description: s.description,
319
268
  output: s.output,
320
- }));
321
- input.contextNote = `Showing last ${recentSteps.length} of ${completedSteps.length} completed steps`;
322
- }
323
- else {
324
- input.contextNote =
325
- "Use context_get tool to retrieve data from previous steps if needed";
326
- }
327
- return JSON.stringify(input, null, 2);
269
+ })),
270
+ planGoal: plan?.goal,
271
+ });
328
272
  }
329
273
  /**
330
274
  * Compile the final result from step results.
@@ -377,12 +321,13 @@ After creating the plan, respond with a brief confirmation.`;
377
321
  * Extract token usage from an agent if available.
378
322
  */
379
323
  extractTokenUsage(agent) {
380
- if (!agent.lastTokenUsage)
324
+ const agentWithUsage = agent;
325
+ if (!agentWithUsage.lastTokenUsage)
381
326
  return undefined;
382
327
  return {
383
- inputTokens: agent.lastTokenUsage.input_tokens,
384
- outputTokens: agent.lastTokenUsage.output_tokens,
385
- totalTokens: agent.lastTokenUsage.total_tokens,
328
+ inputTokens: agentWithUsage.lastTokenUsage.input_tokens,
329
+ outputTokens: agentWithUsage.lastTokenUsage.output_tokens,
330
+ totalTokens: agentWithUsage.lastTokenUsage.total_tokens,
386
331
  };
387
332
  }
388
333
  /**
@@ -119,12 +119,8 @@ class PlanStore {
119
119
  const plan = this.getActivePlan();
120
120
  if (!plan)
121
121
  return undefined;
122
- const maxIndex = plan.steps.reduce((max, s) => {
123
- const match = s.id.match(/^step_(\d+)$/);
124
- return match ? Math.max(max, parseInt(match[1], 10)) : max;
125
- }, 0);
126
122
  const newStep = {
127
- id: `step_${maxIndex + 1}`,
123
+ id: `step_${plan.steps.length + 1}`,
128
124
  description,
129
125
  status: "pending",
130
126
  };
@@ -173,7 +169,7 @@ class PlanStore {
173
169
  * Update the overall plan status based on step statuses.
174
170
  */
175
171
  updatePlanStatus(plan) {
176
- const allCompleted = plan.steps.every((s) => s.status === "completed" || s.status === "skipped");
172
+ const allCompleted = plan.steps.every((s) => s.status === "completed");
177
173
  const anyFailed = plan.steps.some((s) => s.status === "failed");
178
174
  const anyInProgress = plan.steps.some((s) => s.status === "in_progress");
179
175
  let newStatus;
package/dist/index.d.ts CHANGED
@@ -9,6 +9,7 @@ export * from "./history/types";
9
9
  export { anthropicTransformer, openAiTransformer, mistralTransformer, geminiTransformer, } from "./history/transformers";
10
10
  export * from "./graph/AgentGraph";
11
11
  export * from "./tools/Tool";
12
+ export * from "./mcp";
12
13
  export * from "./viz";
13
14
  export * from "./vectorstore";
14
15
  export * from "./embeddings";
package/dist/index.js CHANGED
@@ -45,6 +45,8 @@ Object.defineProperty(exports, "geminiTransformer", { enumerable: true, get: fun
45
45
  __exportStar(require("./graph/AgentGraph"), exports);
46
46
  // Tools
47
47
  __exportStar(require("./tools/Tool"), exports);
48
+ // MCP (Model Context Protocol)
49
+ __exportStar(require("./mcp"), exports);
48
50
  // Visualization
49
51
  __exportStar(require("./viz"), exports);
50
52
  // Vector Store
@@ -0,0 +1,106 @@
1
+ import { Tool } from "../tools/Tool";
2
+ import { MCPStdioConfig, MCPHttpConfig, MCPClientOptions } from "./types";
3
+ /**
4
+ * MCPClient connects to an MCP (Model Context Protocol) server and converts its
5
+ * tools into agention-lib {@link Tool} instances that can be passed to any agent.
6
+ *
7
+ * Supports two transport types:
8
+ * - **stdio** — spawns a local process and communicates over stdin/stdout
9
+ * - **http** — connects to a remote MCP server over Streamable HTTP
10
+ *
11
+ * @requires @modelcontextprotocol/sdk - Install as a peer dependency:
12
+ * ```
13
+ * npm install @modelcontextprotocol/sdk
14
+ * ```
15
+ *
16
+ * @example Stdio (local process)
17
+ * ```typescript
18
+ * import { MCPClient } from "@agentionai/agents";
19
+ * import { ClaudeAgent } from "@agentionai/agents/claude";
20
+ *
21
+ * const mcp = MCPClient.fromStdio({
22
+ * command: "npx",
23
+ * args: ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"],
24
+ * });
25
+ *
26
+ * await mcp.connect();
27
+ * const agent = new ClaudeAgent({
28
+ * id: "file-agent",
29
+ * name: "File Agent",
30
+ * description: "An agent that can work with files",
31
+ * apiKey: process.env.ANTHROPIC_API_KEY!,
32
+ * tools: mcp.getTools(),
33
+ * });
34
+ *
35
+ * const result = await agent.execute("List the files in /tmp");
36
+ * await mcp.disconnect();
37
+ * ```
38
+ *
39
+ * @example HTTP with static API key
40
+ * ```typescript
41
+ * const mcp = MCPClient.fromUrl("https://my-mcp-server.com/mcp", {
42
+ * headers: { Authorization: "Bearer my-api-key" },
43
+ * });
44
+ *
45
+ * await mcp.connect();
46
+ * agent.addTools(mcp.getTools());
47
+ * ```
48
+ *
49
+ * @example HTTP with OAuth
50
+ * ```typescript
51
+ * import type { OAuthClientProvider } from "@modelcontextprotocol/sdk/client/auth.js";
52
+ *
53
+ * const mcp = MCPClient.fromUrl("https://my-mcp-server.com/mcp", {
54
+ * authProvider: myOAuthProvider, // implements OAuthClientProvider
55
+ * });
56
+ * ```
57
+ */
58
+ export declare class MCPClient {
59
+ private readonly transportConfig;
60
+ private readonly options;
61
+ private sdkClient;
62
+ private sdkTransport;
63
+ private _tools;
64
+ private connected;
65
+ private constructor();
66
+ /**
67
+ * Create an MCPClient that connects to a local MCP server process via stdio.
68
+ *
69
+ * @param config - Command and arguments to spawn the MCP server process
70
+ * @param options - Optional client identification options
71
+ */
72
+ static fromStdio(config: MCPStdioConfig, options?: MCPClientOptions): MCPClient;
73
+ /**
74
+ * Create an MCPClient that connects to a remote MCP server via HTTP.
75
+ *
76
+ * @param url - Full URL to the MCP endpoint
77
+ * @param options - Optional client options including auth headers or OAuth provider
78
+ */
79
+ static fromUrl(url: string, options?: MCPClientOptions & Pick<MCPHttpConfig, "headers" | "authProvider">): MCPClient;
80
+ /**
81
+ * Connect to the MCP server and discover all available tools.
82
+ *
83
+ * This method is idempotent — calling it when already connected is a no-op.
84
+ * Must be called before {@link getTools}.
85
+ *
86
+ * @throws If the MCP server cannot be reached or the SDK is not installed
87
+ */
88
+ connect(): Promise<void>;
89
+ /**
90
+ * Return all tools discovered from the MCP server as agention-lib Tool instances.
91
+ *
92
+ * Returns an empty array if {@link connect} has not been called yet.
93
+ * The returned tools can be passed directly to any agent via the `tools` config
94
+ * option or {@link BaseAgent.addTools}.
95
+ */
96
+ getTools(): Tool<unknown>[];
97
+ /**
98
+ * Disconnect from the MCP server and release all resources.
99
+ *
100
+ * This method is idempotent — calling it when not connected is a no-op.
101
+ * After disconnecting, {@link getTools} returns an empty array.
102
+ */
103
+ disconnect(): Promise<void>;
104
+ private wrapMcpTool;
105
+ }
106
+ //# sourceMappingURL=MCPClient.d.ts.map
@@ -0,0 +1,264 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.MCPClient = void 0;
37
+ const Tool_1 = require("../tools/Tool");
38
+ /**
39
+ * MCPClient connects to an MCP (Model Context Protocol) server and converts its
40
+ * tools into agention-lib {@link Tool} instances that can be passed to any agent.
41
+ *
42
+ * Supports two transport types:
43
+ * - **stdio** — spawns a local process and communicates over stdin/stdout
44
+ * - **http** — connects to a remote MCP server over Streamable HTTP
45
+ *
46
+ * @requires @modelcontextprotocol/sdk - Install as a peer dependency:
47
+ * ```
48
+ * npm install @modelcontextprotocol/sdk
49
+ * ```
50
+ *
51
+ * @example Stdio (local process)
52
+ * ```typescript
53
+ * import { MCPClient } from "@agentionai/agents";
54
+ * import { ClaudeAgent } from "@agentionai/agents/claude";
55
+ *
56
+ * const mcp = MCPClient.fromStdio({
57
+ * command: "npx",
58
+ * args: ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"],
59
+ * });
60
+ *
61
+ * await mcp.connect();
62
+ * const agent = new ClaudeAgent({
63
+ * id: "file-agent",
64
+ * name: "File Agent",
65
+ * description: "An agent that can work with files",
66
+ * apiKey: process.env.ANTHROPIC_API_KEY!,
67
+ * tools: mcp.getTools(),
68
+ * });
69
+ *
70
+ * const result = await agent.execute("List the files in /tmp");
71
+ * await mcp.disconnect();
72
+ * ```
73
+ *
74
+ * @example HTTP with static API key
75
+ * ```typescript
76
+ * const mcp = MCPClient.fromUrl("https://my-mcp-server.com/mcp", {
77
+ * headers: { Authorization: "Bearer my-api-key" },
78
+ * });
79
+ *
80
+ * await mcp.connect();
81
+ * agent.addTools(mcp.getTools());
82
+ * ```
83
+ *
84
+ * @example HTTP with OAuth
85
+ * ```typescript
86
+ * import type { OAuthClientProvider } from "@modelcontextprotocol/sdk/client/auth.js";
87
+ *
88
+ * const mcp = MCPClient.fromUrl("https://my-mcp-server.com/mcp", {
89
+ * authProvider: myOAuthProvider, // implements OAuthClientProvider
90
+ * });
91
+ * ```
92
+ */
93
+ class MCPClient {
94
+ constructor(transportConfig, options = {}) {
95
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
96
+ this.sdkClient = null;
97
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
98
+ this.sdkTransport = null;
99
+ this._tools = [];
100
+ this.connected = false;
101
+ this.transportConfig = transportConfig;
102
+ this.options = {
103
+ clientName: options.clientName ?? "agention-mcp-client",
104
+ clientVersion: options.clientVersion ?? "1.0.0",
105
+ };
106
+ }
107
+ /**
108
+ * Create an MCPClient that connects to a local MCP server process via stdio.
109
+ *
110
+ * @param config - Command and arguments to spawn the MCP server process
111
+ * @param options - Optional client identification options
112
+ */
113
+ static fromStdio(config, options) {
114
+ return new MCPClient({ type: "stdio", config }, options);
115
+ }
116
+ /**
117
+ * Create an MCPClient that connects to a remote MCP server via HTTP.
118
+ *
119
+ * @param url - Full URL to the MCP endpoint
120
+ * @param options - Optional client options including auth headers or OAuth provider
121
+ */
122
+ static fromUrl(url, options) {
123
+ const config = {
124
+ url,
125
+ headers: options?.headers,
126
+ authProvider: options?.authProvider,
127
+ };
128
+ return new MCPClient({ type: "http", config }, options);
129
+ }
130
+ /**
131
+ * Connect to the MCP server and discover all available tools.
132
+ *
133
+ * This method is idempotent — calling it when already connected is a no-op.
134
+ * Must be called before {@link getTools}.
135
+ *
136
+ * @throws If the MCP server cannot be reached or the SDK is not installed
137
+ */
138
+ async connect() {
139
+ if (this.connected)
140
+ return;
141
+ // Build module paths at runtime so tsc does not attempt to resolve them at
142
+ // compile time. @modelcontextprotocol/sdk is an optional peer dependency and
143
+ // may not be installed on the build host.
144
+ const pkg = "@modelcontextprotocol/sdk";
145
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
146
+ const { Client } = await Promise.resolve(`${`${pkg}/client/index.js`}`).then(s => __importStar(require(s)));
147
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
148
+ const sdkClient = new Client({ name: this.options.clientName, version: this.options.clientVersion }, { capabilities: {} });
149
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
150
+ let transport;
151
+ if (this.transportConfig.type === "stdio") {
152
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
153
+ const { StdioClientTransport } = await Promise.resolve(`${`${pkg}/client/stdio.js`}`).then(s => __importStar(require(s)));
154
+ transport = new StdioClientTransport({
155
+ command: this.transportConfig.config.command,
156
+ args: this.transportConfig.config.args ?? [],
157
+ env: this.transportConfig.config.env,
158
+ });
159
+ }
160
+ else {
161
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
162
+ const { StreamableHTTPClientTransport } = await Promise.resolve(`${`${pkg}/client/streamableHttp.js`}`).then(s => __importStar(require(s)));
163
+ const { url, headers, authProvider } = this.transportConfig.config;
164
+ transport = new StreamableHTTPClientTransport(new URL(url), {
165
+ ...(headers ? { requestInit: { headers } } : {}),
166
+ ...(authProvider ? { authProvider } : {}),
167
+ });
168
+ }
169
+ await sdkClient.connect(transport);
170
+ this.sdkClient = sdkClient;
171
+ this.sdkTransport = transport;
172
+ this.connected = true;
173
+ // Paginate through all tools
174
+ const allMcpTools = [];
175
+ let cursor;
176
+ do {
177
+ const response = await sdkClient.listTools(cursor ? { cursor } : {});
178
+ allMcpTools.push(...response.tools);
179
+ cursor = response.nextCursor;
180
+ } while (cursor);
181
+ this._tools = allMcpTools.map((mcpTool) => this.wrapMcpTool(mcpTool));
182
+ }
183
+ /**
184
+ * Return all tools discovered from the MCP server as agention-lib Tool instances.
185
+ *
186
+ * Returns an empty array if {@link connect} has not been called yet.
187
+ * The returned tools can be passed directly to any agent via the `tools` config
188
+ * option or {@link BaseAgent.addTools}.
189
+ */
190
+ getTools() {
191
+ return this._tools;
192
+ }
193
+ /**
194
+ * Disconnect from the MCP server and release all resources.
195
+ *
196
+ * This method is idempotent — calling it when not connected is a no-op.
197
+ * After disconnecting, {@link getTools} returns an empty array.
198
+ */
199
+ async disconnect() {
200
+ if (!this.connected)
201
+ return;
202
+ try {
203
+ if (this.transportConfig.type === "http" && this.sdkTransport) {
204
+ await this.sdkTransport.terminateSession?.();
205
+ }
206
+ if (this.sdkClient) {
207
+ await this.sdkClient.close();
208
+ }
209
+ }
210
+ finally {
211
+ this.sdkClient = null;
212
+ this.sdkTransport = null;
213
+ this._tools = [];
214
+ this.connected = false;
215
+ }
216
+ }
217
+ wrapMcpTool(mcpTool) {
218
+ const inputSchema = {
219
+ type: "object",
220
+ properties: mcpTool.inputSchema?.properties ?? {},
221
+ required: mcpTool.inputSchema?.required,
222
+ };
223
+ return new Tool_1.Tool({
224
+ name: mcpTool.name,
225
+ description: mcpTool.description ?? mcpTool.name,
226
+ inputSchema,
227
+ execute: async (input) => {
228
+ if (!this.connected || !this.sdkClient) {
229
+ throw new Error(`MCPClient: Cannot execute tool "${mcpTool.name}" — client is not connected`);
230
+ }
231
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
232
+ let result;
233
+ try {
234
+ result = await this.sdkClient.callTool({
235
+ name: mcpTool.name,
236
+ arguments: input,
237
+ });
238
+ }
239
+ catch (error) {
240
+ const message = error instanceof Error ? error.message : String(error);
241
+ throw new Error(`MCPClient: Tool "${mcpTool.name}" execution failed: ${message}`);
242
+ }
243
+ // Extract text content items from MCP result
244
+ if (result?.content && Array.isArray(result.content)) {
245
+ const textItems = result.content
246
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
247
+ .filter((item) => item.type === "text")
248
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
249
+ .map((item) => item.text);
250
+ if (textItems.length > 0) {
251
+ return textItems.length === 1 ? textItems[0] : textItems.join("\n");
252
+ }
253
+ }
254
+ // Fall back to structured content or full JSON serialization
255
+ if (result?.structuredContent !== undefined) {
256
+ return result.structuredContent;
257
+ }
258
+ return JSON.stringify(result ?? null);
259
+ },
260
+ });
261
+ }
262
+ }
263
+ exports.MCPClient = MCPClient;
264
+ //# sourceMappingURL=MCPClient.js.map
@@ -0,0 +1,64 @@
1
+ /**
2
+ * MCP (Model Context Protocol) support for agention-lib.
3
+ *
4
+ * Connects to any MCP server — local stdio processes or remote HTTP endpoints —
5
+ * and exposes their tools as agention-lib {@link Tool} instances compatible with
6
+ * all agent types (ClaudeAgent, OpenAiAgent, MistralAgent, GeminiAgent).
7
+ *
8
+ * @requires @modelcontextprotocol/sdk - Optional peer dependency, install when needed:
9
+ * ```
10
+ * npm install @modelcontextprotocol/sdk
11
+ * ```
12
+ *
13
+ * @example Stdio (local process)
14
+ * ```typescript
15
+ * import { MCPClient, ClaudeAgent } from "@agentionai/agents";
16
+ *
17
+ * const mcp = MCPClient.fromStdio({
18
+ * command: "npx",
19
+ * args: ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"],
20
+ * });
21
+ *
22
+ * await mcp.connect();
23
+ *
24
+ * const agent = new ClaudeAgent({
25
+ * id: "file-agent",
26
+ * name: "File Agent",
27
+ * description: "An agent that can work with files",
28
+ * apiKey: process.env.ANTHROPIC_API_KEY!,
29
+ * tools: mcp.getTools(),
30
+ * });
31
+ *
32
+ * const result = await agent.execute("List the files in /tmp");
33
+ * await mcp.disconnect();
34
+ * ```
35
+ *
36
+ * @example HTTP with static API key
37
+ * ```typescript
38
+ * import { MCPClient } from "@agentionai/agents";
39
+ *
40
+ * const mcp = MCPClient.fromUrl("https://my-mcp-server.com/mcp", {
41
+ * headers: { Authorization: "Bearer my-api-key" },
42
+ * });
43
+ *
44
+ * await mcp.connect();
45
+ * agent.addTools(mcp.getTools());
46
+ * await mcp.disconnect();
47
+ * ```
48
+ *
49
+ * @example HTTP with OAuth
50
+ * ```typescript
51
+ * import { MCPClient } from "@agentionai/agents";
52
+ * import type { OAuthClientProvider } from "@modelcontextprotocol/sdk/client/auth.js";
53
+ *
54
+ * // Implement OAuthClientProvider from the MCP SDK
55
+ * const myOAuthProvider: OAuthClientProvider = { ... };
56
+ *
57
+ * const mcp = MCPClient.fromUrl("https://my-mcp-server.com/mcp", {
58
+ * authProvider: myOAuthProvider,
59
+ * });
60
+ * ```
61
+ */
62
+ export { MCPClient } from "./MCPClient";
63
+ export type { MCPStdioConfig, MCPHttpConfig, MCPClientOptions } from "./types";
64
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,67 @@
1
+ "use strict";
2
+ /**
3
+ * MCP (Model Context Protocol) support for agention-lib.
4
+ *
5
+ * Connects to any MCP server — local stdio processes or remote HTTP endpoints —
6
+ * and exposes their tools as agention-lib {@link Tool} instances compatible with
7
+ * all agent types (ClaudeAgent, OpenAiAgent, MistralAgent, GeminiAgent).
8
+ *
9
+ * @requires @modelcontextprotocol/sdk - Optional peer dependency, install when needed:
10
+ * ```
11
+ * npm install @modelcontextprotocol/sdk
12
+ * ```
13
+ *
14
+ * @example Stdio (local process)
15
+ * ```typescript
16
+ * import { MCPClient, ClaudeAgent } from "@agentionai/agents";
17
+ *
18
+ * const mcp = MCPClient.fromStdio({
19
+ * command: "npx",
20
+ * args: ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"],
21
+ * });
22
+ *
23
+ * await mcp.connect();
24
+ *
25
+ * const agent = new ClaudeAgent({
26
+ * id: "file-agent",
27
+ * name: "File Agent",
28
+ * description: "An agent that can work with files",
29
+ * apiKey: process.env.ANTHROPIC_API_KEY!,
30
+ * tools: mcp.getTools(),
31
+ * });
32
+ *
33
+ * const result = await agent.execute("List the files in /tmp");
34
+ * await mcp.disconnect();
35
+ * ```
36
+ *
37
+ * @example HTTP with static API key
38
+ * ```typescript
39
+ * import { MCPClient } from "@agentionai/agents";
40
+ *
41
+ * const mcp = MCPClient.fromUrl("https://my-mcp-server.com/mcp", {
42
+ * headers: { Authorization: "Bearer my-api-key" },
43
+ * });
44
+ *
45
+ * await mcp.connect();
46
+ * agent.addTools(mcp.getTools());
47
+ * await mcp.disconnect();
48
+ * ```
49
+ *
50
+ * @example HTTP with OAuth
51
+ * ```typescript
52
+ * import { MCPClient } from "@agentionai/agents";
53
+ * import type { OAuthClientProvider } from "@modelcontextprotocol/sdk/client/auth.js";
54
+ *
55
+ * // Implement OAuthClientProvider from the MCP SDK
56
+ * const myOAuthProvider: OAuthClientProvider = { ... };
57
+ *
58
+ * const mcp = MCPClient.fromUrl("https://my-mcp-server.com/mcp", {
59
+ * authProvider: myOAuthProvider,
60
+ * });
61
+ * ```
62
+ */
63
+ Object.defineProperty(exports, "__esModule", { value: true });
64
+ exports.MCPClient = void 0;
65
+ var MCPClient_1 = require("./MCPClient");
66
+ Object.defineProperty(exports, "MCPClient", { enumerable: true, get: function () { return MCPClient_1.MCPClient; } });
67
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Configuration for connecting to an MCP server via stdio (local process).
3
+ */
4
+ export interface MCPStdioConfig {
5
+ /** The command to spawn (e.g. "node", "python", "npx") */
6
+ command: string;
7
+ /** Arguments to pass to the command */
8
+ args?: string[];
9
+ /** Environment variables for the spawned process */
10
+ env?: Record<string, string>;
11
+ }
12
+ /**
13
+ * Configuration for connecting to an MCP server via HTTP (remote URL).
14
+ */
15
+ export interface MCPHttpConfig {
16
+ /** Full URL to the MCP endpoint */
17
+ url: string;
18
+ /** Optional HTTP headers for static auth tokens or API keys */
19
+ headers?: Record<string, string>;
20
+ /**
21
+ * Optional OAuth provider for dynamic authorization.
22
+ * Implement the `OAuthClientProvider` interface from `@modelcontextprotocol/sdk`
23
+ * and pass it here for OAuth 2.0 + PKCE flows.
24
+ *
25
+ * @example
26
+ * ```typescript
27
+ * import { OAuthClientProvider } from "@modelcontextprotocol/sdk/client/auth.js";
28
+ *
29
+ * const mcp = MCPClient.fromUrl("https://my-server.com/mcp", {
30
+ * authProvider: myOAuthProvider,
31
+ * });
32
+ * ```
33
+ */
34
+ authProvider?: unknown;
35
+ }
36
+ /**
37
+ * Options shared by all MCPClient connection types.
38
+ */
39
+ export interface MCPClientOptions {
40
+ /**
41
+ * Name to identify this MCP client (sent during SDK handshake).
42
+ * @default "agention-mcp-client"
43
+ */
44
+ clientName?: string;
45
+ /**
46
+ * Version string for the MCP client.
47
+ * @default "1.0.0"
48
+ */
49
+ clientVersion?: string;
50
+ }
51
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=types.js.map
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@agentionai/agents",
3
3
  "author": "Laurent Zuijdwijk",
4
- "version": "0.6.1",
4
+ "version": "0.7.0",
5
5
  "description": "Agent Library",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",
@@ -110,6 +110,7 @@
110
110
  "@google/generative-ai": "^0.24.1",
111
111
  "@lancedb/lancedb": "^0.23.0",
112
112
  "@mistralai/mistralai": "^1.13.0",
113
+ "@modelcontextprotocol/sdk": "^1.26.0",
113
114
  "apache-arrow": "^18.0.0",
114
115
  "openai": "^6.16.0",
115
116
  "voyageai": "^0.0.3"
@@ -130,6 +131,9 @@
130
131
  "@anthropic-ai/sdk": {
131
132
  "optional": true
132
133
  },
134
+ "@modelcontextprotocol/sdk": {
135
+ "optional": true
136
+ },
133
137
  "openai": {
134
138
  "optional": true
135
139
  },