@juspay/neurolink 7.12.0 → 7.14.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 +12 -0
- package/README.md +90 -25
- package/dist/config/conversationMemoryConfig.js +2 -1
- package/dist/context/ContextManager.d.ts +28 -0
- package/dist/context/ContextManager.js +113 -0
- package/dist/context/config.d.ts +5 -0
- package/dist/context/config.js +42 -0
- package/dist/context/types.d.ts +20 -0
- package/dist/context/types.js +1 -0
- package/dist/context/utils.d.ts +7 -0
- package/dist/context/utils.js +8 -0
- package/dist/core/baseProvider.d.ts +16 -1
- package/dist/core/baseProvider.js +208 -9
- package/dist/core/conversationMemoryManager.js +3 -2
- package/dist/core/factory.js +13 -2
- package/dist/factories/providerFactory.js +5 -11
- package/dist/factories/providerRegistry.js +2 -2
- package/dist/lib/config/conversationMemoryConfig.js +2 -1
- package/dist/lib/context/ContextManager.d.ts +28 -0
- package/dist/lib/context/ContextManager.js +113 -0
- package/dist/lib/context/config.d.ts +5 -0
- package/dist/lib/context/config.js +42 -0
- package/dist/lib/context/types.d.ts +20 -0
- package/dist/lib/context/types.js +1 -0
- package/dist/lib/context/utils.d.ts +7 -0
- package/dist/lib/context/utils.js +8 -0
- package/dist/lib/core/baseProvider.d.ts +16 -1
- package/dist/lib/core/baseProvider.js +208 -9
- package/dist/lib/core/conversationMemoryManager.js +3 -2
- package/dist/lib/core/factory.js +13 -2
- package/dist/lib/factories/providerFactory.js +5 -11
- package/dist/lib/factories/providerRegistry.js +2 -2
- package/dist/lib/mcp/externalServerManager.d.ts +115 -0
- package/dist/lib/mcp/externalServerManager.js +677 -0
- package/dist/lib/mcp/mcpCircuitBreaker.d.ts +184 -0
- package/dist/lib/mcp/mcpCircuitBreaker.js +338 -0
- package/dist/lib/mcp/mcpClientFactory.d.ts +104 -0
- package/dist/lib/mcp/mcpClientFactory.js +416 -0
- package/dist/lib/mcp/toolDiscoveryService.d.ts +192 -0
- package/dist/lib/mcp/toolDiscoveryService.js +578 -0
- package/dist/lib/neurolink.d.ts +128 -16
- package/dist/lib/neurolink.js +555 -49
- package/dist/lib/providers/googleVertex.d.ts +1 -1
- package/dist/lib/providers/googleVertex.js +23 -7
- package/dist/lib/types/externalMcp.d.ts +282 -0
- package/dist/lib/types/externalMcp.js +6 -0
- package/dist/lib/types/generateTypes.d.ts +0 -1
- package/dist/lib/types/index.d.ts +1 -0
- package/dist/mcp/externalServerManager.d.ts +115 -0
- package/dist/mcp/externalServerManager.js +677 -0
- package/dist/mcp/mcpCircuitBreaker.d.ts +184 -0
- package/dist/mcp/mcpCircuitBreaker.js +338 -0
- package/dist/mcp/mcpClientFactory.d.ts +104 -0
- package/dist/mcp/mcpClientFactory.js +416 -0
- package/dist/mcp/toolDiscoveryService.d.ts +192 -0
- package/dist/mcp/toolDiscoveryService.js +578 -0
- package/dist/neurolink.d.ts +128 -16
- package/dist/neurolink.js +555 -49
- package/dist/providers/googleVertex.d.ts +1 -1
- package/dist/providers/googleVertex.js +23 -7
- package/dist/types/externalMcp.d.ts +282 -0
- package/dist/types/externalMcp.js +6 -0
- package/dist/types/generateTypes.d.ts +0 -1
- package/dist/types/index.d.ts +1 -0
- package/package.json +1 -1
|
@@ -157,10 +157,20 @@ export class BaseProvider {
|
|
|
157
157
|
try {
|
|
158
158
|
// Import generateText dynamically to avoid circular dependencies
|
|
159
159
|
const { generateText } = await import("ai");
|
|
160
|
-
// Get ALL available tools (direct + MCP
|
|
160
|
+
// Get ALL available tools (direct + MCP + external from options)
|
|
161
161
|
const shouldUseTools = !options.disableTools && this.supportsTools();
|
|
162
|
-
const
|
|
163
|
-
|
|
162
|
+
const baseTools = shouldUseTools ? await this.getAllTools() : {};
|
|
163
|
+
const tools = shouldUseTools
|
|
164
|
+
? {
|
|
165
|
+
...baseTools,
|
|
166
|
+
...(options.tools || {}), // Include external tools passed from NeuroLink
|
|
167
|
+
}
|
|
168
|
+
: {};
|
|
169
|
+
logger.debug(`[BaseProvider.generate] Tools for ${this.providerName}:`, {
|
|
170
|
+
directTools: Object.keys(baseTools),
|
|
171
|
+
externalTools: Object.keys(options.tools || {}),
|
|
172
|
+
totalTools: Object.keys(tools),
|
|
173
|
+
});
|
|
164
174
|
// EVERY provider uses Vercel AI SDK - no exceptions
|
|
165
175
|
const model = await this.getAISDKModel(); // This method is now REQUIRED
|
|
166
176
|
// Build proper message array with conversation history
|
|
@@ -201,22 +211,66 @@ export class BaseProvider {
|
|
|
201
211
|
const uniqueToolsUsed = [...new Set(toolsUsed)];
|
|
202
212
|
// ✅ Extract tool executions from AI SDK result
|
|
203
213
|
const toolExecutions = [];
|
|
214
|
+
// Create a map of tool calls to their arguments for matching with results
|
|
215
|
+
const toolCallArgsMap = new Map();
|
|
204
216
|
// Extract tool executions from AI SDK result steps
|
|
205
|
-
// Extract tool executions from steps (where tool results are stored)
|
|
206
217
|
if (result.steps &&
|
|
207
218
|
Array.isArray(result.steps)) {
|
|
208
219
|
for (const step of result.steps ||
|
|
209
220
|
[]) {
|
|
210
|
-
//
|
|
211
|
-
|
|
221
|
+
// First, collect tool calls and their arguments
|
|
222
|
+
if (step?.toolCalls && Array.isArray(step.toolCalls)) {
|
|
223
|
+
for (const toolCall of step.toolCalls) {
|
|
224
|
+
const tcRecord = toolCall;
|
|
225
|
+
const toolName = tcRecord.toolName ||
|
|
226
|
+
tcRecord.name ||
|
|
227
|
+
"unknown";
|
|
228
|
+
const toolId = tcRecord.toolCallId ||
|
|
229
|
+
tcRecord.id ||
|
|
230
|
+
toolName;
|
|
231
|
+
// Extract arguments from tool call
|
|
232
|
+
let callArgs = {};
|
|
233
|
+
if (tcRecord.args) {
|
|
234
|
+
callArgs = tcRecord.args;
|
|
235
|
+
}
|
|
236
|
+
else if (tcRecord.arguments) {
|
|
237
|
+
callArgs = tcRecord.arguments;
|
|
238
|
+
}
|
|
239
|
+
else if (tcRecord.parameters) {
|
|
240
|
+
callArgs = tcRecord.parameters;
|
|
241
|
+
}
|
|
242
|
+
toolCallArgsMap.set(toolId, callArgs);
|
|
243
|
+
toolCallArgsMap.set(toolName, callArgs); // Also map by name as fallback
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
// Then, process tool results and match with call arguments
|
|
212
247
|
if (step?.toolResults && Array.isArray(step.toolResults)) {
|
|
213
248
|
for (const toolResult of step.toolResults) {
|
|
214
249
|
const trRecord = toolResult;
|
|
250
|
+
const toolName = trRecord.toolName || "unknown";
|
|
251
|
+
const toolId = trRecord.toolCallId || trRecord.id;
|
|
252
|
+
// Try to get arguments from the tool result first
|
|
253
|
+
let toolArgs = {};
|
|
254
|
+
if (trRecord.args) {
|
|
255
|
+
toolArgs = trRecord.args;
|
|
256
|
+
}
|
|
257
|
+
else if (trRecord.arguments) {
|
|
258
|
+
toolArgs = trRecord.arguments;
|
|
259
|
+
}
|
|
260
|
+
else if (trRecord.parameters) {
|
|
261
|
+
toolArgs = trRecord.parameters;
|
|
262
|
+
}
|
|
263
|
+
else if (trRecord.input) {
|
|
264
|
+
toolArgs = trRecord.input;
|
|
265
|
+
}
|
|
266
|
+
else {
|
|
267
|
+
// Fallback: get arguments from the corresponding tool call
|
|
268
|
+
toolArgs = toolCallArgsMap.get(toolId || toolName) || {};
|
|
269
|
+
}
|
|
215
270
|
toolExecutions.push({
|
|
216
|
-
name:
|
|
217
|
-
input:
|
|
271
|
+
name: toolName,
|
|
272
|
+
input: toolArgs,
|
|
218
273
|
output: trRecord.result || "success",
|
|
219
|
-
duration: 0, // AI SDK doesn't track duration
|
|
220
274
|
});
|
|
221
275
|
}
|
|
222
276
|
}
|
|
@@ -248,6 +302,12 @@ export class BaseProvider {
|
|
|
248
302
|
toolResults: result.toolResults,
|
|
249
303
|
toolsUsed: uniqueToolsUsed,
|
|
250
304
|
toolExecutions, // ✅ Add extracted tool executions
|
|
305
|
+
availableTools: Object.keys(tools).map((name) => ({
|
|
306
|
+
name,
|
|
307
|
+
description: tools[name].description || "No description available",
|
|
308
|
+
parameters: tools[name].parameters || {},
|
|
309
|
+
server: tools[name].serverId || "direct",
|
|
310
|
+
})),
|
|
251
311
|
};
|
|
252
312
|
// Enhanced result with analytics and evaluation
|
|
253
313
|
return await this.enhanceResult(enhancedResult, options, startTime);
|
|
@@ -339,6 +399,71 @@ export class BaseProvider {
|
|
|
339
399
|
// Not an error - custom tools are optional
|
|
340
400
|
}
|
|
341
401
|
}
|
|
402
|
+
// ✅ CRITICAL FIX: Add external MCP tools if SDK has external server manager
|
|
403
|
+
if (this.sdk &&
|
|
404
|
+
this.sdk.externalServerManager &&
|
|
405
|
+
typeof this.sdk.externalServerManager.getAllTools === "function") {
|
|
406
|
+
try {
|
|
407
|
+
logger.debug(`[BaseProvider] Loading external MCP tools from SDK via externalServerManager`);
|
|
408
|
+
const externalTools = this.sdk.externalServerManager.getAllTools();
|
|
409
|
+
logger.debug(`[BaseProvider] Found ${externalTools.length} external MCP tools`, {
|
|
410
|
+
tools: externalTools.map((t) => ({
|
|
411
|
+
name: t.name,
|
|
412
|
+
available: t.isAvailable,
|
|
413
|
+
server: t.serverId,
|
|
414
|
+
})),
|
|
415
|
+
});
|
|
416
|
+
for (const externalTool of externalTools) {
|
|
417
|
+
if (externalTool.isAvailable) {
|
|
418
|
+
logger.debug(`[BaseProvider] Converting external MCP tool: ${externalTool.name} from ${externalTool.serverId}`);
|
|
419
|
+
// Convert to AI SDK tool format
|
|
420
|
+
const { tool: createAISDKTool } = await import("ai");
|
|
421
|
+
const { z } = await import("zod");
|
|
422
|
+
tools[externalTool.name] = createAISDKTool({
|
|
423
|
+
description: externalTool.description ||
|
|
424
|
+
`External MCP tool ${externalTool.name}`,
|
|
425
|
+
parameters: await this.convertMCPSchemaToZod(externalTool.inputSchema),
|
|
426
|
+
execute: async (args) => {
|
|
427
|
+
logger.debug(`[BaseProvider] Executing external MCP tool: ${externalTool.name}`, { args });
|
|
428
|
+
// Execute via SDK's external server manager
|
|
429
|
+
if (this.sdk &&
|
|
430
|
+
this.sdk.externalServerManager &&
|
|
431
|
+
typeof this.sdk.externalServerManager.executeTool ===
|
|
432
|
+
"function") {
|
|
433
|
+
return await this.sdk.externalServerManager.executeTool(externalTool.serverId, externalTool.name, args);
|
|
434
|
+
}
|
|
435
|
+
else {
|
|
436
|
+
throw new Error(`Cannot execute external MCP tool: SDK externalServerManager.executeTool not available`);
|
|
437
|
+
}
|
|
438
|
+
},
|
|
439
|
+
});
|
|
440
|
+
logger.debug(`[BaseProvider] Successfully added external MCP tool: ${externalTool.name}`);
|
|
441
|
+
}
|
|
442
|
+
else {
|
|
443
|
+
logger.debug(`[BaseProvider] Skipping unavailable external MCP tool: ${externalTool.name}`);
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
logger.debug(`[BaseProvider] External MCP tools loading complete`, {
|
|
447
|
+
totalExternalTools: externalTools.length,
|
|
448
|
+
availableExternalTools: externalTools.filter((t) => t.isAvailable)
|
|
449
|
+
.length,
|
|
450
|
+
addedToTools: externalTools.filter((t) => t.isAvailable).length,
|
|
451
|
+
});
|
|
452
|
+
}
|
|
453
|
+
catch (error) {
|
|
454
|
+
logger.error(`[BaseProvider] Failed to load external MCP tools for ${this.providerName}:`, error);
|
|
455
|
+
// Not an error - external tools are optional
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
else {
|
|
459
|
+
logger.debug(`[BaseProvider] No external MCP tools interface available`, {
|
|
460
|
+
hasSDK: !!this.sdk,
|
|
461
|
+
hasExternalServerManager: this.sdk && !!this.sdk.externalServerManager,
|
|
462
|
+
hasGetAllTools: this.sdk &&
|
|
463
|
+
this.sdk.externalServerManager &&
|
|
464
|
+
typeof this.sdk.externalServerManager.getAllTools === "function",
|
|
465
|
+
});
|
|
466
|
+
}
|
|
342
467
|
// MCP tools loading simplified - removed functionCalling dependency
|
|
343
468
|
if (!this.mcpTools) {
|
|
344
469
|
// Set empty tools object - MCP tools are handled at a higher level
|
|
@@ -351,6 +476,80 @@ export class BaseProvider {
|
|
|
351
476
|
logger.debug(`[BaseProvider] getAllTools returning tools: ${Object.keys(tools).join(", ")}`);
|
|
352
477
|
return tools;
|
|
353
478
|
}
|
|
479
|
+
/**
|
|
480
|
+
* Convert MCP JSON Schema to Zod schema for AI SDK tools
|
|
481
|
+
* Handles common MCP schema patterns safely
|
|
482
|
+
*/
|
|
483
|
+
async convertMCPSchemaToZod(inputSchema) {
|
|
484
|
+
const { z } = await import("zod");
|
|
485
|
+
if (!inputSchema || typeof inputSchema !== "object") {
|
|
486
|
+
return z.object({});
|
|
487
|
+
}
|
|
488
|
+
try {
|
|
489
|
+
const schema = inputSchema;
|
|
490
|
+
const zodFields = {};
|
|
491
|
+
// Handle JSON Schema properties
|
|
492
|
+
if (schema.properties && typeof schema.properties === "object") {
|
|
493
|
+
const required = new Set(Array.isArray(schema.required) ? schema.required : []);
|
|
494
|
+
for (const [propName, propDef] of Object.entries(schema.properties)) {
|
|
495
|
+
const prop = propDef;
|
|
496
|
+
let zodType;
|
|
497
|
+
// Convert based on JSON Schema type
|
|
498
|
+
switch (prop.type) {
|
|
499
|
+
case "string":
|
|
500
|
+
zodType = z.string();
|
|
501
|
+
if (prop.description) {
|
|
502
|
+
zodType = zodType.describe(prop.description);
|
|
503
|
+
}
|
|
504
|
+
break;
|
|
505
|
+
case "number":
|
|
506
|
+
case "integer":
|
|
507
|
+
zodType = z.number();
|
|
508
|
+
if (prop.description) {
|
|
509
|
+
zodType = zodType.describe(prop.description);
|
|
510
|
+
}
|
|
511
|
+
break;
|
|
512
|
+
case "boolean":
|
|
513
|
+
zodType = z.boolean();
|
|
514
|
+
if (prop.description) {
|
|
515
|
+
zodType = zodType.describe(prop.description);
|
|
516
|
+
}
|
|
517
|
+
break;
|
|
518
|
+
case "array":
|
|
519
|
+
zodType = z.array(z.unknown());
|
|
520
|
+
if (prop.description) {
|
|
521
|
+
zodType = zodType.describe(prop.description);
|
|
522
|
+
}
|
|
523
|
+
break;
|
|
524
|
+
case "object":
|
|
525
|
+
zodType = z.object({});
|
|
526
|
+
if (prop.description) {
|
|
527
|
+
zodType = zodType.describe(prop.description);
|
|
528
|
+
}
|
|
529
|
+
break;
|
|
530
|
+
default:
|
|
531
|
+
// Unknown type, use string as fallback
|
|
532
|
+
zodType = z.string();
|
|
533
|
+
if (prop.description) {
|
|
534
|
+
zodType = zodType.describe(prop.description);
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
// Make optional if not required
|
|
538
|
+
if (!required.has(propName)) {
|
|
539
|
+
zodType = zodType.optional();
|
|
540
|
+
}
|
|
541
|
+
zodFields[propName] = zodType;
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
return Object.keys(zodFields).length > 0
|
|
545
|
+
? z.object(zodFields)
|
|
546
|
+
: z.object({});
|
|
547
|
+
}
|
|
548
|
+
catch (error) {
|
|
549
|
+
logger.warn(`Failed to convert MCP schema to Zod, using empty schema:`, error);
|
|
550
|
+
return z.object({});
|
|
551
|
+
}
|
|
552
|
+
}
|
|
354
553
|
/**
|
|
355
554
|
* Set session context for MCP tools
|
|
356
555
|
*/
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Handles in-memory conversation storage, session management, and context injection
|
|
4
4
|
*/
|
|
5
5
|
import { ConversationMemoryError } from "../types/conversationTypes.js";
|
|
6
|
-
import { DEFAULT_MAX_TURNS_PER_SESSION, DEFAULT_MAX_SESSIONS, MESSAGES_PER_TURN } from "../config/conversationMemoryConfig.js";
|
|
6
|
+
import { DEFAULT_MAX_TURNS_PER_SESSION, DEFAULT_MAX_SESSIONS, MESSAGES_PER_TURN, } from "../config/conversationMemoryConfig.js";
|
|
7
7
|
import { logger } from "../utils/logger.js";
|
|
8
8
|
export class ConversationMemoryManager {
|
|
9
9
|
sessions = new Map();
|
|
@@ -49,7 +49,8 @@ export class ConversationMemoryManager {
|
|
|
49
49
|
session.messages.push({ role: "user", content: userMessage }, { role: "assistant", content: aiResponse });
|
|
50
50
|
session.lastActivity = Date.now();
|
|
51
51
|
// Enforce per-session turn limit (each turn = MESSAGES_PER_TURN messages: user + assistant)
|
|
52
|
-
const maxMessages = (this.config.maxTurnsPerSession || DEFAULT_MAX_TURNS_PER_SESSION) *
|
|
52
|
+
const maxMessages = (this.config.maxTurnsPerSession || DEFAULT_MAX_TURNS_PER_SESSION) *
|
|
53
|
+
MESSAGES_PER_TURN;
|
|
53
54
|
if (session.messages.length > maxMessages) {
|
|
54
55
|
session.messages = session.messages.slice(-maxMessages);
|
|
55
56
|
}
|
package/dist/lib/core/factory.js
CHANGED
|
@@ -109,13 +109,24 @@ export class AIProviderFactory {
|
|
|
109
109
|
const finalModelName = resolvedModelName === "default" || resolvedModelName === null
|
|
110
110
|
? undefined
|
|
111
111
|
: resolvedModelName;
|
|
112
|
-
|
|
112
|
+
// ✅ CRITICAL FIX: Pass external MCP tools interface to BaseProvider
|
|
113
|
+
let finalSdk = sdk;
|
|
114
|
+
if (sdk && typeof sdk.getExternalMCPTools === "function") {
|
|
115
|
+
finalSdk = {
|
|
116
|
+
...sdk,
|
|
117
|
+
externalServerManager: {
|
|
118
|
+
getAllTools: () => sdk.getExternalMCPTools(),
|
|
119
|
+
executeTool: (serverId, toolName, params) => sdk.executeExternalMCPTool(serverId, toolName, params),
|
|
120
|
+
},
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
// Create provider with enhanced SDK
|
|
124
|
+
const provider = await ProviderFactory.createProvider(normalizedName, finalModelName, finalSdk);
|
|
113
125
|
logger.debug(componentIdentifier, "Pure factory pattern provider created", {
|
|
114
126
|
providerName: normalizedName,
|
|
115
127
|
modelName: finalModelName,
|
|
116
128
|
factoryUsed: true,
|
|
117
129
|
});
|
|
118
|
-
// PURE FACTORY PATTERN: All providers handled by ProviderFactory - no switch statements needed
|
|
119
130
|
// Wrap with MCP if enabled
|
|
120
131
|
if (enableMCP) {
|
|
121
132
|
try {
|
|
@@ -46,22 +46,16 @@ export class ProviderFactory {
|
|
|
46
46
|
model = model || registration.defaultModel;
|
|
47
47
|
}
|
|
48
48
|
try {
|
|
49
|
-
// Try calling as factory function first, then fallback to constructor
|
|
50
49
|
let result;
|
|
51
50
|
try {
|
|
52
|
-
// Try as factory function
|
|
53
|
-
result = registration.constructor(model, providerName, sdk);
|
|
51
|
+
// Try as async factory function first (most providers are async functions)
|
|
52
|
+
result = await registration.constructor(model, providerName, sdk);
|
|
54
53
|
}
|
|
55
|
-
catch (
|
|
56
|
-
// Fallback to constructor
|
|
54
|
+
catch (functionError) {
|
|
55
|
+
// Fallback to constructor - ensure parameters are maintained
|
|
57
56
|
result = new registration.constructor(model, providerName, sdk);
|
|
58
57
|
}
|
|
59
|
-
//
|
|
60
|
-
if (result &&
|
|
61
|
-
typeof result === "object" &&
|
|
62
|
-
typeof result.then === "function") {
|
|
63
|
-
result = await result;
|
|
64
|
-
}
|
|
58
|
+
// Return result (no need to await again if already awaited in try block)
|
|
65
59
|
return result;
|
|
66
60
|
}
|
|
67
61
|
catch (error) {
|
|
@@ -52,9 +52,9 @@ export class ProviderRegistry {
|
|
|
52
52
|
process.env.AZURE_OPENAI_DEPLOYMENT_ID ||
|
|
53
53
|
"gpt-4o-mini", ["azure", "azureOpenai"]);
|
|
54
54
|
// Register Google Vertex AI provider
|
|
55
|
-
ProviderFactory.registerProvider(AIProviderName.VERTEX, async (modelName) => {
|
|
55
|
+
ProviderFactory.registerProvider(AIProviderName.VERTEX, async (modelName, providerName, sdk) => {
|
|
56
56
|
const { GoogleVertexProvider } = await import("../providers/googleVertex.js");
|
|
57
|
-
return new GoogleVertexProvider(modelName);
|
|
57
|
+
return new GoogleVertexProvider(modelName, providerName, sdk);
|
|
58
58
|
}, "claude-sonnet-4@20250514", ["vertex", "googleVertex"]);
|
|
59
59
|
// Register Hugging Face provider (Unified Router implementation)
|
|
60
60
|
ProviderFactory.registerProvider(AIProviderName.HUGGINGFACE, async (modelName) => {
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* External MCP Server Manager
|
|
3
|
+
* Handles lifecycle management of external MCP servers including:
|
|
4
|
+
* - Process spawning and management
|
|
5
|
+
* - Health monitoring and automatic restart
|
|
6
|
+
* - Connection management and cleanup
|
|
7
|
+
* - Tool discovery and registration
|
|
8
|
+
*/
|
|
9
|
+
import { EventEmitter } from "events";
|
|
10
|
+
import { ToolDiscoveryService } from "./toolDiscoveryService.js";
|
|
11
|
+
import type { ExternalMCPServerConfig, ExternalMCPServerInstance, ExternalMCPServerHealth, ExternalMCPConfigValidation, ExternalMCPOperationResult, ExternalMCPManagerConfig, ExternalMCPToolInfo } from "../types/externalMcp.js";
|
|
12
|
+
/**
|
|
13
|
+
* ExternalServerManager
|
|
14
|
+
* Core class for managing external MCP servers
|
|
15
|
+
*/
|
|
16
|
+
export declare class ExternalServerManager extends EventEmitter {
|
|
17
|
+
private servers;
|
|
18
|
+
private config;
|
|
19
|
+
private isShuttingDown;
|
|
20
|
+
private toolDiscovery;
|
|
21
|
+
constructor(config?: ExternalMCPManagerConfig);
|
|
22
|
+
/**
|
|
23
|
+
* Validate external MCP server configuration
|
|
24
|
+
*/
|
|
25
|
+
validateConfig(config: ExternalMCPServerConfig): ExternalMCPConfigValidation;
|
|
26
|
+
/**
|
|
27
|
+
* Add a new external MCP server
|
|
28
|
+
*/
|
|
29
|
+
addServer(serverId: string, config: ExternalMCPServerConfig): Promise<ExternalMCPOperationResult<ExternalMCPServerInstance>>;
|
|
30
|
+
/**
|
|
31
|
+
* Remove an external MCP server
|
|
32
|
+
*/
|
|
33
|
+
removeServer(serverId: string): Promise<ExternalMCPOperationResult<void>>;
|
|
34
|
+
/**
|
|
35
|
+
* Start an external MCP server
|
|
36
|
+
*/
|
|
37
|
+
private startServer;
|
|
38
|
+
/**
|
|
39
|
+
* Stop an external MCP server
|
|
40
|
+
*/
|
|
41
|
+
private stopServer;
|
|
42
|
+
/**
|
|
43
|
+
* Update server status and emit events
|
|
44
|
+
*/
|
|
45
|
+
private updateServerStatus;
|
|
46
|
+
/**
|
|
47
|
+
* Handle server errors
|
|
48
|
+
*/
|
|
49
|
+
private handleServerError;
|
|
50
|
+
/**
|
|
51
|
+
* Handle server disconnection
|
|
52
|
+
*/
|
|
53
|
+
private handleServerDisconnection;
|
|
54
|
+
/**
|
|
55
|
+
* Schedule server restart with exponential backoff
|
|
56
|
+
*/
|
|
57
|
+
private scheduleRestart;
|
|
58
|
+
/**
|
|
59
|
+
* Start health monitoring for a server
|
|
60
|
+
*/
|
|
61
|
+
private startHealthMonitoring;
|
|
62
|
+
/**
|
|
63
|
+
* Perform health check on a server
|
|
64
|
+
*/
|
|
65
|
+
private performHealthCheck;
|
|
66
|
+
/**
|
|
67
|
+
* Get server instance
|
|
68
|
+
*/
|
|
69
|
+
getServer(serverId: string): ExternalMCPServerInstance | undefined;
|
|
70
|
+
/**
|
|
71
|
+
* Get all servers
|
|
72
|
+
*/
|
|
73
|
+
getAllServers(): Map<string, ExternalMCPServerInstance>;
|
|
74
|
+
/**
|
|
75
|
+
* Get server statuses
|
|
76
|
+
*/
|
|
77
|
+
getServerStatuses(): ExternalMCPServerHealth[];
|
|
78
|
+
/**
|
|
79
|
+
* Shutdown all servers
|
|
80
|
+
*/
|
|
81
|
+
shutdown(): Promise<void>;
|
|
82
|
+
/**
|
|
83
|
+
* Get manager statistics
|
|
84
|
+
*/
|
|
85
|
+
getStatistics(): {
|
|
86
|
+
totalServers: number;
|
|
87
|
+
connectedServers: number;
|
|
88
|
+
failedServers: number;
|
|
89
|
+
totalTools: number;
|
|
90
|
+
totalConnections: number;
|
|
91
|
+
totalErrors: number;
|
|
92
|
+
};
|
|
93
|
+
/**
|
|
94
|
+
* Discover tools from a server
|
|
95
|
+
*/
|
|
96
|
+
private discoverServerTools;
|
|
97
|
+
/**
|
|
98
|
+
* Execute a tool on a specific server
|
|
99
|
+
*/
|
|
100
|
+
executeTool(serverId: string, toolName: string, parameters: Record<string, any>, options?: {
|
|
101
|
+
timeout?: number;
|
|
102
|
+
}): Promise<any>;
|
|
103
|
+
/**
|
|
104
|
+
* Get all tools from all servers
|
|
105
|
+
*/
|
|
106
|
+
getAllTools(): ExternalMCPToolInfo[];
|
|
107
|
+
/**
|
|
108
|
+
* Get tools for a specific server
|
|
109
|
+
*/
|
|
110
|
+
getServerTools(serverId: string): ExternalMCPToolInfo[];
|
|
111
|
+
/**
|
|
112
|
+
* Get tool discovery service
|
|
113
|
+
*/
|
|
114
|
+
getToolDiscovery(): ToolDiscoveryService;
|
|
115
|
+
}
|