converse-mcp-server 2.22.4 โ†’ 2.22.5

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,552 +1,552 @@
1
- # Converse MCP Server - Architecture Overview
2
-
3
- ## ๐Ÿ—๏ธ System Architecture
4
-
5
- The Converse MCP Server follows a **functional, modular architecture** designed for simplicity, maintainability, and performance. It implements the Model Context Protocol (MCP) to provide AI capabilities through multiple providers.
6
-
7
- ## ๐Ÿ“ Project Structure
8
-
9
- ```
10
- src/
11
- โ”œโ”€โ”€ index.js # Main entry point & MCP server setup
12
- โ”œโ”€โ”€ config.js # Configuration and environment management
13
- โ”œโ”€โ”€ systemPrompts.js # System prompts for tools
14
- โ”œโ”€โ”€ providers/ # AI provider implementations
15
- โ”‚ โ”œโ”€โ”€ registry.js # Provider registry and management
16
- โ”‚ โ”œโ”€โ”€ openai.js # OpenAI provider implementation
17
- โ”‚ โ”œโ”€โ”€ google.js # Google/Gemini provider implementation
18
- โ”‚ โ””โ”€โ”€ xai.js # X.AI/Grok provider implementation
19
- โ”œโ”€โ”€ tools/ # MCP tool implementations
20
- โ”‚ โ”œโ”€โ”€ chat.js # Single-provider chat tool
21
- โ”‚ โ””โ”€โ”€ consensus.js # Multi-provider consensus tool
22
- โ”œโ”€โ”€ utils/ # Utility functions
23
- โ”‚ โ”œโ”€โ”€ logger.js # Structured logging
24
- โ”‚ โ”œโ”€โ”€ context.js # File and image processing
25
- โ”‚ โ”œโ”€โ”€ continuation.js # Conversation persistence
26
- โ”‚ โ””โ”€โ”€ validators.js # Input validation
27
- bin/
28
- โ”œโ”€โ”€ converse.js # CLI entry point for npx execution
29
- docs/ # Documentation
30
- tests/ # Test suites
31
- ```
32
-
33
- ## ๐Ÿ”„ Core Design Principles
34
-
35
- ### 1. Functional Programming
36
- - **No Classes**: Pure functions and modules only
37
- - **Immutable Data**: Avoid state mutations where possible
38
- - **Composable Functions**: Small, focused, reusable functions
39
- - **Error Boundaries**: Explicit error handling at module boundaries
40
-
41
- ### 2. Provider Abstraction
42
- - **Unified Interface**: All providers implement consistent API
43
- - **Auto-Discovery**: Providers register themselves dynamically
44
- - **Graceful Degradation**: System works with any subset of providers
45
- - **Parallel Execution**: Multiple providers can run simultaneously
46
-
47
- ### 3. Tool Architecture
48
- - **Minimal Interface**: Tools expose simple, focused functionality
49
- - **Context Processing**: Standardized file and image handling
50
- - **Continuation Support**: Persistent conversation management
51
- - **Parameter Validation**: Comprehensive input validation
52
-
53
- ## ๐Ÿ”Œ MCP Integration Layer
54
-
55
- ### Server Setup
56
-
57
- **HTTP Transport (Default):**
58
- ```javascript
59
- // index.js - HTTP transport setup
60
- import { Server } from '@modelcontextprotocol/sdk/server/index.js';
61
- import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
62
-
63
- const server = new Server(
64
- { name: 'converse-mcp-server', version: '1.0.0' },
65
- { capabilities: { tools: {} } }
66
- );
67
-
68
- // HTTP transport on port 3157 (default)
69
- const httpTransport = new StreamableHTTPServerTransport({
70
- host: 'localhost',
71
- port: 3157
72
- });
73
- ```
74
-
75
- **Stdio Transport (Legacy):**
76
- ```javascript
77
- // Alternative stdio transport
78
- import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
79
-
80
- const transport = new StdioServerTransport();
81
- await server.connect(transport);
82
- ```
83
-
84
- **Transport Selection:**
85
- - **HTTP**: Default, better for development and debugging
86
- - **Stdio**: Use `--transport=stdio` or `MCP_TRANSPORT=stdio`
87
-
88
- ### Tool Registration
89
- ```javascript
90
- // Dynamic tool registration
91
- server.setRequestHandler(CallToolRequestSchema, async (request) => {
92
- const { name, arguments: args } = request.params;
93
-
94
- switch (name) {
95
- case 'chat':
96
- return await chatTool(args);
97
- case 'consensus':
98
- return await consensusTool(args);
99
- default:
100
- throw new McpError(ErrorCode.MethodNotFound, `Tool not found: ${name}`);
101
- }
102
- });
103
- ```
104
-
105
- ## ๐Ÿค– Provider System
106
-
107
- ### Provider Registry Pattern
108
- ```javascript
109
- // providers/registry.js
110
- const providers = new Map();
111
-
112
- export function registerProvider(name, implementation) {
113
- if (implementation.isAvailable()) {
114
- providers.set(name, implementation);
115
- }
116
- }
117
-
118
- export function getProvider(name) {
119
- return providers.get(name);
120
- }
121
-
122
- export function getAvailableProviders() {
123
- return Array.from(providers.keys());
124
- }
125
- ```
126
-
127
- ### Provider Implementation Contract
128
- ```javascript
129
- // Each provider must implement:
130
- export const providerImplementation = {
131
- // Check if provider is configured and available
132
- isAvailable: () => Boolean(process.env.API_KEY),
133
-
134
- // Get supported models
135
- getSupportedModels: () => ['model1', 'model2'],
136
-
137
- // Main chat completion method
138
- chatCompletion: async (messages, options) => {
139
- // Implementation details...
140
- return {
141
- content: 'Response text',
142
- usage: { input_tokens: 100, output_tokens: 50 }
143
- };
144
- },
145
-
146
- // Provider name for logging/tracking
147
- name: 'provider-name'
148
- };
149
- ```
150
-
151
- ### Model Resolution
152
- ```javascript
153
- // Automatic model resolution across providers
154
- export function resolveModel(modelName) {
155
- // Handle aliases (flash -> gemini-2.5-flash)
156
- const resolvedName = MODEL_ALIASES[modelName] || modelName;
157
-
158
- // Find provider that supports this model
159
- const provider = findProviderForModel(resolvedName);
160
-
161
- return { provider, model: resolvedName };
162
- }
163
- ```
164
-
165
- ## ๐Ÿ› ๏ธ Tool Architecture
166
-
167
- ### Tool Implementation Pattern
168
- ```javascript
169
- // tools/example.js
170
- export const exampleTool = {
171
- definition: {
172
- name: 'example',
173
- description: 'Example tool description',
174
- inputSchema: {
175
- type: 'object',
176
- properties: {
177
- prompt: { type: 'string', description: 'User prompt' }
178
- },
179
- required: ['prompt']
180
- }
181
- },
182
-
183
- handler: async (args) => {
184
- // 1. Validate input
185
- const validation = validateInput(args);
186
- if (!validation.valid) {
187
- throw new McpError(ErrorCode.InvalidParams, validation.error);
188
- }
189
-
190
- // 2. Process context (files, images)
191
- const context = await processContext(args.files, args.images);
192
-
193
- // 3. Execute main logic
194
- const result = await executeLogic(args, context);
195
-
196
- // 4. Return standardized response
197
- return formatResponse(result);
198
- }
199
- };
200
- ```
201
-
202
- ### Context Processing Pipeline
203
- ```javascript
204
- // utils/context.js
205
- export async function processContext(files = [], images = []) {
206
- return {
207
- fileContext: await processFiles(files),
208
- imageContext: await processImages(images)
209
- };
210
- }
211
-
212
- async function processFiles(filePaths) {
213
- return await Promise.all(
214
- filePaths.map(async (path) => {
215
- const content = await readFile(path);
216
- return {
217
- path,
218
- content: addLineNumbers(content),
219
- metadata: { size: content.length, type: getFileType(path) }
220
- };
221
- })
222
- );
223
- }
224
- ```
225
-
226
- ## ๐Ÿ”„ Data Flow
227
-
228
- ### Single Tool Execution (Chat)
229
- ```
230
- User Request
231
- โ†“
232
- Input Validation
233
- โ†“
234
- Context Processing (files/images)
235
- โ†“
236
- Provider Selection (auto/manual)
237
- โ†“
238
- Model Resolution
239
- โ†“
240
- API Call to Provider
241
- โ†“
242
- Response Processing
243
- โ†“
244
- Continuation Management
245
- โ†“
246
- Response to Client
247
- ```
248
-
249
- ### Multi-Provider Execution (Consensus)
250
- ```
251
- User Request
252
- โ†“
253
- Input Validation
254
- โ†“
255
- Context Processing
256
- โ†“
257
- Provider Selection (multiple)
258
- โ†“
259
- Parallel Execution โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€ Provider A
260
- โ”œโ”€โ”€โ”€ Provider B
261
- โ””โ”€โ”€โ”€ Provider C
262
- โ†“
263
- Initial Response Collection
264
- โ†“
265
- Cross-Feedback Phase (optional)
266
- โ†“
267
- Parallel Refinement โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€ Provider A (sees B,C)
268
- โ”œโ”€โ”€โ”€ Provider B (sees A,C)
269
- โ””โ”€โ”€โ”€ Provider C (sees A,B)
270
- โ†“
271
- Final Response Aggregation
272
- โ†“
273
- Response to Client
274
- ```
275
-
276
- ## ๐Ÿ”ง Configuration System
277
-
278
- ### Environment-Driven Configuration
279
- ```javascript
280
- // config.js
281
- export const config = {
282
- // Provider API keys
283
- providers: {
284
- openai: { apiKey: process.env.OPENAI_API_KEY },
285
- google: { apiKey: process.env.GOOGLE_API_KEY },
286
- xai: { apiKey: process.env.XAI_API_KEY }
287
- },
288
-
289
- // Server settings
290
- server: {
291
- port: parseInt(process.env.PORT) || 3157,
292
- logLevel: process.env.LOG_LEVEL || 'info',
293
- maxOutputTokens: parseInt(process.env.MAX_MCP_OUTPUT_TOKENS) || 25000
294
- },
295
-
296
- // Model mappings and aliases
297
- models: {
298
- aliases: {
299
- 'flash': 'gemini-2.5-flash',
300
- 'pro': 'gemini-2.5-pro',
301
- 'grok': 'grok-4-0709'
302
- }
303
- }
304
- };
305
- ```
306
-
307
- ### Dynamic Provider Registration
308
- ```javascript
309
- // index.js - Provider initialization
310
- async function initializeProviders() {
311
- const providerModules = [
312
- await import('./providers/openai.js'),
313
- await import('./providers/google.js'),
314
- await import('./providers/xai.js')
315
- ];
316
-
317
- for (const module of providerModules) {
318
- const provider = module.default;
319
- if (provider.isAvailable()) {
320
- registerProvider(provider.name, provider);
321
- logger.info(`Registered provider: ${provider.name}`);
322
- }
323
- }
324
- }
325
- ```
326
-
327
- ## ๐Ÿ“Š State Management
328
-
329
- ### Stateless Design
330
- - **No Global State**: Each request is independent
331
- - **Continuation Storage**: Conversations stored as isolated state
332
- - **Provider Independence**: Providers don't share state
333
- - **Immutable Responses**: Responses are constructed, not modified
334
-
335
- ### Continuation System
336
- ```javascript
337
- // utils/continuation.js
338
- const continuations = new Map();
339
-
340
- export function storeContinuation(id, data) {
341
- continuations.set(id, {
342
- ...data,
343
- lastAccessed: Date.now(),
344
- messageCount: (data.messageCount || 0) + 1
345
- });
346
- }
347
-
348
- export function getContinuation(id) {
349
- const continuation = continuations.get(id);
350
- if (continuation) {
351
- continuation.lastAccessed = Date.now();
352
- }
353
- return continuation;
354
- }
355
- ```
356
-
357
- ## ๐Ÿš€ Performance Characteristics
358
-
359
- ### Parallel Execution
360
- - **Consensus Tool**: Executes all providers simultaneously
361
- - **Non-Blocking I/O**: All async operations use Promise.all()
362
- - **Provider Isolation**: One provider failure doesn't affect others
363
- - **Request Batching**: Multiple requests handled concurrently
364
-
365
- ### Memory Management
366
- - **Streaming Responses**: Large responses handled efficiently
367
- - **Context Cleanup**: Old continuations automatically expire
368
- - **File Processing**: Files read on-demand, not cached
369
- - **Provider Pooling**: Connection reuse where possible
370
-
371
- ### Error Resilience
372
- ```javascript
373
- // Graceful error handling pattern
374
- async function executeWithFallback(primaryFn, fallbackFn) {
375
- try {
376
- return await primaryFn();
377
- } catch (primaryError) {
378
- logger.warn('Primary execution failed, attempting fallback', {
379
- error: primaryError.message
380
- });
381
-
382
- try {
383
- return await fallbackFn();
384
- } catch (fallbackError) {
385
- logger.error('Both primary and fallback failed', {
386
- primaryError: primaryError.message,
387
- fallbackError: fallbackError.message
388
- });
389
- throw new McpError(ErrorCode.InternalError, 'All execution attempts failed');
390
- }
391
- }
392
- }
393
- ```
394
-
395
- ## ๐Ÿ”’ Security Architecture
396
-
397
- ### Input Validation
398
- ```javascript
399
- // utils/validators.js
400
- export function validateChatInput(args) {
401
- const errors = [];
402
-
403
- if (!args.prompt || typeof args.prompt !== 'string') {
404
- errors.push('prompt must be a non-empty string');
405
- }
406
-
407
- if (args.files && !Array.isArray(args.files)) {
408
- errors.push('files must be an array');
409
- }
410
-
411
- return { valid: errors.length === 0, errors };
412
- }
413
- ```
414
-
415
- ### Path Security
416
- ```javascript
417
- // Prevent path traversal attacks
418
- function validateFilePath(filePath) {
419
- const normalized = path.resolve(filePath);
420
- const allowed = path.resolve(process.cwd());
421
-
422
- if (!normalized.startsWith(allowed)) {
423
- throw new McpError(ErrorCode.InvalidParams, 'Access denied: Path outside allowed directory');
424
- }
425
-
426
- return normalized;
427
- }
428
- ```
429
-
430
- ### API Key Protection
431
- - **Environment Variables**: Keys never hardcoded
432
- - **No Logging**: API keys excluded from all logs
433
- - **Provider Isolation**: Keys scoped to specific providers
434
- - **Error Sanitization**: Error messages don't expose keys
435
-
436
- ## ๐Ÿ” Observability
437
-
438
- ### Structured Logging
439
- ```javascript
440
- // utils/logger.js
441
- export const logger = {
442
- info: (message, meta = {}) => {
443
- console.log(JSON.stringify({
444
- level: 'info',
445
- timestamp: new Date().toISOString(),
446
- message,
447
- ...meta
448
- }));
449
- },
450
-
451
- error: (message, error = {}) => {
452
- console.error(JSON.stringify({
453
- level: 'error',
454
- timestamp: new Date().toISOString(),
455
- message,
456
- error: {
457
- name: error.name,
458
- message: error.message,
459
- stack: error.stack
460
- }
461
- }));
462
- }
463
- };
464
- ```
465
-
466
- ### Request Tracing
467
- ```javascript
468
- // Request correlation IDs
469
- function generateRequestId() {
470
- return `req_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
471
- }
472
-
473
- // All operations tagged with request ID
474
- logger.info('Processing chat request', {
475
- requestId,
476
- provider: 'openai',
477
- model: 'gpt-5'
478
- });
479
- ```
480
-
481
- ## ๐Ÿ“ˆ Extensibility
482
-
483
- ### Adding New Providers
484
- 1. Create provider module in `src/providers/`
485
- 2. Implement the provider contract
486
- 3. Export as default
487
- 4. Provider auto-registers if API key is available
488
-
489
- ### Adding New Tools
490
- 1. Create tool module in `src/tools/`
491
- 2. Define tool schema and handler
492
- 3. Register in main server setup
493
- 4. Add to MCP tool list
494
-
495
- ### Configuration Extensions
496
- ```javascript
497
- // Adding new configuration options
498
- export const config = {
499
- // ... existing config
500
-
501
- // New feature config
502
- experimental: {
503
- enableFeatureX: process.env.ENABLE_FEATURE_X === 'true',
504
- featureXTimeout: parseInt(process.env.FEATURE_X_TIMEOUT) || 30000
505
- }
506
- };
507
- ```
508
-
509
- ## ๐Ÿงช Testing Architecture
510
-
511
- ### Test Strategy
512
- - **Unit Tests**: Individual functions and modules
513
- - **Integration Tests**: Provider interactions (mocked APIs)
514
- - **E2E Tests**: Full request/response cycles
515
- - **Contract Tests**: Provider interface compliance
516
-
517
- ### Test Organization
518
- ```
519
- tests/
520
- โ”œโ”€โ”€ unit/ # Unit tests for individual functions
521
- โ”œโ”€โ”€ integration/ # Integration tests with mocked dependencies
522
- โ”œโ”€โ”€ e2e/ # End-to-end tests
523
- โ”œโ”€โ”€ fixtures/ # Test data and mocks
524
- โ””โ”€โ”€ helpers/ # Test utilities
525
- ```
526
-
527
- ## ๐Ÿ”ง Development Workflow
528
-
529
- ### Hot Reload Development
530
- ```bash
531
- # Development with auto-restart
532
- npm run dev
533
-
534
- # Debug mode with inspection
535
- npm run debug
536
- ```
537
-
538
- ### Code Quality Pipeline
539
- ```bash
540
- # Full validation pipeline
541
- npm run validate
542
-
543
- # Individual checks
544
- npm run lint
545
- npm run typecheck
546
- npm run test
547
- npm run format:check
548
- ```
549
-
550
- ---
551
-
1
+ # Converse MCP Server - Architecture Overview
2
+
3
+ ## ๐Ÿ—๏ธ System Architecture
4
+
5
+ The Converse MCP Server follows a **functional, modular architecture** designed for simplicity, maintainability, and performance. It implements the Model Context Protocol (MCP) to provide AI capabilities through multiple providers.
6
+
7
+ ## ๐Ÿ“ Project Structure
8
+
9
+ ```
10
+ src/
11
+ โ”œโ”€โ”€ index.js # Main entry point & MCP server setup
12
+ โ”œโ”€โ”€ config.js # Configuration and environment management
13
+ โ”œโ”€โ”€ systemPrompts.js # System prompts for tools
14
+ โ”œโ”€โ”€ providers/ # AI provider implementations
15
+ โ”‚ โ”œโ”€โ”€ registry.js # Provider registry and management
16
+ โ”‚ โ”œโ”€โ”€ openai.js # OpenAI provider implementation
17
+ โ”‚ โ”œโ”€โ”€ google.js # Google/Gemini provider implementation
18
+ โ”‚ โ””โ”€โ”€ xai.js # X.AI/Grok provider implementation
19
+ โ”œโ”€โ”€ tools/ # MCP tool implementations
20
+ โ”‚ โ”œโ”€โ”€ chat.js # Single-provider chat tool
21
+ โ”‚ โ””โ”€โ”€ consensus.js # Multi-provider consensus tool
22
+ โ”œโ”€โ”€ utils/ # Utility functions
23
+ โ”‚ โ”œโ”€โ”€ logger.js # Structured logging
24
+ โ”‚ โ”œโ”€โ”€ context.js # File and image processing
25
+ โ”‚ โ”œโ”€โ”€ continuation.js # Conversation persistence
26
+ โ”‚ โ””โ”€โ”€ validators.js # Input validation
27
+ bin/
28
+ โ”œโ”€โ”€ converse.js # CLI entry point for npx execution
29
+ docs/ # Documentation
30
+ tests/ # Test suites
31
+ ```
32
+
33
+ ## ๐Ÿ”„ Core Design Principles
34
+
35
+ ### 1. Functional Programming
36
+ - **No Classes**: Pure functions and modules only
37
+ - **Immutable Data**: Avoid state mutations where possible
38
+ - **Composable Functions**: Small, focused, reusable functions
39
+ - **Error Boundaries**: Explicit error handling at module boundaries
40
+
41
+ ### 2. Provider Abstraction
42
+ - **Unified Interface**: All providers implement consistent API
43
+ - **Auto-Discovery**: Providers register themselves dynamically
44
+ - **Graceful Degradation**: System works with any subset of providers
45
+ - **Parallel Execution**: Multiple providers can run simultaneously
46
+
47
+ ### 3. Tool Architecture
48
+ - **Minimal Interface**: Tools expose simple, focused functionality
49
+ - **Context Processing**: Standardized file and image handling
50
+ - **Continuation Support**: Persistent conversation management
51
+ - **Parameter Validation**: Comprehensive input validation
52
+
53
+ ## ๐Ÿ”Œ MCP Integration Layer
54
+
55
+ ### Server Setup
56
+
57
+ **HTTP Transport (Default):**
58
+ ```javascript
59
+ // index.js - HTTP transport setup
60
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
61
+ import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
62
+
63
+ const server = new Server(
64
+ { name: 'converse-mcp-server', version: '1.0.0' },
65
+ { capabilities: { tools: {} } }
66
+ );
67
+
68
+ // HTTP transport on port 3157 (default)
69
+ const httpTransport = new StreamableHTTPServerTransport({
70
+ host: 'localhost',
71
+ port: 3157
72
+ });
73
+ ```
74
+
75
+ **Stdio Transport (Legacy):**
76
+ ```javascript
77
+ // Alternative stdio transport
78
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
79
+
80
+ const transport = new StdioServerTransport();
81
+ await server.connect(transport);
82
+ ```
83
+
84
+ **Transport Selection:**
85
+ - **HTTP**: Default, better for development and debugging
86
+ - **Stdio**: Use `--transport=stdio` or `MCP_TRANSPORT=stdio`
87
+
88
+ ### Tool Registration
89
+ ```javascript
90
+ // Dynamic tool registration
91
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
92
+ const { name, arguments: args } = request.params;
93
+
94
+ switch (name) {
95
+ case 'chat':
96
+ return await chatTool(args);
97
+ case 'consensus':
98
+ return await consensusTool(args);
99
+ default:
100
+ throw new McpError(ErrorCode.MethodNotFound, `Tool not found: ${name}`);
101
+ }
102
+ });
103
+ ```
104
+
105
+ ## ๐Ÿค– Provider System
106
+
107
+ ### Provider Registry Pattern
108
+ ```javascript
109
+ // providers/registry.js
110
+ const providers = new Map();
111
+
112
+ export function registerProvider(name, implementation) {
113
+ if (implementation.isAvailable()) {
114
+ providers.set(name, implementation);
115
+ }
116
+ }
117
+
118
+ export function getProvider(name) {
119
+ return providers.get(name);
120
+ }
121
+
122
+ export function getAvailableProviders() {
123
+ return Array.from(providers.keys());
124
+ }
125
+ ```
126
+
127
+ ### Provider Implementation Contract
128
+ ```javascript
129
+ // Each provider must implement:
130
+ export const providerImplementation = {
131
+ // Check if provider is configured and available
132
+ isAvailable: () => Boolean(process.env.API_KEY),
133
+
134
+ // Get supported models
135
+ getSupportedModels: () => ['model1', 'model2'],
136
+
137
+ // Main chat completion method
138
+ chatCompletion: async (messages, options) => {
139
+ // Implementation details...
140
+ return {
141
+ content: 'Response text',
142
+ usage: { input_tokens: 100, output_tokens: 50 }
143
+ };
144
+ },
145
+
146
+ // Provider name for logging/tracking
147
+ name: 'provider-name'
148
+ };
149
+ ```
150
+
151
+ ### Model Resolution
152
+ ```javascript
153
+ // Automatic model resolution across providers
154
+ export function resolveModel(modelName) {
155
+ // Handle aliases (flash -> gemini-2.5-flash)
156
+ const resolvedName = MODEL_ALIASES[modelName] || modelName;
157
+
158
+ // Find provider that supports this model
159
+ const provider = findProviderForModel(resolvedName);
160
+
161
+ return { provider, model: resolvedName };
162
+ }
163
+ ```
164
+
165
+ ## ๐Ÿ› ๏ธ Tool Architecture
166
+
167
+ ### Tool Implementation Pattern
168
+ ```javascript
169
+ // tools/example.js
170
+ export const exampleTool = {
171
+ definition: {
172
+ name: 'example',
173
+ description: 'Example tool description',
174
+ inputSchema: {
175
+ type: 'object',
176
+ properties: {
177
+ prompt: { type: 'string', description: 'User prompt' }
178
+ },
179
+ required: ['prompt']
180
+ }
181
+ },
182
+
183
+ handler: async (args) => {
184
+ // 1. Validate input
185
+ const validation = validateInput(args);
186
+ if (!validation.valid) {
187
+ throw new McpError(ErrorCode.InvalidParams, validation.error);
188
+ }
189
+
190
+ // 2. Process context (files, images)
191
+ const context = await processContext(args.files, args.images);
192
+
193
+ // 3. Execute main logic
194
+ const result = await executeLogic(args, context);
195
+
196
+ // 4. Return standardized response
197
+ return formatResponse(result);
198
+ }
199
+ };
200
+ ```
201
+
202
+ ### Context Processing Pipeline
203
+ ```javascript
204
+ // utils/context.js
205
+ export async function processContext(files = [], images = []) {
206
+ return {
207
+ fileContext: await processFiles(files),
208
+ imageContext: await processImages(images)
209
+ };
210
+ }
211
+
212
+ async function processFiles(filePaths) {
213
+ return await Promise.all(
214
+ filePaths.map(async (path) => {
215
+ const content = await readFile(path);
216
+ return {
217
+ path,
218
+ content: addLineNumbers(content),
219
+ metadata: { size: content.length, type: getFileType(path) }
220
+ };
221
+ })
222
+ );
223
+ }
224
+ ```
225
+
226
+ ## ๐Ÿ”„ Data Flow
227
+
228
+ ### Single Tool Execution (Chat)
229
+ ```
230
+ User Request
231
+ โ†“
232
+ Input Validation
233
+ โ†“
234
+ Context Processing (files/images)
235
+ โ†“
236
+ Provider Selection (auto/manual)
237
+ โ†“
238
+ Model Resolution
239
+ โ†“
240
+ API Call to Provider
241
+ โ†“
242
+ Response Processing
243
+ โ†“
244
+ Continuation Management
245
+ โ†“
246
+ Response to Client
247
+ ```
248
+
249
+ ### Multi-Provider Execution (Consensus)
250
+ ```
251
+ User Request
252
+ โ†“
253
+ Input Validation
254
+ โ†“
255
+ Context Processing
256
+ โ†“
257
+ Provider Selection (multiple)
258
+ โ†“
259
+ Parallel Execution โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€ Provider A
260
+ โ”œโ”€โ”€โ”€ Provider B
261
+ โ””โ”€โ”€โ”€ Provider C
262
+ โ†“
263
+ Initial Response Collection
264
+ โ†“
265
+ Cross-Feedback Phase (optional)
266
+ โ†“
267
+ Parallel Refinement โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€ Provider A (sees B,C)
268
+ โ”œโ”€โ”€โ”€ Provider B (sees A,C)
269
+ โ””โ”€โ”€โ”€ Provider C (sees A,B)
270
+ โ†“
271
+ Final Response Aggregation
272
+ โ†“
273
+ Response to Client
274
+ ```
275
+
276
+ ## ๐Ÿ”ง Configuration System
277
+
278
+ ### Environment-Driven Configuration
279
+ ```javascript
280
+ // config.js
281
+ export const config = {
282
+ // Provider API keys
283
+ providers: {
284
+ openai: { apiKey: process.env.OPENAI_API_KEY },
285
+ google: { apiKey: process.env.GOOGLE_API_KEY },
286
+ xai: { apiKey: process.env.XAI_API_KEY }
287
+ },
288
+
289
+ // Server settings
290
+ server: {
291
+ port: parseInt(process.env.PORT) || 3157,
292
+ logLevel: process.env.LOG_LEVEL || 'info',
293
+ maxOutputTokens: parseInt(process.env.MAX_MCP_OUTPUT_TOKENS) || 25000
294
+ },
295
+
296
+ // Model mappings and aliases
297
+ models: {
298
+ aliases: {
299
+ 'flash': 'gemini-2.5-flash',
300
+ 'pro': 'gemini-2.5-pro',
301
+ 'grok': 'grok-4-0709'
302
+ }
303
+ }
304
+ };
305
+ ```
306
+
307
+ ### Dynamic Provider Registration
308
+ ```javascript
309
+ // index.js - Provider initialization
310
+ async function initializeProviders() {
311
+ const providerModules = [
312
+ await import('./providers/openai.js'),
313
+ await import('./providers/google.js'),
314
+ await import('./providers/xai.js')
315
+ ];
316
+
317
+ for (const module of providerModules) {
318
+ const provider = module.default;
319
+ if (provider.isAvailable()) {
320
+ registerProvider(provider.name, provider);
321
+ logger.info(`Registered provider: ${provider.name}`);
322
+ }
323
+ }
324
+ }
325
+ ```
326
+
327
+ ## ๐Ÿ“Š State Management
328
+
329
+ ### Stateless Design
330
+ - **No Global State**: Each request is independent
331
+ - **Continuation Storage**: Conversations stored as isolated state
332
+ - **Provider Independence**: Providers don't share state
333
+ - **Immutable Responses**: Responses are constructed, not modified
334
+
335
+ ### Continuation System
336
+ ```javascript
337
+ // utils/continuation.js
338
+ const continuations = new Map();
339
+
340
+ export function storeContinuation(id, data) {
341
+ continuations.set(id, {
342
+ ...data,
343
+ lastAccessed: Date.now(),
344
+ messageCount: (data.messageCount || 0) + 1
345
+ });
346
+ }
347
+
348
+ export function getContinuation(id) {
349
+ const continuation = continuations.get(id);
350
+ if (continuation) {
351
+ continuation.lastAccessed = Date.now();
352
+ }
353
+ return continuation;
354
+ }
355
+ ```
356
+
357
+ ## ๐Ÿš€ Performance Characteristics
358
+
359
+ ### Parallel Execution
360
+ - **Consensus Tool**: Executes all providers simultaneously
361
+ - **Non-Blocking I/O**: All async operations use Promise.all()
362
+ - **Provider Isolation**: One provider failure doesn't affect others
363
+ - **Request Batching**: Multiple requests handled concurrently
364
+
365
+ ### Memory Management
366
+ - **Streaming Responses**: Large responses handled efficiently
367
+ - **Context Cleanup**: Old continuations automatically expire
368
+ - **File Processing**: Files read on-demand, not cached
369
+ - **Provider Pooling**: Connection reuse where possible
370
+
371
+ ### Error Resilience
372
+ ```javascript
373
+ // Graceful error handling pattern
374
+ async function executeWithFallback(primaryFn, fallbackFn) {
375
+ try {
376
+ return await primaryFn();
377
+ } catch (primaryError) {
378
+ logger.warn('Primary execution failed, attempting fallback', {
379
+ error: primaryError.message
380
+ });
381
+
382
+ try {
383
+ return await fallbackFn();
384
+ } catch (fallbackError) {
385
+ logger.error('Both primary and fallback failed', {
386
+ primaryError: primaryError.message,
387
+ fallbackError: fallbackError.message
388
+ });
389
+ throw new McpError(ErrorCode.InternalError, 'All execution attempts failed');
390
+ }
391
+ }
392
+ }
393
+ ```
394
+
395
+ ## ๐Ÿ”’ Security Architecture
396
+
397
+ ### Input Validation
398
+ ```javascript
399
+ // utils/validators.js
400
+ export function validateChatInput(args) {
401
+ const errors = [];
402
+
403
+ if (!args.prompt || typeof args.prompt !== 'string') {
404
+ errors.push('prompt must be a non-empty string');
405
+ }
406
+
407
+ if (args.files && !Array.isArray(args.files)) {
408
+ errors.push('files must be an array');
409
+ }
410
+
411
+ return { valid: errors.length === 0, errors };
412
+ }
413
+ ```
414
+
415
+ ### Path Security
416
+ ```javascript
417
+ // Prevent path traversal attacks
418
+ function validateFilePath(filePath) {
419
+ const normalized = path.resolve(filePath);
420
+ const allowed = path.resolve(process.cwd());
421
+
422
+ if (!normalized.startsWith(allowed)) {
423
+ throw new McpError(ErrorCode.InvalidParams, 'Access denied: Path outside allowed directory');
424
+ }
425
+
426
+ return normalized;
427
+ }
428
+ ```
429
+
430
+ ### API Key Protection
431
+ - **Environment Variables**: Keys never hardcoded
432
+ - **No Logging**: API keys excluded from all logs
433
+ - **Provider Isolation**: Keys scoped to specific providers
434
+ - **Error Sanitization**: Error messages don't expose keys
435
+
436
+ ## ๐Ÿ” Observability
437
+
438
+ ### Structured Logging
439
+ ```javascript
440
+ // utils/logger.js
441
+ export const logger = {
442
+ info: (message, meta = {}) => {
443
+ console.log(JSON.stringify({
444
+ level: 'info',
445
+ timestamp: new Date().toISOString(),
446
+ message,
447
+ ...meta
448
+ }));
449
+ },
450
+
451
+ error: (message, error = {}) => {
452
+ console.error(JSON.stringify({
453
+ level: 'error',
454
+ timestamp: new Date().toISOString(),
455
+ message,
456
+ error: {
457
+ name: error.name,
458
+ message: error.message,
459
+ stack: error.stack
460
+ }
461
+ }));
462
+ }
463
+ };
464
+ ```
465
+
466
+ ### Request Tracing
467
+ ```javascript
468
+ // Request correlation IDs
469
+ function generateRequestId() {
470
+ return `req_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
471
+ }
472
+
473
+ // All operations tagged with request ID
474
+ logger.info('Processing chat request', {
475
+ requestId,
476
+ provider: 'openai',
477
+ model: 'gpt-5'
478
+ });
479
+ ```
480
+
481
+ ## ๐Ÿ“ˆ Extensibility
482
+
483
+ ### Adding New Providers
484
+ 1. Create provider module in `src/providers/`
485
+ 2. Implement the provider contract
486
+ 3. Export as default
487
+ 4. Provider auto-registers if API key is available
488
+
489
+ ### Adding New Tools
490
+ 1. Create tool module in `src/tools/`
491
+ 2. Define tool schema and handler
492
+ 3. Register in main server setup
493
+ 4. Add to MCP tool list
494
+
495
+ ### Configuration Extensions
496
+ ```javascript
497
+ // Adding new configuration options
498
+ export const config = {
499
+ // ... existing config
500
+
501
+ // New feature config
502
+ experimental: {
503
+ enableFeatureX: process.env.ENABLE_FEATURE_X === 'true',
504
+ featureXTimeout: parseInt(process.env.FEATURE_X_TIMEOUT) || 30000
505
+ }
506
+ };
507
+ ```
508
+
509
+ ## ๐Ÿงช Testing Architecture
510
+
511
+ ### Test Strategy
512
+ - **Unit Tests**: Individual functions and modules
513
+ - **Integration Tests**: Provider interactions (mocked APIs)
514
+ - **E2E Tests**: Full request/response cycles
515
+ - **Contract Tests**: Provider interface compliance
516
+
517
+ ### Test Organization
518
+ ```
519
+ tests/
520
+ โ”œโ”€โ”€ unit/ # Unit tests for individual functions
521
+ โ”œโ”€โ”€ integration/ # Integration tests with mocked dependencies
522
+ โ”œโ”€โ”€ e2e/ # End-to-end tests
523
+ โ”œโ”€โ”€ fixtures/ # Test data and mocks
524
+ โ””โ”€โ”€ helpers/ # Test utilities
525
+ ```
526
+
527
+ ## ๐Ÿ”ง Development Workflow
528
+
529
+ ### Hot Reload Development
530
+ ```bash
531
+ # Development with auto-restart
532
+ npm run dev
533
+
534
+ # Debug mode with inspection
535
+ npm run debug
536
+ ```
537
+
538
+ ### Code Quality Pipeline
539
+ ```bash
540
+ # Full validation pipeline
541
+ npm run validate
542
+
543
+ # Individual checks
544
+ npm run lint
545
+ npm run typecheck
546
+ npm run test
547
+ npm run format:check
548
+ ```
549
+
550
+ ---
551
+
552
552
  This architecture emphasizes **simplicity**, **reliability**, and **extensibility** while maintaining high performance through parallel execution and efficient resource management.