@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.
- package/CHANGELOG.md +14 -5
- package/README.md +150 -92
- package/dist/lib/mcp/dynamic-chain-executor.d.ts +201 -0
- package/dist/lib/mcp/dynamic-chain-executor.js +489 -0
- package/dist/lib/mcp/dynamic-orchestrator.d.ts +109 -0
- package/dist/lib/mcp/dynamic-orchestrator.js +351 -0
- package/dist/lib/mcp/error-manager.d.ts +254 -0
- package/dist/lib/mcp/error-manager.js +501 -0
- package/dist/lib/mcp/error-recovery.d.ts +158 -0
- package/dist/lib/mcp/error-recovery.js +405 -0
- package/dist/lib/mcp/health-monitor.d.ts +256 -0
- package/dist/lib/mcp/health-monitor.js +621 -0
- package/dist/lib/mcp/orchestrator.d.ts +136 -5
- package/dist/lib/mcp/orchestrator.js +316 -9
- package/dist/lib/mcp/registry.d.ts +22 -0
- package/dist/lib/mcp/registry.js +24 -0
- package/dist/lib/mcp/semaphore-manager.d.ts +137 -0
- package/dist/lib/mcp/semaphore-manager.js +329 -0
- package/dist/lib/mcp/servers/ai-providers/ai-workflow-tools.d.ts +2 -2
- package/dist/lib/mcp/session-manager.d.ts +186 -0
- package/dist/lib/mcp/session-manager.js +400 -0
- package/dist/lib/mcp/session-persistence.d.ts +93 -0
- package/dist/lib/mcp/session-persistence.js +298 -0
- package/dist/lib/mcp/transport-manager.d.ts +153 -0
- package/dist/lib/mcp/transport-manager.js +330 -0
- package/dist/lib/mcp/unified-registry.d.ts +42 -1
- package/dist/lib/mcp/unified-registry.js +122 -2
- package/dist/lib/neurolink.d.ts +75 -0
- package/dist/lib/neurolink.js +104 -0
- package/dist/mcp/dynamic-chain-executor.d.ts +201 -0
- package/dist/mcp/dynamic-chain-executor.js +489 -0
- package/dist/mcp/dynamic-orchestrator.d.ts +109 -0
- package/dist/mcp/dynamic-orchestrator.js +351 -0
- package/dist/mcp/error-manager.d.ts +254 -0
- package/dist/mcp/error-manager.js +501 -0
- package/dist/mcp/error-recovery.d.ts +158 -0
- package/dist/mcp/error-recovery.js +405 -0
- package/dist/mcp/health-monitor.d.ts +256 -0
- package/dist/mcp/health-monitor.js +621 -0
- package/dist/mcp/orchestrator.d.ts +136 -5
- package/dist/mcp/orchestrator.js +316 -9
- package/dist/mcp/plugins/core/neurolink-mcp.json +15 -15
- package/dist/mcp/registry.d.ts +22 -0
- package/dist/mcp/registry.js +24 -0
- package/dist/mcp/semaphore-manager.d.ts +137 -0
- package/dist/mcp/semaphore-manager.js +329 -0
- package/dist/mcp/session-manager.d.ts +186 -0
- package/dist/mcp/session-manager.js +400 -0
- package/dist/mcp/session-persistence.d.ts +93 -0
- package/dist/mcp/session-persistence.js +299 -0
- package/dist/mcp/transport-manager.d.ts +153 -0
- package/dist/mcp/transport-manager.js +331 -0
- package/dist/mcp/unified-registry.d.ts +42 -1
- package/dist/mcp/unified-registry.js +122 -2
- package/dist/neurolink.d.ts +75 -0
- package/dist/neurolink.js +104 -0
- 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
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
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
|
|
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
|
-
//
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
package/dist/lib/mcp/registry.js
CHANGED
|
@@ -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
|