@mimik/agent-kit 1.0.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.
package/README.md ADDED
@@ -0,0 +1,718 @@
1
+ # agent-kit: MCP Agent Library
2
+
3
+ A powerful wrapper library for building intelligent agents that interact with multiple Model Context Protocol (MCP) servers, providing streaming capabilities, tool orchestration, and comprehensive security controls.
4
+
5
+ ## Table of Contents
6
+
7
+ - [Installation](#installation)
8
+ - [Quick Start](#quick-start)
9
+ - [Core Concepts](#core-concepts)
10
+ - [Configuration](#configuration)
11
+ - [API Reference](#api-reference)
12
+ - [Streaming Events](#streaming-events)
13
+ - [Security Features](#security-features)
14
+ - [Examples](#examples)
15
+ - [Best Practices](#best-practices)
16
+ - [Error Handling](#error-handling)
17
+
18
+ ## Installation
19
+
20
+ ```bash
21
+ npm install @mimik/agent-kit
22
+ ```
23
+
24
+ ```javascript
25
+ const { Agent } = require('@mimik/agent-kit');
26
+ ```
27
+
28
+ ## Quick Start
29
+
30
+ ```javascript
31
+ const { Agent } = require('@mimik/agent-kit');
32
+
33
+ // Create an agent instance
34
+ const agent = new Agent({
35
+ name: 'My Assistant',
36
+ instructions: 'You are a helpful assistant with access to MCP tools.',
37
+ llm: {
38
+ model: 'lmstudio-community/Qwen3-4B-GGUF',
39
+ temperature: 0.1
40
+ },
41
+ mcpEndpoints: ['http://localhost:3000/mcp'],
42
+ httpClient: global.http
43
+ });
44
+
45
+ // Initialize the agent
46
+ await agent.initialize();
47
+
48
+ // Run a conversation (always returns a streaming iterator)
49
+ const streamIterator = await agent.run('find devices around me');
50
+
51
+ for await (const event of streamIterator) {
52
+ if (event.type === 'content_delta') {
53
+ sendSSE(event.data.content);
54
+ } else if (event.type === 'conversation_complete') {
55
+ console.log('\nFinal result:', event.data.finalOutput);
56
+ break;
57
+ }
58
+ }
59
+ ```
60
+
61
+ ## Core Concepts
62
+
63
+ ### Agent
64
+ The main orchestrator that connects to multiple MCP servers, routes tool calls, and manages conversation flow with automatic streaming execution.
65
+
66
+ ### MCP Servers
67
+ Multiple Model Context Protocol servers that provide tools, resources, and capabilities. The agent automatically routes tool calls to the appropriate server.
68
+
69
+ ### Streaming Execution
70
+ All agent conversations use real-time streaming for immediate feedback and responsive user experiences.
71
+
72
+ ### Tool Security
73
+ Multi-layered security with server-level tool whitelisting and runtime tool approval callbacks.
74
+
75
+ ## Configuration
76
+
77
+ ### Basic Configuration
78
+
79
+ ```javascript
80
+ const agent = new Agent({
81
+ name: 'My Agent', // Agent name for logging
82
+ instructions: 'System prompt...', // System instructions
83
+ maxIterations: 5, // Max conversation loops
84
+
85
+ llm: {
86
+ model: 'lmstudio-community/Qwen3-4B-GGUF',
87
+ temperature: 0.1,
88
+ max_tokens: 2048,
89
+ endpoint: 'https://api.anthropic.com/v1/messages',
90
+ apiKey: 'your-api-key'
91
+ },
92
+
93
+ mcpEndpoints: ['http://localhost:3000/mcp'],
94
+ httpClient: global.http
95
+ });
96
+ ```
97
+
98
+ ### Advanced Configuration with Security
99
+
100
+ ```javascript
101
+ const agent = new Agent({
102
+ name: 'Secure Assistant',
103
+ instructions: 'Help users safely with controlled tool access.',
104
+ maxIterations: 5,
105
+
106
+ llm: {
107
+ model: 'lmstudio-community/Qwen3-4B-GGUF',
108
+ temperature: 0.1,
109
+ max_tokens: 4096,
110
+ no_think: false // Disable thinking mode
111
+ },
112
+
113
+ mcpEndpoints: [
114
+ // Simple endpoint - all tools allowed
115
+ 'http://localhost:3000/mcp',
116
+
117
+ // Endpoint with tool whitelist
118
+ {
119
+ url: 'http://localhost:3001/mcp',
120
+ apiKey: 'server-api-key',
121
+ options: {
122
+ toolWhitelist: ['gitStatus', 'gitLog', 'gitDiff'], // Only these tools
123
+ whitelistMode: 'include' // Include mode
124
+ }
125
+ },
126
+
127
+ // Endpoint blocking dangerous tools
128
+ {
129
+ url: 'http://localhost:3002/mcp',
130
+ options: {
131
+ toolWhitelist: ['deleteFile', 'formatDisk'], // Block these tools
132
+ whitelistMode: 'exclude' // Exclude mode
133
+ }
134
+ }
135
+ ],
136
+
137
+ httpClient: global.http
138
+ });
139
+ ```
140
+
141
+ ### Configuration Options
142
+
143
+ #### Top-Level Options
144
+ - `name` (string): Agent name for logging (default: 'MCP Assistant')
145
+ - `instructions` (string): System prompt (default: 'You are a helpful assistant...')
146
+ - `maxIterations` (number): Maximum conversation loops (default: 5)
147
+ - `mcpEndpoints` (array): MCP server configurations
148
+ - `httpClient` (object): HTTP client instance
149
+
150
+ #### LLM Configuration
151
+ - `model` (string): LLM model name
152
+ - `temperature` (number): Sampling temperature (0.0-1.0)
153
+ - `max_tokens` (number): Maximum tokens per response
154
+ - `endpoint` (string): LLM API endpoint
155
+ - `apiKey` (string): LLM API key
156
+ - `no_think` (boolean): Append '/no_think' to prompts for direct responses
157
+
158
+ #### MCP Endpoint Configuration
159
+ - **Simple**: `'http://localhost:3000/mcp'`
160
+ - **Advanced**: Object with `url`, `apiKey`, and `options`
161
+
162
+ #### Tool Whitelist Options
163
+ - `toolWhitelist` (array): Tool names to include/exclude
164
+ - `whitelistMode` (string): `'include'` (only listed tools) or `'exclude'` (all except listed)
165
+
166
+ ## API Reference
167
+
168
+ ### Agent Class
169
+
170
+ #### Constructor
171
+ ```javascript
172
+ new Agent(config)
173
+ ```
174
+
175
+ #### Methods
176
+
177
+ ##### initialize()
178
+ Connects to all MCP servers and loads available tools.
179
+
180
+ ```javascript
181
+ await agent.initialize();
182
+ ```
183
+
184
+ ##### run(message, options)
185
+ Executes a conversation with streaming output.
186
+
187
+ **Parameters:**
188
+ - `message` (string): User message to process
189
+ - `options` (object): Configuration options
190
+ - `toolApproval` (function): Tool approval callback
191
+
192
+ **Returns:** AsyncIterator - Streaming events
193
+
194
+ ```javascript
195
+ const streamIterator = await agent.run('find devices', {
196
+ toolApproval: async (toolCalls) => ({
197
+ stopAfterExecution: false,
198
+ approvals: [true, false, true] // Approve, deny, approve
199
+ })
200
+ });
201
+ ```
202
+
203
+ ### Tool Approval System
204
+
205
+ #### Callback Function
206
+ ```javascript
207
+ toolApproval: async (toolCalls) => {
208
+ // toolCalls = [{ id, type, function: { name, arguments } }, ...]
209
+
210
+ return {
211
+ stopAfterExecution: false, // Continue after execution
212
+ approvals: [
213
+ true, // Simple approval
214
+ false, // Simple denial
215
+ { approve: true }, // Explicit approval
216
+ { approve: false, reason: 'Not safe' } // Denial with reason
217
+ ]
218
+ };
219
+ }
220
+ ```
221
+
222
+ #### Response Format
223
+ - `stopAfterExecution` (boolean): End conversation after tool execution
224
+ - `approvals` (array): Approval decision for each tool call
225
+
226
+ #### Approval Options
227
+ - `true` - Approve the tool
228
+ - `false` - Deny the tool (default reason)
229
+ - `{ approve: true }` - Explicit approval
230
+ - `{ approve: false, reason: 'Custom reason' }` - Denial with custom reason
231
+
232
+ ## Streaming Events
233
+
234
+ All agent conversations emit real-time events for responsive user experiences.
235
+
236
+ ### Event Types
237
+
238
+ #### iteration_start
239
+ Start of each conversation loop
240
+ ```javascript
241
+ {
242
+ type: 'iteration_start',
243
+ data: {
244
+ iteration: 1,
245
+ messages: [/* conversation history */]
246
+ }
247
+ }
248
+ ```
249
+
250
+ #### content_delta
251
+ Assistant text content updates
252
+ ```javascript
253
+ {
254
+ type: 'content_delta',
255
+ data: {
256
+ content: "I'll help you find devices..."
257
+ }
258
+ }
259
+ ```
260
+
261
+ #### tool_calls_detected
262
+ Complete tool calls ready for execution
263
+ ```javascript
264
+ {
265
+ type: 'tool_calls_detected',
266
+ data: {
267
+ toolCalls: [{
268
+ id: "call_123",
269
+ type: "function",
270
+ function: { name: "discoverLocal", arguments: "{}" }
271
+ }]
272
+ }
273
+ }
274
+ ```
275
+
276
+ #### tool_approval_result
277
+ Results of tool approval decisions
278
+ ```javascript
279
+ {
280
+ type: 'tool_approval_result',
281
+ data: {
282
+ approvalResult: {
283
+ stopAfterExecution: false,
284
+ approvals: [true, { approve: false, reason: 'Not safe' }]
285
+ }
286
+ }
287
+ }
288
+ ```
289
+
290
+ #### tool_results
291
+ Results from tool execution
292
+ ```javascript
293
+ {
294
+ type: 'tool_results',
295
+ data: {
296
+ results: [{
297
+ role: "tool",
298
+ tool_call_id: "call_123",
299
+ name: "discoverLocal",
300
+ content: JSON.stringify([/* results */])
301
+ }]
302
+ }
303
+ }
304
+ ```
305
+
306
+ #### conversation_complete
307
+ Final conversation result
308
+ ```javascript
309
+ {
310
+ type: 'conversation_complete',
311
+ data: {
312
+ finalOutput: "I found 2 devices around you...",
313
+ messages: [/* complete history */],
314
+ iterations: 2,
315
+ stoppedAfterToolExecution: false
316
+ }
317
+ }
318
+ ```
319
+
320
+ ## Security Features
321
+
322
+ ### Tool Whitelisting
323
+
324
+ Control which tools are available from each MCP server.
325
+
326
+ #### Include Mode (Default)
327
+ Only allow specific tools:
328
+ ```javascript
329
+ {
330
+ url: 'http://localhost:3001/mcp',
331
+ options: {
332
+ toolWhitelist: ['readFile', 'listDirectory'],
333
+ whitelistMode: 'include'
334
+ }
335
+ }
336
+ ```
337
+
338
+ #### Exclude Mode
339
+ Block specific dangerous tools:
340
+ ```javascript
341
+ {
342
+ url: 'http://localhost:3002/mcp',
343
+ options: {
344
+ toolWhitelist: ['deleteFile', 'formatDisk'],
345
+ whitelistMode: 'exclude'
346
+ }
347
+ }
348
+ ```
349
+
350
+ ### Runtime Tool Approval
351
+
352
+ Additional security layer with approval callbacks:
353
+ ```javascript
354
+ toolApproval: async (toolCalls) => ({
355
+ stopAfterExecution: false,
356
+ approvals: toolCalls.map(tool => {
357
+ if (tool.function.name.includes('delete')) {
358
+ return { approve: false, reason: 'Destructive operations not allowed' };
359
+ }
360
+ return true;
361
+ })
362
+ })
363
+ ```
364
+
365
+ ### Security Benefits
366
+ - **Principle of Least Privilege**: Only expose necessary tools
367
+ - **Defense in Depth**: Multiple security layers
368
+ - **Server Isolation**: Different policies per MCP server
369
+ - **Runtime Protection**: Dynamic approval decisions
370
+
371
+ ## Examples
372
+
373
+ ### Basic Usage
374
+
375
+ ```javascript
376
+ const agent = new Agent({
377
+ name: 'Basic Assistant',
378
+ llm: { model: 'lmstudio-community/Qwen3-4B-GGUF', temperature: 0.1 },
379
+ mcpEndpoints: ['http://localhost:3000/mcp'],
380
+ httpClient: global.http
381
+ });
382
+
383
+ await agent.initialize();
384
+
385
+ const streamIterator = await agent.run('help me find local devices');
386
+
387
+ for await (const event of streamIterator) {
388
+ switch (event.type) {
389
+ case 'content_delta':
390
+ sendSSE(event.data.content);
391
+ break;
392
+ case 'conversation_complete':
393
+ console.log('\n✅ Done:', event.data.finalOutput);
394
+ return;
395
+ }
396
+ }
397
+ ```
398
+
399
+ ### Multi-Agent with Security
400
+
401
+ ```javascript
402
+ const agent = new Agent({
403
+ name: 'Secure Multi-Tool Agent',
404
+ instructions: 'Help users with controlled access to various tools.',
405
+ llm: {
406
+ model: 'lmstudio-community/Qwen3-4B-GGUF',
407
+ temperature: 0.2,
408
+ max_tokens: 4096
409
+ },
410
+ mcpEndpoints: [
411
+ {
412
+ url: 'http://localhost:3000/mcp', // Network tools
413
+ options: {
414
+ toolWhitelist: ['discoverLocal', 'pingDevice'],
415
+ whitelistMode: 'include'
416
+ }
417
+ },
418
+ {
419
+ url: 'http://localhost:3001/mcp', // Git tools
420
+ options: {
421
+ toolWhitelist: ['gitStatus', 'gitLog', 'gitDiff'],
422
+ whitelistMode: 'include'
423
+ }
424
+ },
425
+ {
426
+ url: 'http://localhost:3002/mcp', // File system (safe)
427
+ options: {
428
+ toolWhitelist: ['deleteFile', 'formatDisk'],
429
+ whitelistMode: 'exclude'
430
+ }
431
+ }
432
+ ],
433
+ httpClient: global.http
434
+ });
435
+
436
+ await agent.initialize();
437
+
438
+ const streamIterator = await agent.run('scan network and check git status', {
439
+ toolApproval: async (toolCalls) => ({
440
+ stopAfterExecution: false,
441
+ approvals: toolCalls.map(tool => {
442
+ // Extra safety check
443
+ if (tool.function.name.toLowerCase().includes('format')) {
444
+ return { approve: false, reason: 'Disk formatting not allowed' };
445
+ }
446
+ return true;
447
+ })
448
+ })
449
+ });
450
+
451
+ for await (const event of streamIterator) {
452
+ switch (event.type) {
453
+ case 'content_delta':
454
+ sendSSE(event.data.content);
455
+ break;
456
+ case 'tool_calls_detected':
457
+ console.log('\n🔧 Executing:',
458
+ event.data.toolCalls.map(tc => tc.function.name).join(', '));
459
+ break;
460
+ case 'conversation_complete':
461
+ console.log('\n\n📋 Final:', event.data.finalOutput);
462
+ break;
463
+ }
464
+ }
465
+ ```
466
+
467
+ ### No-Think Mode
468
+
469
+ For direct responses without reasoning display:
470
+ ```javascript
471
+ const agent = new Agent({
472
+ name: 'Direct Assistant',
473
+ llm: {
474
+ model: 'lmstudio-community/Qwen3-4B-GGUF',
475
+ no_think: true // Enables direct responses
476
+ },
477
+ mcpEndpoints: ['http://localhost:3000/mcp'],
478
+ httpClient: global.http
479
+ });
480
+
481
+ // Prompts sent to LLM will include '/no_think' suffix
482
+ const streamIterator = await agent.run('What time is it?');
483
+ ```
484
+
485
+ ### Web API Integration
486
+
487
+ ```javascript
488
+ app.post('/chat', async (req, res) => {
489
+ const agent = new Agent({
490
+ name: 'API Assistant',
491
+ llm: {
492
+ model: 'lmstudio-community/Qwen3-4B-GGUF',
493
+ temperature: 0.1,
494
+ no_think: true
495
+ },
496
+ mcpEndpoints: [{
497
+ url: 'http://localhost:3000/mcp',
498
+ options: {
499
+ toolWhitelist: ['readFile', 'listDirectory'], // Read-only for web
500
+ whitelistMode: 'include'
501
+ }
502
+ }],
503
+ httpClient: global.http
504
+ });
505
+
506
+ await agent.initialize();
507
+
508
+ res.setHeader('Content-Type', 'text/event-stream');
509
+ res.setHeader('Cache-Control', 'no-cache');
510
+
511
+ try {
512
+ const streamIterator = await agent.run(req.body.message, {
513
+ toolApproval: async (toolCalls) => ({
514
+ stopAfterExecution: false,
515
+ approvals: toolCalls.map(tool => {
516
+ // Block write operations via web
517
+ if (['writeFile', 'deleteFile'].includes(tool.function.name)) {
518
+ return { approve: false, reason: 'Write operations not allowed via web' };
519
+ }
520
+ return true;
521
+ })
522
+ })
523
+ });
524
+
525
+ for await (const event of streamIterator) {
526
+ res.write(`data: ${JSON.stringify(event)}\n\n`);
527
+
528
+ if (event.type === 'conversation_complete') {
529
+ break;
530
+ }
531
+ }
532
+
533
+ res.end();
534
+ } catch (error) {
535
+ res.write(`data: ${JSON.stringify({ error: error.message })}\n\n`);
536
+ res.end();
537
+ }
538
+ });
539
+ ```
540
+
541
+ ### Collecting Final Results
542
+
543
+ If you need just the final result without processing events:
544
+ ```javascript
545
+ const streamIterator = await agent.run('find devices around me');
546
+ let finalResult = null;
547
+
548
+ for await (const event of streamIterator) {
549
+ if (event.type === 'conversation_complete') {
550
+ finalResult = event.data;
551
+ break;
552
+ }
553
+ }
554
+
555
+ console.log('Final output:', finalResult.finalOutput);
556
+ console.log('Total iterations:', finalResult.iterations);
557
+ ```
558
+
559
+ ## Best Practices
560
+
561
+ ### 1. Always Handle Streaming
562
+ Since `run()` always returns a streaming iterator, process events appropriately:
563
+ ```javascript
564
+ // Good - handle all relevant events
565
+ for await (const event of streamIterator) {
566
+ switch (event.type) {
567
+ case 'content_delta':
568
+ displayContent(event.data.content);
569
+ break;
570
+ case 'tool_calls_detected':
571
+ showToolExecution(event.data.toolCalls);
572
+ break;
573
+ case 'conversation_complete':
574
+ return event.data.finalOutput;
575
+ }
576
+ }
577
+
578
+ // Avoid - only handling one event type
579
+ ```
580
+
581
+ ### 2. Layer Security Controls
582
+ Combine whitelisting with runtime approval:
583
+ ```javascript
584
+ // Server-level whitelist
585
+ {
586
+ url: 'http://localhost:3000/mcp',
587
+ options: {
588
+ toolWhitelist: ['readFile', 'writeFile', 'deleteFile'],
589
+ whitelistMode: 'include'
590
+ }
591
+ }
592
+
593
+ // Runtime approval for additional safety
594
+ toolApproval: async (toolCalls) => ({
595
+ approvals: toolCalls.map(tool => {
596
+ if (tool.function.name === 'deleteFile') {
597
+ return { approve: false, reason: 'Delete operations require manual approval' };
598
+ }
599
+ return true;
600
+ })
601
+ })
602
+ ```
603
+
604
+ ### 3. Organize Tools by Domain
605
+ Use multiple MCP servers for different tool categories:
606
+ ```javascript
607
+ mcpEndpoints: [
608
+ 'http://localhost:3000/mcp', // Network tools
609
+ 'http://localhost:3001/mcp', // File system tools
610
+ 'http://localhost:3002/mcp', // Git tools
611
+ 'http://localhost:3003/mcp' // System tools
612
+ ]
613
+ ```
614
+
615
+ ### 4. Set Appropriate Limits
616
+ Prevent infinite loops while allowing complex tasks:
617
+ ```javascript
618
+ {
619
+ maxIterations: 10, // Allow complex multi-step tasks
620
+ llm: {
621
+ max_tokens: 4096, // Sufficient for detailed responses
622
+ temperature: 0.1 // Consistent behavior
623
+ }
624
+ }
625
+ ```
626
+
627
+ ### 5. Use No-Think Mode Appropriately
628
+ Enable for more direct responses when reasoning isn't needed:
629
+ ```javascript
630
+ // For APIs or when you want concise responses
631
+ llm: { no_think: true }
632
+
633
+ // For interactive assistants where reasoning helps users
634
+ llm: { no_think: false }
635
+ ```
636
+
637
+ ### 6. Handle Errors Gracefully
638
+ Always wrap agent operations in try-catch:
639
+ ```javascript
640
+ try {
641
+ const streamIterator = await agent.run(userMessage);
642
+ // Process stream...
643
+ } catch (error) {
644
+ console.error('Agent error:', error.message);
645
+ // Handle error appropriately
646
+ }
647
+ ```
648
+
649
+ ## Error Handling
650
+
651
+ ### Common Error Types
652
+
653
+ #### Connection Errors
654
+ ```javascript
655
+ // Server unavailable
656
+ try {
657
+ await agent.initialize();
658
+ } catch (error) {
659
+ console.error('Failed to connect to MCP servers:', error.message);
660
+ }
661
+ ```
662
+
663
+ #### Tool Execution Errors
664
+ Tool errors are returned in tool results, conversation continues:
665
+ ```javascript
666
+ {
667
+ type: 'tool_results',
668
+ data: {
669
+ results: [{
670
+ role: "tool",
671
+ tool_call_id: "call_123",
672
+ name: "failingTool",
673
+ content: "Error: Tool execution failed"
674
+ }]
675
+ }
676
+ }
677
+ ```
678
+
679
+ #### Validation Errors
680
+ Invalid configurations throw errors during initialization:
681
+ ```javascript
682
+ // Invalid endpoint format
683
+ mcpEndpoints: ['invalid-url'] // Throws error
684
+
685
+ // Missing required HTTP client
686
+ httpClient: undefined // Throws error
687
+ ```
688
+
689
+ #### LLM Errors
690
+ LLM failures are propagated to the caller:
691
+ ```javascript
692
+ try {
693
+ const streamIterator = await agent.run('test message');
694
+ } catch (error) {
695
+ if (error.message.includes('API key')) {
696
+ console.error('LLM authentication failed');
697
+ }
698
+ }
699
+ ```
700
+
701
+ ### Error Recovery Strategies
702
+
703
+ 1. **Server Failures**: Agent continues with available servers
704
+ 2. **Tool Failures**: Returned as error messages, conversation continues
705
+ 3. **Approval Callback Errors**: Defaults to denying all tools for safety
706
+ 4. **Parsing Errors**: Logged and skipped, processing continues
707
+
708
+ ## Performance Considerations
709
+
710
+ - **Parallel Initialization**: All MCP servers connect concurrently
711
+ - **Efficient Tool Routing**: O(1) lookup for tool-to-server mapping
712
+ - **Streaming**: Real-time events with minimal buffering
713
+ - **Memory Management**: Conversation history accumulates; consider limits for long conversations
714
+ - **No-Think Mode**: Reduces response time and token usage when appropriate
715
+
716
+ ---
717
+
718
+ **Need help?** Check the examples above or refer to the MCP Kit documentation for server-side tool development.
package/package.json ADDED
@@ -0,0 +1,11 @@
1
+ {
2
+ "name": "@mimik/agent-kit",
3
+ "version": "1.0.0",
4
+ "main": "./src/index.js",
5
+ "scripts": {
6
+
7
+ },
8
+ "author": "mimik",
9
+ "license": "ISC",
10
+ "description": "A powerful wrapper library for building intelligent agents that interact with multiple Model Context Protocol (MCP) servers, providing streaming capabilities, tool orchestration, and comprehensive security controls."
11
+ }