@juspay/neurolink 4.0.0 → 4.1.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.
Files changed (57) hide show
  1. package/CHANGELOG.md +14 -5
  2. package/README.md +150 -92
  3. package/dist/lib/mcp/dynamic-chain-executor.d.ts +201 -0
  4. package/dist/lib/mcp/dynamic-chain-executor.js +489 -0
  5. package/dist/lib/mcp/dynamic-orchestrator.d.ts +109 -0
  6. package/dist/lib/mcp/dynamic-orchestrator.js +351 -0
  7. package/dist/lib/mcp/error-manager.d.ts +254 -0
  8. package/dist/lib/mcp/error-manager.js +501 -0
  9. package/dist/lib/mcp/error-recovery.d.ts +158 -0
  10. package/dist/lib/mcp/error-recovery.js +405 -0
  11. package/dist/lib/mcp/health-monitor.d.ts +256 -0
  12. package/dist/lib/mcp/health-monitor.js +621 -0
  13. package/dist/lib/mcp/orchestrator.d.ts +136 -5
  14. package/dist/lib/mcp/orchestrator.js +316 -9
  15. package/dist/lib/mcp/registry.d.ts +22 -0
  16. package/dist/lib/mcp/registry.js +24 -0
  17. package/dist/lib/mcp/semaphore-manager.d.ts +137 -0
  18. package/dist/lib/mcp/semaphore-manager.js +329 -0
  19. package/dist/lib/mcp/servers/ai-providers/ai-workflow-tools.d.ts +2 -2
  20. package/dist/lib/mcp/session-manager.d.ts +186 -0
  21. package/dist/lib/mcp/session-manager.js +400 -0
  22. package/dist/lib/mcp/session-persistence.d.ts +93 -0
  23. package/dist/lib/mcp/session-persistence.js +298 -0
  24. package/dist/lib/mcp/transport-manager.d.ts +153 -0
  25. package/dist/lib/mcp/transport-manager.js +330 -0
  26. package/dist/lib/mcp/unified-registry.d.ts +42 -1
  27. package/dist/lib/mcp/unified-registry.js +122 -2
  28. package/dist/lib/neurolink.d.ts +75 -0
  29. package/dist/lib/neurolink.js +104 -0
  30. package/dist/mcp/dynamic-chain-executor.d.ts +201 -0
  31. package/dist/mcp/dynamic-chain-executor.js +489 -0
  32. package/dist/mcp/dynamic-orchestrator.d.ts +109 -0
  33. package/dist/mcp/dynamic-orchestrator.js +351 -0
  34. package/dist/mcp/error-manager.d.ts +254 -0
  35. package/dist/mcp/error-manager.js +501 -0
  36. package/dist/mcp/error-recovery.d.ts +158 -0
  37. package/dist/mcp/error-recovery.js +405 -0
  38. package/dist/mcp/health-monitor.d.ts +256 -0
  39. package/dist/mcp/health-monitor.js +621 -0
  40. package/dist/mcp/orchestrator.d.ts +136 -5
  41. package/dist/mcp/orchestrator.js +316 -9
  42. package/dist/mcp/plugins/core/neurolink-mcp.json +15 -15
  43. package/dist/mcp/registry.d.ts +22 -0
  44. package/dist/mcp/registry.js +24 -0
  45. package/dist/mcp/semaphore-manager.d.ts +137 -0
  46. package/dist/mcp/semaphore-manager.js +329 -0
  47. package/dist/mcp/session-manager.d.ts +186 -0
  48. package/dist/mcp/session-manager.js +400 -0
  49. package/dist/mcp/session-persistence.d.ts +93 -0
  50. package/dist/mcp/session-persistence.js +299 -0
  51. package/dist/mcp/transport-manager.d.ts +153 -0
  52. package/dist/mcp/transport-manager.js +331 -0
  53. package/dist/mcp/unified-registry.d.ts +42 -1
  54. package/dist/mcp/unified-registry.js +122 -2
  55. package/dist/neurolink.d.ts +75 -0
  56. package/dist/neurolink.js +104 -0
  57. package/package.json +245 -244
@@ -2,10 +2,16 @@
2
2
  * NeuroLink MCP Tool Orchestration Engine
3
3
  * Central orchestrator for coordinated tool execution with pipeline management
4
4
  * Coordinates factory, registry, context, and AI tools for seamless operation
5
+ * Now with semaphore-based race condition prevention
5
6
  */
6
7
  import type { ToolResult } from "./factory.js";
7
8
  import { MCPToolRegistry, type ToolExecutionOptions } from "./tool-registry.js";
8
9
  import { ContextManager, type ContextRequest } from "./context-manager.js";
10
+ import { SemaphoreManager } from "./semaphore-manager.js";
11
+ import { SessionManager, type OrchestratorSession, type SessionOptions } from "./session-manager.js";
12
+ import { ErrorManager } from "./error-manager.js";
13
+ import { HealthMonitor, type HealthMonitorOptions } from "./health-monitor.js";
14
+ import { TransportManager, type TransportConfig, type TransportManagerOptions } from "./transport-manager.js";
9
15
  /**
10
16
  * Pipeline execution options
11
17
  */
@@ -67,10 +73,15 @@ export interface TextPipelineResult {
67
73
  * Central coordination engine for tool execution, pipelines, and AI operations
68
74
  */
69
75
  export declare class MCPOrchestrator {
70
- private registry;
71
- private contextManager;
72
- private pipelineCounter;
73
- constructor(registry?: MCPToolRegistry, contextManager?: ContextManager);
76
+ protected registry: MCPToolRegistry;
77
+ protected contextManager: ContextManager;
78
+ protected semaphoreManager: SemaphoreManager;
79
+ protected sessionManager: SessionManager;
80
+ protected errorManager: ErrorManager;
81
+ protected healthMonitor: HealthMonitor | null;
82
+ protected transportManager: TransportManager | null;
83
+ protected pipelineCounter: number;
84
+ constructor(registry?: MCPToolRegistry, contextManager?: ContextManager, semaphoreManager?: SemaphoreManager, sessionManager?: SessionManager, errorManager?: ErrorManager);
74
85
  /**
75
86
  * Initialize with default servers (AI Core)
76
87
  */
@@ -84,7 +95,9 @@ export declare class MCPOrchestrator {
84
95
  * @param options Execution options
85
96
  * @returns Tool execution result
86
97
  */
87
- executeTool(toolName: string, params: any, contextRequest?: ContextRequest, options?: ToolExecutionOptions): Promise<ToolResult>;
98
+ executeTool(toolName: string, params: any, contextRequest?: ContextRequest, options?: ToolExecutionOptions & {
99
+ sessionOptions?: SessionOptions;
100
+ }): Promise<ToolResult>;
88
101
  /**
89
102
  * Execute a pipeline of tools with dependency management
90
103
  *
@@ -118,10 +131,128 @@ export declare class MCPOrchestrator {
118
131
  getStats(): {
119
132
  registry: any;
120
133
  context: any;
134
+ session: any;
135
+ error: any;
136
+ health?: any;
121
137
  orchestrator: {
122
138
  pipelinesExecuted: number;
123
139
  };
124
140
  };
141
+ /**
142
+ * Get session by ID
143
+ *
144
+ * @param sessionId Session identifier
145
+ * @param extend Whether to extend session expiration
146
+ * @returns Session or null if not found
147
+ */
148
+ getSession(sessionId: string, extend?: boolean): Promise<OrchestratorSession | null>;
149
+ /**
150
+ * Create a new session for continuous tool calling
151
+ *
152
+ * @param contextRequest Context creation request
153
+ * @param sessionOptions Session configuration options
154
+ * @returns Created session
155
+ */
156
+ createSession(contextRequest?: ContextRequest, sessionOptions?: SessionOptions): Promise<OrchestratorSession>;
157
+ /**
158
+ * Set session state value
159
+ *
160
+ * @param sessionId Session identifier
161
+ * @param key State key
162
+ * @param value State value
163
+ * @returns Success status
164
+ */
165
+ setSessionState(sessionId: string, key: string, value: any): Promise<boolean>;
166
+ /**
167
+ * Get session state value
168
+ *
169
+ * @param sessionId Session identifier
170
+ * @param key State key
171
+ * @returns State value or undefined
172
+ */
173
+ getSessionState(sessionId: string, key: string): Promise<any>;
174
+ /**
175
+ * Get all active sessions
176
+ *
177
+ * @returns Array of active sessions
178
+ */
179
+ getActiveSessions(): Promise<OrchestratorSession[]>;
180
+ /**
181
+ * Clean up expired sessions
182
+ *
183
+ * @returns Number of sessions cleaned
184
+ */
185
+ cleanupSessions(): Promise<number>;
186
+ /**
187
+ * Get error history
188
+ *
189
+ * @param filter Optional filter criteria
190
+ * @returns Filtered error history
191
+ */
192
+ getErrorHistory(filter?: Parameters<ErrorManager["getErrorHistory"]>[0]): import("./error-manager.js").ErrorEntry[];
193
+ /**
194
+ * Clear error history
195
+ */
196
+ clearErrorHistory(): void;
197
+ /**
198
+ * Get recovery suggestion for last error
199
+ *
200
+ * @param sessionId Optional session ID to get last error from
201
+ * @returns Recovery suggestion or null
202
+ */
203
+ getLastErrorRecovery(sessionId?: string): string | null;
204
+ /**
205
+ * Initialize health monitoring
206
+ *
207
+ * @param options Health monitor options
208
+ */
209
+ initializeHealthMonitor(options?: HealthMonitorOptions): void;
210
+ /**
211
+ * Start health monitoring for all registered servers
212
+ */
213
+ startHealthMonitoring(): void;
214
+ /**
215
+ * Stop health monitoring
216
+ */
217
+ stopHealthMonitoring(): void;
218
+ /**
219
+ * Register recovery callback for a server
220
+ *
221
+ * @param serverId Server ID
222
+ * @param callback Recovery callback
223
+ */
224
+ registerRecoveryCallback(serverId: string, callback: (serverId: string) => Promise<void>): void;
225
+ /**
226
+ * Get health status for all servers
227
+ *
228
+ * @returns Map of server health status
229
+ */
230
+ getHealthStatus(): Map<any, any>;
231
+ /**
232
+ * Initialize transport manager for MCP connections
233
+ *
234
+ * @param options Transport manager options
235
+ */
236
+ initializeTransportManager(options?: TransportManagerOptions): void;
237
+ /**
238
+ * Connect to MCP server using specified transport
239
+ *
240
+ * @param config Transport configuration
241
+ * @returns Connected MCP client
242
+ */
243
+ connectTransport(config: TransportConfig): Promise<any>;
244
+ /**
245
+ * Disconnect from MCP server
246
+ */
247
+ disconnectTransport(): Promise<void>;
248
+ /**
249
+ * Get transport connection status
250
+ */
251
+ getTransportStatus(): import("./transport-manager.js").TransportStatus;
252
+ /**
253
+ * Check if transport is connected
254
+ */
255
+ isTransportConnected(): boolean;
125
256
  /**
126
257
  * Execute parallel pipeline with dependency management
127
258
  *
@@ -2,9 +2,15 @@
2
2
  * NeuroLink MCP Tool Orchestration Engine
3
3
  * Central orchestrator for coordinated tool execution with pipeline management
4
4
  * Coordinates factory, registry, context, and AI tools for seamless operation
5
+ * Now with semaphore-based race condition prevention
5
6
  */
6
7
  import { defaultToolRegistry, } from "./tool-registry.js";
7
8
  import { defaultContextManager, } from "./context-manager.js";
9
+ import { defaultSemaphoreManager, } from "./semaphore-manager.js";
10
+ import { defaultSessionManager, } from "./session-manager.js";
11
+ import { defaultErrorManager, ErrorCategory, ErrorSeverity, } from "./error-manager.js";
12
+ import { initializeHealthMonitor, } from "./health-monitor.js";
13
+ import { TransportManager, } from "./transport-manager.js";
8
14
  import { aiCoreServer } from "./servers/ai-providers/ai-core-server.js";
9
15
  /**
10
16
  * NeuroLink MCP Tool Orchestrator
@@ -13,10 +19,18 @@ import { aiCoreServer } from "./servers/ai-providers/ai-core-server.js";
13
19
  export class MCPOrchestrator {
14
20
  registry;
15
21
  contextManager;
22
+ semaphoreManager;
23
+ sessionManager;
24
+ errorManager;
25
+ healthMonitor = null;
26
+ transportManager = null;
16
27
  pipelineCounter = 0;
17
- constructor(registry, contextManager) {
28
+ constructor(registry, contextManager, semaphoreManager, sessionManager, errorManager) {
18
29
  this.registry = registry || defaultToolRegistry;
19
30
  this.contextManager = contextManager || defaultContextManager;
31
+ this.semaphoreManager = semaphoreManager || defaultSemaphoreManager;
32
+ this.sessionManager = sessionManager || defaultSessionManager;
33
+ this.errorManager = errorManager || defaultErrorManager;
20
34
  // Initialize with AI Core Server
21
35
  this.initializeDefaultServers();
22
36
  }
@@ -47,15 +61,89 @@ export class MCPOrchestrator {
47
61
  async executeTool(toolName, params, contextRequest = {}, options = {}) {
48
62
  // Create execution context
49
63
  const context = this.contextManager.createContext(contextRequest);
64
+ // Get or create session for continuous tool calling
65
+ let session = null;
66
+ if (context.sessionId) {
67
+ session = await this.sessionManager.getSession(context.sessionId);
68
+ }
69
+ if (!session) {
70
+ // Create new session with options
71
+ session = await this.sessionManager.createSession(context, options.sessionOptions);
72
+ // Update context with new session ID
73
+ context.sessionId = session.id;
74
+ }
50
75
  if (process.env.NEUROLINK_DEBUG === "true") {
51
76
  console.log(`[Orchestrator] Executing tool '${toolName}' in session ${context.sessionId}`);
52
77
  }
53
- // Execute tool through registry
54
- const result = await this.registry.executeTool(toolName, params, context);
55
- if (process.env.NEUROLINK_DEBUG === "true") {
56
- console.log(`[Orchestrator] Tool '${toolName}' execution ${result.success ? "completed" : "failed"}`);
78
+ // Use semaphore to prevent race conditions for the same tool
79
+ // Each tool gets its own semaphore key to allow parallel execution of different tools
80
+ const semaphoreKey = `tool:${toolName}`;
81
+ const semaphoreResult = await this.semaphoreManager.acquire(semaphoreKey, async () => {
82
+ try {
83
+ // Execute tool through registry
84
+ const result = await this.registry.executeTool(toolName, params, context);
85
+ if (process.env.NEUROLINK_DEBUG === "true") {
86
+ console.log(`[Orchestrator] Tool '${toolName}' execution ${result.success ? "completed" : "failed"}`);
87
+ }
88
+ // Record error if tool execution failed
89
+ if (!result.success && result.error) {
90
+ this.errorManager.recordError(result.error, {
91
+ category: ErrorCategory.TOOL_ERROR,
92
+ severity: ErrorSeverity.HIGH,
93
+ sessionId: session.id,
94
+ toolName,
95
+ parameters: params,
96
+ executionContext: context,
97
+ });
98
+ }
99
+ return result;
100
+ }
101
+ catch (error) {
102
+ // Record unexpected errors
103
+ const errorEntry = await this.errorManager.recordError(error, {
104
+ category: ErrorCategory.TOOL_ERROR,
105
+ severity: ErrorSeverity.CRITICAL,
106
+ sessionId: session.id,
107
+ toolName,
108
+ parameters: params,
109
+ executionContext: context,
110
+ });
111
+ // Return error result
112
+ return {
113
+ success: false,
114
+ data: null,
115
+ error: errorEntry.error,
116
+ usage: {},
117
+ };
118
+ }
119
+ }, context);
120
+ // Handle semaphore errors
121
+ if (!semaphoreResult.success) {
122
+ const errorResult = {
123
+ success: false,
124
+ data: null,
125
+ error: semaphoreResult.error || new Error("Semaphore acquisition failed"),
126
+ usage: {
127
+ executionTime: semaphoreResult.executionTime,
128
+ waitTime: semaphoreResult.waitTime,
129
+ },
130
+ };
131
+ // Update session with error result
132
+ await this.sessionManager.updateSession(session.id, errorResult);
133
+ return errorResult;
57
134
  }
58
- return result;
135
+ const result = semaphoreResult.result;
136
+ // Update session with tool result
137
+ await this.sessionManager.updateSession(session.id, result);
138
+ // Enhance result with session information
139
+ return {
140
+ ...result,
141
+ sessionId: session.id,
142
+ sessionData: {
143
+ toolHistory: session.toolHistory.length,
144
+ state: Object.fromEntries(session.state),
145
+ },
146
+ };
59
147
  }
60
148
  /**
61
149
  * Execute a pipeline of tools with dependency management
@@ -95,7 +183,23 @@ export class MCPOrchestrator {
95
183
  const stepId = step.stepId || `step-${stepsExecuted + 1}`;
96
184
  try {
97
185
  console.log(`[Orchestrator] Executing step: ${stepId} (${step.toolName})`);
98
- const stepResult = await this.registry.executeTool(step.toolName, step.params, context);
186
+ // Use semaphore for each tool execution in pipeline
187
+ const semaphoreKey = `tool:${step.toolName}`;
188
+ const semaphoreResult = await this.semaphoreManager.acquire(semaphoreKey, async () => {
189
+ return await this.registry.executeTool(step.toolName, step.params, context);
190
+ }, context);
191
+ const stepResult = semaphoreResult.success
192
+ ? semaphoreResult.result
193
+ : {
194
+ success: false,
195
+ data: null,
196
+ error: semaphoreResult.error ||
197
+ new Error("Semaphore acquisition failed"),
198
+ usage: {
199
+ executionTime: semaphoreResult.executionTime,
200
+ waitTime: semaphoreResult.waitTime,
201
+ },
202
+ };
99
203
  results.set(stepId, stepResult);
100
204
  stepsExecuted++;
101
205
  if (!stepResult.success) {
@@ -265,13 +369,200 @@ export class MCPOrchestrator {
265
369
  * @returns Comprehensive orchestrator statistics
266
370
  */
267
371
  getStats() {
268
- return {
372
+ const stats = {
269
373
  registry: this.registry.getStats(),
270
374
  context: this.contextManager.getStats(),
375
+ session: this.sessionManager.getStats(),
376
+ error: this.errorManager.getStats(),
271
377
  orchestrator: {
272
378
  pipelinesExecuted: this.pipelineCounter,
273
379
  },
274
380
  };
381
+ if (this.healthMonitor) {
382
+ const healthStatus = this.healthMonitor.getHealthStatus();
383
+ stats.health = {
384
+ servers: Array.from(healthStatus.entries()).map(([id, health]) => ({
385
+ id,
386
+ status: health.status,
387
+ checkCount: health.checkCount,
388
+ errorCount: health.errorCount,
389
+ lastSuccessfulCheck: health.lastSuccessfulCheck,
390
+ })),
391
+ };
392
+ }
393
+ return stats;
394
+ }
395
+ /**
396
+ * Get session by ID
397
+ *
398
+ * @param sessionId Session identifier
399
+ * @param extend Whether to extend session expiration
400
+ * @returns Session or null if not found
401
+ */
402
+ async getSession(sessionId, extend = true) {
403
+ return this.sessionManager.getSession(sessionId, extend);
404
+ }
405
+ /**
406
+ * Create a new session for continuous tool calling
407
+ *
408
+ * @param contextRequest Context creation request
409
+ * @param sessionOptions Session configuration options
410
+ * @returns Created session
411
+ */
412
+ async createSession(contextRequest = {}, sessionOptions) {
413
+ const context = this.contextManager.createContext(contextRequest);
414
+ return this.sessionManager.createSession(context, sessionOptions);
415
+ }
416
+ /**
417
+ * Set session state value
418
+ *
419
+ * @param sessionId Session identifier
420
+ * @param key State key
421
+ * @param value State value
422
+ * @returns Success status
423
+ */
424
+ async setSessionState(sessionId, key, value) {
425
+ return this.sessionManager.setSessionState(sessionId, key, value) !== null;
426
+ }
427
+ /**
428
+ * Get session state value
429
+ *
430
+ * @param sessionId Session identifier
431
+ * @param key State key
432
+ * @returns State value or undefined
433
+ */
434
+ async getSessionState(sessionId, key) {
435
+ return this.sessionManager.getSessionState(sessionId, key);
436
+ }
437
+ /**
438
+ * Get all active sessions
439
+ *
440
+ * @returns Array of active sessions
441
+ */
442
+ async getActiveSessions() {
443
+ return this.sessionManager.getActiveSessions();
444
+ }
445
+ /**
446
+ * Clean up expired sessions
447
+ *
448
+ * @returns Number of sessions cleaned
449
+ */
450
+ async cleanupSessions() {
451
+ return this.sessionManager.cleanup();
452
+ }
453
+ /**
454
+ * Get error history
455
+ *
456
+ * @param filter Optional filter criteria
457
+ * @returns Filtered error history
458
+ */
459
+ getErrorHistory(filter) {
460
+ return this.errorManager.getErrorHistory(filter);
461
+ }
462
+ /**
463
+ * Clear error history
464
+ */
465
+ clearErrorHistory() {
466
+ this.errorManager.clearHistory();
467
+ }
468
+ /**
469
+ * Get recovery suggestion for last error
470
+ *
471
+ * @param sessionId Optional session ID to get last error from
472
+ * @returns Recovery suggestion or null
473
+ */
474
+ getLastErrorRecovery(sessionId) {
475
+ const filter = sessionId ? { sessionId, limit: 1 } : { limit: 1 };
476
+ const errors = this.errorManager.getErrorHistory(filter);
477
+ if (errors.length > 0) {
478
+ return this.errorManager.getRecoverySuggestion(errors[0]);
479
+ }
480
+ return null;
481
+ }
482
+ /**
483
+ * Initialize health monitoring
484
+ *
485
+ * @param options Health monitor options
486
+ */
487
+ initializeHealthMonitor(options) {
488
+ this.healthMonitor = initializeHealthMonitor(this.registry, this.errorManager, options);
489
+ }
490
+ /**
491
+ * Start health monitoring for all registered servers
492
+ */
493
+ startHealthMonitoring() {
494
+ if (!this.healthMonitor) {
495
+ this.initializeHealthMonitor();
496
+ }
497
+ this.healthMonitor.startMonitoring();
498
+ }
499
+ /**
500
+ * Stop health monitoring
501
+ */
502
+ stopHealthMonitoring() {
503
+ this.healthMonitor?.stopMonitoring();
504
+ }
505
+ /**
506
+ * Register recovery callback for a server
507
+ *
508
+ * @param serverId Server ID
509
+ * @param callback Recovery callback
510
+ */
511
+ registerRecoveryCallback(serverId, callback) {
512
+ if (!this.healthMonitor) {
513
+ this.initializeHealthMonitor();
514
+ }
515
+ this.healthMonitor.registerRecoveryCallback(serverId, callback);
516
+ }
517
+ /**
518
+ * Get health status for all servers
519
+ *
520
+ * @returns Map of server health status
521
+ */
522
+ getHealthStatus() {
523
+ return this.healthMonitor?.getHealthStatus() || new Map();
524
+ }
525
+ /**
526
+ * Initialize transport manager for MCP connections
527
+ *
528
+ * @param options Transport manager options
529
+ */
530
+ initializeTransportManager(options) {
531
+ this.transportManager = new TransportManager(this.errorManager, options);
532
+ }
533
+ /**
534
+ * Connect to MCP server using specified transport
535
+ *
536
+ * @param config Transport configuration
537
+ * @returns Connected MCP client
538
+ */
539
+ async connectTransport(config) {
540
+ if (!this.transportManager) {
541
+ this.initializeTransportManager();
542
+ }
543
+ return this.transportManager.connect(config);
544
+ }
545
+ /**
546
+ * Disconnect from MCP server
547
+ */
548
+ async disconnectTransport() {
549
+ await this.transportManager?.disconnect();
550
+ }
551
+ /**
552
+ * Get transport connection status
553
+ */
554
+ getTransportStatus() {
555
+ return (this.transportManager?.getStatus() || {
556
+ connected: false,
557
+ type: "stdio",
558
+ reconnectAttempts: 0,
559
+ });
560
+ }
561
+ /**
562
+ * Check if transport is connected
563
+ */
564
+ isTransportConnected() {
565
+ return this.transportManager?.isConnected() || false;
275
566
  }
276
567
  /**
277
568
  * Execute parallel pipeline with dependency management
@@ -306,7 +597,23 @@ export class MCPOrchestrator {
306
597
  executing.add(stepId);
307
598
  const step = stepMap.get(stepId);
308
599
  try {
309
- const result = await this.registry.executeTool(step.toolName, step.params, context);
600
+ // Use semaphore for parallel execution to prevent race conditions
601
+ const semaphoreKey = `tool:${step.toolName}`;
602
+ const semaphoreResult = await this.semaphoreManager.acquire(semaphoreKey, async () => {
603
+ return await this.registry.executeTool(step.toolName, step.params, context);
604
+ }, context);
605
+ const result = semaphoreResult.success
606
+ ? semaphoreResult.result
607
+ : {
608
+ success: false,
609
+ data: null,
610
+ error: semaphoreResult.error ||
611
+ new Error("Semaphore acquisition failed"),
612
+ usage: {
613
+ executionTime: semaphoreResult.executionTime,
614
+ waitTime: semaphoreResult.waitTime,
615
+ },
616
+ };
310
617
  results.set(stepId, result);
311
618
  if (!result.success) {
312
619
  const error = result.error;
@@ -67,6 +67,28 @@ export declare class MCPRegistry implements McpRegistry {
67
67
  name: string;
68
68
  description?: string;
69
69
  }>;
70
+ /**
71
+ * List all registered server IDs
72
+ *
73
+ * Returns an array of server IDs that are currently registered in the MCP registry.
74
+ * This complements listTools() by providing server-level information, while listTools()
75
+ * provides tool-level information across all servers.
76
+ *
77
+ * @returns Array of registered server identifier strings
78
+ * @see listTools() for getting detailed tool information from all servers
79
+ * @see list() for getting complete server metadata objects
80
+ *
81
+ * @example
82
+ * ```typescript
83
+ * const serverIds = registry.listServers();
84
+ * // ['ai-core', 'external-api', 'database-connector']
85
+ *
86
+ * // Compare with listTools() for comprehensive overview:
87
+ * const servers = registry.listServers(); // ['server1', 'server2']
88
+ * const tools = await registry.listTools(); // [{ name: 'tool1', serverId: 'server1' }, ...]
89
+ * ```
90
+ */
91
+ listServers(): string[];
70
92
  }
71
93
  /**
72
94
  * Enhanced MCP Registry implementation with config integration
@@ -113,6 +113,30 @@ export class MCPRegistry {
113
113
  }));
114
114
  return tools;
115
115
  }
116
+ /**
117
+ * List all registered server IDs
118
+ *
119
+ * Returns an array of server IDs that are currently registered in the MCP registry.
120
+ * This complements listTools() by providing server-level information, while listTools()
121
+ * provides tool-level information across all servers.
122
+ *
123
+ * @returns Array of registered server identifier strings
124
+ * @see listTools() for getting detailed tool information from all servers
125
+ * @see list() for getting complete server metadata objects
126
+ *
127
+ * @example
128
+ * ```typescript
129
+ * const serverIds = registry.listServers();
130
+ * // ['ai-core', 'external-api', 'database-connector']
131
+ *
132
+ * // Compare with listTools() for comprehensive overview:
133
+ * const servers = registry.listServers(); // ['server1', 'server2']
134
+ * const tools = await registry.listTools(); // [{ name: 'tool1', serverId: 'server1' }, ...]
135
+ * ```
136
+ */
137
+ listServers() {
138
+ return Array.from(this.plugins.keys());
139
+ }
116
140
  }
117
141
  /**
118
142
  * Enhanced MCP Registry implementation with config integration