@juspay/neurolink 7.14.0 → 7.14.1

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 (111) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/dist/agent/directTools.d.ts +3 -3
  3. package/dist/agent/directTools.js +1 -1
  4. package/dist/cli/commands/mcp.js +67 -207
  5. package/dist/cli/factories/commandFactory.js +7 -1
  6. package/dist/cli/utils/interactiveSetup.js +1 -1
  7. package/dist/core/baseProvider.d.ts +6 -40
  8. package/dist/core/baseProvider.js +102 -75
  9. package/dist/core/dynamicModels.d.ts +14 -14
  10. package/dist/core/dynamicModels.js +1 -1
  11. package/dist/core/evaluation.js +1 -1
  12. package/dist/core/factory.js +1 -12
  13. package/dist/index.d.ts +5 -4
  14. package/dist/index.js +1 -1
  15. package/dist/lib/agent/directTools.js +1 -1
  16. package/dist/lib/core/baseProvider.d.ts +6 -40
  17. package/dist/lib/core/baseProvider.js +102 -75
  18. package/dist/lib/core/dynamicModels.js +1 -1
  19. package/dist/lib/core/evaluation.js +1 -1
  20. package/dist/lib/core/factory.js +1 -12
  21. package/dist/lib/index.d.ts +5 -4
  22. package/dist/lib/index.js +1 -1
  23. package/dist/lib/mcp/externalServerManager.d.ts +46 -13
  24. package/dist/lib/mcp/externalServerManager.js +393 -32
  25. package/dist/lib/mcp/mcpClientFactory.d.ts +5 -4
  26. package/dist/lib/mcp/mcpClientFactory.js +8 -3
  27. package/dist/lib/mcp/toolDiscoveryService.d.ts +1 -0
  28. package/dist/lib/mcp/toolDiscoveryService.js +76 -8
  29. package/dist/lib/mcp/toolRegistry.d.ts +15 -11
  30. package/dist/lib/mcp/toolRegistry.js +118 -55
  31. package/dist/lib/models/modelResolver.js +1 -1
  32. package/dist/lib/neurolink.d.ts +32 -31
  33. package/dist/lib/neurolink.js +173 -210
  34. package/dist/lib/providers/googleVertex.d.ts +6 -0
  35. package/dist/lib/providers/googleVertex.js +11 -0
  36. package/dist/lib/providers/huggingFace.js +1 -1
  37. package/dist/lib/providers/mistral.js +3 -3
  38. package/dist/lib/providers/ollama.js +1 -1
  39. package/dist/lib/providers/openAI.d.ts +3 -2
  40. package/dist/lib/providers/openAI.js +2 -2
  41. package/dist/lib/providers/openaiCompatible.d.ts +1 -1
  42. package/dist/lib/providers/openaiCompatible.js +2 -2
  43. package/dist/lib/providers/sagemaker/config.js +1 -1
  44. package/dist/lib/sdk/toolRegistration.d.ts +4 -13
  45. package/dist/lib/sdk/toolRegistration.js +19 -66
  46. package/dist/lib/types/cli.d.ts +0 -1
  47. package/dist/lib/types/cli.js +0 -1
  48. package/dist/lib/types/common.d.ts +1 -2
  49. package/dist/lib/types/common.js +0 -1
  50. package/dist/lib/types/contextTypes.d.ts +1 -1
  51. package/dist/lib/types/contextTypes.js +3 -3
  52. package/dist/lib/types/externalMcp.d.ts +6 -0
  53. package/dist/lib/types/externalMcp.js +1 -0
  54. package/dist/lib/types/index.d.ts +2 -3
  55. package/dist/lib/types/index.js +0 -1
  56. package/dist/lib/types/mcpTypes.d.ts +53 -99
  57. package/dist/lib/types/providers.d.ts +0 -1
  58. package/dist/lib/types/providers.js +0 -1
  59. package/dist/lib/types/tools.d.ts +2 -2
  60. package/dist/lib/types/tools.js +2 -2
  61. package/dist/lib/utils/factoryProcessing.js +1 -1
  62. package/dist/lib/utils/mcpDefaults.d.ts +54 -0
  63. package/dist/lib/utils/mcpDefaults.js +125 -0
  64. package/dist/lib/utils/providerConfig.d.ts +1 -1
  65. package/dist/lib/utils/providerConfig.js +2 -2
  66. package/dist/lib/utils/providerHealth.js +6 -6
  67. package/dist/mcp/externalServerManager.d.ts +46 -13
  68. package/dist/mcp/externalServerManager.js +393 -32
  69. package/dist/mcp/mcpClientFactory.d.ts +5 -4
  70. package/dist/mcp/mcpClientFactory.js +8 -3
  71. package/dist/mcp/toolDiscoveryService.d.ts +1 -0
  72. package/dist/mcp/toolDiscoveryService.js +76 -8
  73. package/dist/mcp/toolRegistry.d.ts +15 -11
  74. package/dist/mcp/toolRegistry.js +118 -55
  75. package/dist/models/modelResolver.js +1 -1
  76. package/dist/neurolink.d.ts +32 -31
  77. package/dist/neurolink.js +173 -210
  78. package/dist/providers/googleVertex.d.ts +6 -0
  79. package/dist/providers/googleVertex.js +11 -0
  80. package/dist/providers/huggingFace.js +1 -1
  81. package/dist/providers/mistral.js +3 -3
  82. package/dist/providers/ollama.js +1 -1
  83. package/dist/providers/openAI.d.ts +3 -2
  84. package/dist/providers/openAI.js +2 -2
  85. package/dist/providers/openaiCompatible.d.ts +1 -1
  86. package/dist/providers/openaiCompatible.js +2 -2
  87. package/dist/providers/sagemaker/config.js +1 -1
  88. package/dist/sdk/toolRegistration.d.ts +4 -13
  89. package/dist/sdk/toolRegistration.js +19 -66
  90. package/dist/types/cli.d.ts +0 -1
  91. package/dist/types/cli.js +0 -1
  92. package/dist/types/common.d.ts +1 -2
  93. package/dist/types/common.js +0 -1
  94. package/dist/types/contextTypes.d.ts +1 -1
  95. package/dist/types/contextTypes.js +3 -3
  96. package/dist/types/externalMcp.d.ts +6 -0
  97. package/dist/types/externalMcp.js +1 -0
  98. package/dist/types/index.d.ts +2 -3
  99. package/dist/types/index.js +0 -1
  100. package/dist/types/mcpTypes.d.ts +53 -99
  101. package/dist/types/providers.d.ts +0 -1
  102. package/dist/types/providers.js +0 -1
  103. package/dist/types/tools.d.ts +2 -2
  104. package/dist/types/tools.js +2 -2
  105. package/dist/utils/factoryProcessing.js +1 -1
  106. package/dist/utils/mcpDefaults.d.ts +54 -0
  107. package/dist/utils/mcpDefaults.js +125 -0
  108. package/dist/utils/providerConfig.d.ts +1 -1
  109. package/dist/utils/providerConfig.js +2 -2
  110. package/dist/utils/providerHealth.js +6 -6
  111. package/package.json +1 -1
@@ -21,7 +21,7 @@ import { toolRegistry } from "./mcp/toolRegistry.js";
21
21
  import { logger } from "./utils/logger.js";
22
22
  import { getBestProvider } from "./utils/providerUtils.js";
23
23
  import { ProviderRegistry } from "./factories/providerRegistry.js";
24
- import { validateTool, createMCPServerFromTools, } from "./sdk/toolRegistration.js";
24
+ import { createCustomToolServerInfo, detectCategory, } from "./utils/mcpDefaults.js";
25
25
  // Factory processing imports
26
26
  import { processFactoryOptions, enhanceTextGenerationOptions, validateFactoryConfig, processStreamingFactoryOptions, createCleanStreamOptions, } from "./utils/factoryProcessing.js";
27
27
  // Enhanced error handling imports
@@ -37,9 +37,7 @@ export class NeuroLink {
37
37
  mcpInitialized = false;
38
38
  emitter = new EventEmitter();
39
39
  contextManager = null;
40
- // Tool registration support
41
- customTools = new Map();
42
- inMemoryServers = new Map();
40
+ autoDiscoveredServerInfos = [];
43
41
  // External MCP server management
44
42
  externalServerManager;
45
43
  // Enhanced error handling support
@@ -76,12 +74,14 @@ export class NeuroLink {
76
74
  maxTurnsPerSession: memoryConfig.maxTurnsPerSession,
77
75
  });
78
76
  }
79
- // Initialize external server manager
77
+ // Initialize external server manager with main registry integration
80
78
  this.externalServerManager = new ExternalServerManager({
81
79
  maxServers: 20,
82
80
  defaultTimeout: 15000,
83
81
  enableAutoRestart: true,
84
82
  enablePerformanceMonitoring: true,
83
+ }, {
84
+ enableMainRegistryIntegration: true, // Enable integration with main toolRegistry
85
85
  });
86
86
  // Forward external server events
87
87
  this.externalServerManager.on("connected", (event) => {
@@ -127,6 +127,26 @@ export class NeuroLink {
127
127
  ]);
128
128
  // Register all providers with lazy loading support
129
129
  await ProviderRegistry.registerAllProviders();
130
+ // Load MCP configuration from .mcp-config.json using ExternalServerManager
131
+ try {
132
+ const configResult = await this.externalServerManager.loadMCPConfiguration();
133
+ mcpLogger.debug("[NeuroLink] MCP configuration loaded successfully", {
134
+ serversLoaded: configResult.serversLoaded,
135
+ errors: configResult.errors.length,
136
+ });
137
+ if (configResult.errors.length > 0) {
138
+ mcpLogger.warn("[NeuroLink] Some MCP servers failed to load", {
139
+ errors: configResult.errors,
140
+ });
141
+ }
142
+ }
143
+ catch (configError) {
144
+ mcpLogger.warn("[NeuroLink] MCP configuration loading failed", {
145
+ error: configError instanceof Error
146
+ ? configError.message
147
+ : String(configError),
148
+ });
149
+ }
130
150
  this.mcpInitialized = true;
131
151
  // Monitor memory usage and provide cleanup suggestions
132
152
  const endMemory = MemoryManager.getMemoryUsageMB();
@@ -416,7 +436,7 @@ export class NeuroLink {
416
436
  this);
417
437
  // Enable tool execution for the provider using BaseProvider method
418
438
  provider.setupToolExecutor({
419
- customTools: this.customTools,
439
+ customTools: this.getCustomTools(),
420
440
  executeTool: this.executeTool.bind(this),
421
441
  }, functionTag);
422
442
  const result = await provider.generate({
@@ -502,7 +522,7 @@ export class NeuroLink {
502
522
  this);
503
523
  // Enable tool execution for direct provider generation using BaseProvider method
504
524
  provider.setupToolExecutor({
505
- customTools: this.customTools,
525
+ customTools: this.getCustomTools(),
506
526
  executeTool: this.executeTool.bind(this),
507
527
  }, functionTag);
508
528
  const result = await provider.generate({
@@ -604,7 +624,7 @@ export class NeuroLink {
604
624
  for (const result of toolResults) {
605
625
  if (result && typeof result === "object") {
606
626
  enhancedPrompt += `\n\nTool Results:\n`;
607
- // Handle any structured result generically
627
+ // Handle structured result generically
608
628
  try {
609
629
  const resultStr = typeof result === "string"
610
630
  ? result
@@ -714,7 +734,7 @@ export class NeuroLink {
714
734
  const provider = await AIProviderFactory.createBestProvider(providerName, options.model, true, this);
715
735
  // Enable tool execution for streaming using BaseProvider method
716
736
  provider.setupToolExecutor({
717
- customTools: this.customTools,
737
+ customTools: this.getCustomTools(),
718
738
  executeTool: this.executeTool.bind(this),
719
739
  }, functionTag);
720
740
  // Create clean options for provider (remove factoryConfig)
@@ -770,7 +790,7 @@ export class NeuroLink {
770
790
  this);
771
791
  // Enable tool execution for fallback streaming using BaseProvider method
772
792
  provider.setupToolExecutor({
773
- customTools: this.customTools,
793
+ customTools: this.getCustomTools(),
774
794
  executeTool: this.executeTool.bind(this),
775
795
  }, functionTag);
776
796
  // Create clean options for fallback provider (remove factoryConfig)
@@ -824,7 +844,7 @@ export class NeuroLink {
824
844
  /**
825
845
  * Register a custom tool that will be available to all AI providers
826
846
  * @param name - Unique name for the tool
827
- * @param tool - Tool configuration
847
+ * @param tool - Tool in MCPExecutableTool format (unified MCP protocol type)
828
848
  */
829
849
  registerTool(name, tool) {
830
850
  // Emit tool registration start event
@@ -833,18 +853,10 @@ export class NeuroLink {
833
853
  timestamp: Date.now(),
834
854
  });
835
855
  try {
836
- // Validate tool configuration
837
- validateTool(name, tool);
838
- // Store the tool
839
- this.customTools.set(name, tool);
840
- // Convert to MCP server format for integration
841
- const serverId = `custom-tool-${name}`;
842
- const mcpServer = createMCPServerFromTools(serverId, { [name]: tool }, {
843
- title: `Custom Tool: ${name}`,
844
- category: "custom",
845
- });
846
- // Store as in-memory server
847
- this.inMemoryServers.set(serverId, mcpServer);
856
+ // SMART DEFAULTS: Use utility to eliminate boilerplate creation
857
+ const mcpServerInfo = createCustomToolServerInfo(name, tool);
858
+ // Register with toolRegistry using MCPServerInfo directly
859
+ toolRegistry.registerServer(mcpServerInfo);
848
860
  logger.info(`Registered custom tool: ${name}`);
849
861
  // Emit tool registration success event
850
862
  this.emitter.emit("tools-register:end", {
@@ -860,10 +872,10 @@ export class NeuroLink {
860
872
  }
861
873
  /**
862
874
  * Register multiple tools at once - Supports both object and array formats
863
- * @param tools - Object mapping tool names to configurations OR Array of tools with names
875
+ * @param tools - Object mapping tool names to MCPExecutableTool format OR Array of tools with names
864
876
  *
865
- * Object format (existing): { toolName: SimpleTool, ... }
866
- * Array format (Lighthouse compatible): [{ name: string, tool: SimpleTool }, ...]
877
+ * Object format (existing): { toolName: MCPExecutableTool, ... }
878
+ * Array format (Lighthouse compatible): [{ name: string, tool: MCPExecutableTool }, ...]
867
879
  */
868
880
  registerTools(tools) {
869
881
  if (Array.isArray(tools)) {
@@ -885,40 +897,57 @@ export class NeuroLink {
885
897
  * @returns true if the tool was removed, false if it didn't exist
886
898
  */
887
899
  unregisterTool(name) {
888
- const removed = this.customTools.delete(name);
900
+ const serverId = `custom-tool-${name}`;
901
+ const removed = toolRegistry.unregisterServer(serverId);
889
902
  if (removed) {
890
- const serverId = `custom-tool-${name}`;
891
- this.inMemoryServers.delete(serverId);
892
903
  logger.info(`Unregistered custom tool: ${name}`);
893
904
  }
894
905
  return removed;
895
906
  }
896
907
  /**
897
908
  * Get all registered custom tools
898
- * @returns Map of tool names to configurations
909
+ * @returns Map of tool names to MCPExecutableTool format
899
910
  */
900
911
  getCustomTools() {
901
- return new Map(this.customTools);
912
+ // Get tools from toolRegistry with smart category detection
913
+ const customTools = toolRegistry.getToolsByCategory(detectCategory({ isCustomTool: true }));
914
+ const toolMap = new Map();
915
+ for (const tool of customTools) {
916
+ // Return MCPServerInfo.tools format directly - no conversion needed
917
+ toolMap.set(tool.name, {
918
+ name: tool.name,
919
+ description: tool.description || "",
920
+ inputSchema: {},
921
+ execute: async (args, context) => {
922
+ // Type guard to ensure context is compatible with ExecutionContext
923
+ const executionContext = context && typeof context === "object" && context !== null
924
+ ? context
925
+ : undefined;
926
+ return await toolRegistry.executeTool(tool.name, args, executionContext);
927
+ },
928
+ });
929
+ }
930
+ return toolMap;
902
931
  }
903
932
  /**
904
933
  * Add an in-memory MCP server (from git diff)
905
934
  * Allows registration of pre-instantiated server objects
906
935
  * @param serverId - Unique identifier for the server
907
- * @param config - Server configuration
936
+ * @param serverInfo - Server configuration
908
937
  */
909
- async addInMemoryMCPServer(serverId, config) {
938
+ async addInMemoryMCPServer(serverId, serverInfo) {
910
939
  try {
911
940
  mcpLogger.debug(`[NeuroLink] Registering in-memory MCP server: ${serverId}`);
912
- // Validate server configuration
913
- if (!config.server) {
914
- throw new Error(`Server object is required for ${serverId}`);
941
+ // Initialize tools array if not provided
942
+ if (!serverInfo.tools) {
943
+ serverInfo.tools = [];
915
944
  }
916
- // Store in registry
917
- this.inMemoryServers.set(serverId, config);
945
+ // ZERO CONVERSIONS: Pass MCPServerInfo directly to toolRegistry
946
+ await toolRegistry.registerServer(serverInfo);
918
947
  mcpLogger.info(`[NeuroLink] Successfully registered in-memory server: ${serverId}`, {
919
- category: config.category,
920
- provider: config.metadata?.provider,
921
- version: config.metadata?.version,
948
+ category: serverInfo.metadata?.category,
949
+ provider: serverInfo.metadata?.provider,
950
+ version: serverInfo.metadata?.version,
922
951
  });
923
952
  }
924
953
  catch (error) {
@@ -928,10 +957,41 @@ export class NeuroLink {
928
957
  }
929
958
  /**
930
959
  * Get all registered in-memory servers
931
- * @returns Map of server IDs to configurations
960
+ * @returns Map of server IDs to MCPServerInfo
932
961
  */
933
962
  getInMemoryServers() {
934
- return new Map(this.inMemoryServers);
963
+ // Get in-memory servers from toolRegistry
964
+ const serverInfos = toolRegistry.getBuiltInServerInfos();
965
+ const serverMap = new Map();
966
+ for (const serverInfo of serverInfos) {
967
+ if (detectCategory({
968
+ existingCategory: serverInfo.metadata?.category,
969
+ serverId: serverInfo.id,
970
+ }) === "in-memory") {
971
+ serverMap.set(serverInfo.id, serverInfo);
972
+ }
973
+ }
974
+ return serverMap;
975
+ }
976
+ /**
977
+ * Get in-memory servers as MCPServerInfo - ZERO conversion needed
978
+ * Now fetches from centralized tool registry instead of local duplication
979
+ * @returns Array of MCPServerInfo
980
+ */
981
+ getInMemoryServerInfos() {
982
+ // Get in-memory servers from centralized tool registry
983
+ const allServers = toolRegistry.getBuiltInServerInfos();
984
+ return allServers.filter((server) => detectCategory({
985
+ existingCategory: server.metadata?.category,
986
+ serverId: server.id,
987
+ }) === "in-memory");
988
+ }
989
+ /**
990
+ * Get auto-discovered servers as MCPServerInfo - ZERO conversion needed
991
+ * @returns Array of MCPServerInfo
992
+ */
993
+ getAutoDiscoveredServerInfos() {
994
+ return this.autoDiscoveredServerInfos;
935
995
  }
936
996
  /**
937
997
  * Execute a specific tool by name with robust error handling
@@ -1050,8 +1110,8 @@ export class NeuroLink {
1050
1110
  structuredError = ErrorFactory.toolTimeout(toolName, finalOptions.timeout);
1051
1111
  }
1052
1112
  else if (error.message.includes("not found")) {
1053
- const availableTools = Array.from(this.customTools.keys());
1054
- structuredError = ErrorFactory.toolNotFound(toolName, availableTools);
1113
+ const availableTools = await this.getAllAvailableTools();
1114
+ structuredError = ErrorFactory.toolNotFound(toolName, availableTools.map((t) => t.name));
1055
1115
  }
1056
1116
  else if (error.message.includes("validation") ||
1057
1117
  error.message.includes("parameter")) {
@@ -1093,57 +1153,6 @@ export class NeuroLink {
1093
1153
  */
1094
1154
  async executeToolInternal(toolName, params, options) {
1095
1155
  const functionTag = "NeuroLink.executeToolInternal";
1096
- // First check custom tools
1097
- if (this.customTools.has(toolName)) {
1098
- const tool = this.customTools.get(toolName);
1099
- // Validate parameters if schema is available
1100
- if (tool.parameters) {
1101
- try {
1102
- tool.parameters.parse(params);
1103
- }
1104
- catch (validationError) {
1105
- throw ErrorFactory.invalidParameters(toolName, validationError, params);
1106
- }
1107
- }
1108
- const context = {
1109
- sessionId: `direct-execution-${Date.now()}`,
1110
- logger,
1111
- };
1112
- try {
1113
- const result = await tool.execute(params, context);
1114
- return result;
1115
- }
1116
- catch (error) {
1117
- throw ErrorFactory.toolExecutionFailed(toolName, error instanceof Error ? error : new Error(String(error)));
1118
- }
1119
- }
1120
- // Then check in-memory servers
1121
- for (const [serverId, serverConfig] of this.inMemoryServers.entries()) {
1122
- const server = serverConfig.server;
1123
- if (server && server.tools) {
1124
- const tool = server.tools instanceof Map
1125
- ? server.tools.get(toolName)
1126
- : server.tools[toolName];
1127
- if (tool && typeof tool.execute === "function") {
1128
- try {
1129
- const result = await tool.execute(params);
1130
- // Handle MCP-style results
1131
- if (result && typeof result === "object" && "success" in result) {
1132
- if (result.success) {
1133
- return result.data;
1134
- }
1135
- else {
1136
- throw ErrorFactory.toolExecutionFailed(toolName, new Error(result.error || "Tool execution failed"), serverId);
1137
- }
1138
- }
1139
- return result;
1140
- }
1141
- catch (error) {
1142
- throw ErrorFactory.toolExecutionFailed(toolName, error instanceof Error ? error : new Error(String(error)), serverId);
1143
- }
1144
- }
1145
- }
1146
- }
1147
1156
  // Check external MCP servers
1148
1157
  const externalTools = this.externalServerManager.getAllTools();
1149
1158
  const externalTool = externalTools.find((tool) => tool.name === toolName);
@@ -1209,35 +1218,30 @@ export class NeuroLink {
1209
1218
  serverId: tool.serverId === "direct" ? "neurolink-direct" : tool.serverId, // Update serverId for test compatibility
1210
1219
  }));
1211
1220
  // 2. Get custom tools from this NeuroLink instance
1212
- const customTools = Array.from(this.customTools.entries()).map(([name, tool]) => ({
1213
- name,
1214
- toolName: name, // Add toolName property for compatibility with tests
1221
+ const customTools = toolRegistry
1222
+ .getToolsByCategory(detectCategory({ isCustomTool: true }))
1223
+ .map((tool) => ({
1224
+ name: tool.name,
1225
+ toolName: tool.name, // Add toolName property for compatibility with tests
1215
1226
  description: tool.description || "Custom tool",
1216
- serverId: `custom-tool-${name}`, // Match the serverId pattern used in registerTool
1217
- category: "user-defined",
1218
- inputSchema: {},
1227
+ serverId: tool.serverId || `custom-tool-${tool.name}`,
1228
+ category: detectCategory({
1229
+ isCustomTool: true,
1230
+ serverId: tool.serverId,
1231
+ }),
1232
+ inputSchema: tool.inputSchema || {},
1219
1233
  }));
1220
1234
  // 3. Get tools from in-memory MCP servers
1221
- const inMemoryTools = [];
1222
- for (const [serverId, serverConfig] of this.inMemoryServers.entries()) {
1223
- const server = serverConfig.server;
1224
- if (server && server.tools) {
1225
- const tools = server.tools instanceof Map
1226
- ? Object.fromEntries(server.tools)
1227
- : server.tools;
1228
- for (const [toolName, toolDef] of Object.entries(tools)) {
1229
- const toolRecord = toolDef;
1230
- inMemoryTools.push({
1231
- name: toolName,
1232
- toolName, // Add toolName property for compatibility with tests
1233
- description: toolRecord.description || "In-memory MCP tool",
1234
- serverId,
1235
- category: serverConfig.category || "mcp-server",
1236
- inputSchema: {},
1237
- });
1238
- }
1239
- }
1240
- }
1235
+ const inMemoryTools = toolRegistry
1236
+ .getToolsByCategory("in-memory")
1237
+ .map((tool) => ({
1238
+ name: tool.name,
1239
+ toolName: tool.name, // Add toolName property for compatibility with tests
1240
+ description: tool.description || "In-memory MCP tool",
1241
+ serverId: tool.serverId || "unknown",
1242
+ category: tool.category || "in-memory",
1243
+ inputSchema: {},
1244
+ }));
1241
1245
  // 4. Get external MCP tools
1242
1246
  const externalMCPTools = this.externalServerManager
1243
1247
  .getAllTools()
@@ -1246,7 +1250,13 @@ export class NeuroLink {
1246
1250
  toolName: tool.name,
1247
1251
  description: tool.description,
1248
1252
  serverId: tool.serverId,
1249
- category: tool.metadata?.category || "external-mcp",
1253
+ category: detectCategory({
1254
+ existingCategory: typeof tool.metadata?.category === "string"
1255
+ ? tool.metadata.category
1256
+ : undefined,
1257
+ isExternal: true,
1258
+ serverId: tool.serverId,
1259
+ }),
1250
1260
  inputSchema: tool.inputSchema || {},
1251
1261
  isAvailable: tool.isAvailable,
1252
1262
  stats: tool.stats,
@@ -1492,41 +1502,36 @@ export class NeuroLink {
1492
1502
  */
1493
1503
  async getMCPStatus() {
1494
1504
  try {
1505
+ // Initialize MCP if not already initialized (loads external servers from config)
1506
+ await this.initializeMCP();
1495
1507
  // Get built-in tools
1496
1508
  const allTools = await toolRegistry.listTools();
1497
1509
  // Get external MCP server statistics
1498
1510
  const externalStats = this.externalServerManager.getStatistics();
1499
- const externalServers = this.listExternalMCPServers();
1511
+ // DIRECT RETURNS - ZERO conversion
1512
+ const externalMCPServers = this.externalServerManager.listServers();
1513
+ const inMemoryServerInfos = this.getInMemoryServerInfos();
1514
+ const builtInServerInfos = toolRegistry.getBuiltInServerInfos();
1515
+ const autoDiscoveredServerInfos = this.getAutoDiscoveredServerInfos();
1500
1516
  // Calculate totals
1501
- const totalServers = 1 + externalStats.totalServers + this.inMemoryServers.size; // toolRegistry + external + in-memory
1502
- const availableServers = 1 + externalStats.connectedServers; // toolRegistry always available + connected external
1503
- const totalTools = allTools.length + externalStats.totalTools + this.customTools.size;
1504
- // Convert external servers to MCPServerInfo format
1505
- const externalMCPServers = externalServers.map((server) => ({
1506
- id: server.serverId,
1507
- name: typeof server.config.metadata?.title === "string"
1508
- ? server.config.metadata.title
1509
- : server.serverId,
1510
- source: `external-${server.config.transport}`,
1511
- status: server.status,
1512
- hasServer: server.isHealthy,
1513
- metadata: {
1514
- transport: server.config.transport,
1515
- command: server.config.command,
1516
- toolCount: server.toolCount,
1517
- uptime: server.uptime,
1518
- },
1519
- }));
1517
+ const totalServers = externalMCPServers.length +
1518
+ inMemoryServerInfos.length +
1519
+ builtInServerInfos.length +
1520
+ autoDiscoveredServerInfos.length;
1521
+ const availableServers = externalStats.connectedServers +
1522
+ inMemoryServerInfos.length +
1523
+ builtInServerInfos.length; // in-memory and built-in always available
1524
+ const totalTools = allTools.length + externalStats.totalTools;
1520
1525
  return {
1521
1526
  mcpInitialized: this.mcpInitialized,
1522
1527
  totalServers,
1523
1528
  availableServers,
1524
- autoDiscoveredCount: 0, // No auto-discovery for external servers
1529
+ autoDiscoveredCount: autoDiscoveredServerInfos.length,
1525
1530
  totalTools,
1526
- autoDiscoveredServers: [],
1527
- customToolsCount: this.customTools.size,
1528
- inMemoryServersCount: this.inMemoryServers.size,
1529
- externalMCPServersCount: externalStats.totalServers,
1531
+ autoDiscoveredServers: autoDiscoveredServerInfos,
1532
+ customToolsCount: toolRegistry.getToolsByCategory(detectCategory({ isCustomTool: true })).length,
1533
+ inMemoryServersCount: inMemoryServerInfos.length,
1534
+ externalMCPServersCount: externalMCPServers.length,
1530
1535
  externalMCPConnectedCount: externalStats.connectedServers,
1531
1536
  externalMCPFailedCount: externalStats.failedServers,
1532
1537
  externalMCPServers,
@@ -1540,8 +1545,8 @@ export class NeuroLink {
1540
1545
  autoDiscoveredCount: 0,
1541
1546
  totalTools: 0,
1542
1547
  autoDiscoveredServers: [],
1543
- customToolsCount: this.customTools.size,
1544
- inMemoryServersCount: this.inMemoryServers.size,
1548
+ customToolsCount: toolRegistry.getToolsByCategory(detectCategory({ isCustomTool: true })).length,
1549
+ inMemoryServersCount: 0,
1545
1550
  externalMCPServersCount: 0,
1546
1551
  externalMCPConnectedCount: 0,
1547
1552
  externalMCPFailedCount: 0,
@@ -1555,54 +1560,13 @@ export class NeuroLink {
1555
1560
  * @returns Promise resolving to array of MCP server information
1556
1561
  */
1557
1562
  async listMCPServers() {
1558
- const servers = [];
1559
- // Add built-in toolRegistry as a server
1560
- servers.push({
1561
- id: "neurolink-direct",
1562
- name: "NeuroLink Built-in Tools",
1563
- source: "built-in",
1564
- status: "connected",
1565
- hasServer: true,
1566
- metadata: {
1567
- type: "direct-tools",
1568
- description: "Built-in NeuroLink tools (getCurrentTime, readFile, etc.)",
1569
- },
1570
- });
1571
- // Add in-memory servers
1572
- for (const [serverId, serverConfig] of this.inMemoryServers.entries()) {
1573
- servers.push({
1574
- id: serverId,
1575
- name: serverConfig.server.title || serverId,
1576
- source: "in-memory",
1577
- status: "connected",
1578
- hasServer: true,
1579
- metadata: {
1580
- category: serverConfig.category,
1581
- provider: serverConfig.metadata?.provider,
1582
- version: serverConfig.metadata?.version,
1583
- },
1584
- });
1585
- }
1586
- // Add external MCP servers
1587
- const externalServers = this.listExternalMCPServers();
1588
- for (const server of externalServers) {
1589
- servers.push({
1590
- id: server.serverId,
1591
- name: typeof server.config.metadata?.title === "string"
1592
- ? server.config.metadata.title
1593
- : server.serverId,
1594
- source: `external-${server.config.transport}`,
1595
- status: server.status,
1596
- hasServer: server.isHealthy,
1597
- metadata: {
1598
- transport: server.config.transport,
1599
- command: server.config.command,
1600
- toolCount: server.toolCount,
1601
- uptime: server.uptime,
1602
- },
1603
- });
1604
- }
1605
- return servers;
1563
+ // DIRECT RETURNS - ZERO conversion logic
1564
+ return [
1565
+ ...this.externalServerManager.listServers(), // Direct return
1566
+ ...this.getInMemoryServerInfos(), // Direct return
1567
+ ...toolRegistry.getBuiltInServerInfos(), // Direct return
1568
+ ...this.getAutoDiscoveredServerInfos(), // Direct return
1569
+ ];
1606
1570
  }
1607
1571
  /**
1608
1572
  * Test connectivity to a specific MCP server
@@ -1617,9 +1581,10 @@ export class NeuroLink {
1617
1581
  return tools.length > 0;
1618
1582
  }
1619
1583
  // Test in-memory servers
1620
- if (this.inMemoryServers.has(serverId)) {
1621
- const serverConfig = this.inMemoryServers.get(serverId);
1622
- return !!(serverConfig.server && serverConfig.server.tools);
1584
+ const inMemoryServers = this.getInMemoryServers();
1585
+ if (inMemoryServers.has(serverId)) {
1586
+ const serverInfo = inMemoryServers.get(serverId);
1587
+ return !!(serverInfo.tools && serverInfo.tools.length > 0);
1623
1588
  }
1624
1589
  // Test external MCP servers
1625
1590
  const externalServer = this.externalServerManager.getServer(serverId);
@@ -1785,14 +1750,12 @@ export class NeuroLink {
1785
1750
  * Get comprehensive tool health report
1786
1751
  * @returns Detailed health report for all tools
1787
1752
  */
1788
- getToolHealthReport() {
1753
+ async getToolHealthReport() {
1789
1754
  const tools = {};
1790
1755
  let healthyCount = 0;
1791
- // Get all tool names from all sources
1792
- const allToolNames = new Set([
1793
- ...this.customTools.keys(),
1794
- ...Array.from(this.inMemoryServers.values()).flatMap((server) => server.server?.tools ? Object.keys(server.server.tools) : []),
1795
- ]);
1756
+ // Get all tool names from toolRegistry
1757
+ const allTools = await toolRegistry.listTools();
1758
+ const allToolNames = new Set(allTools.map((tool) => tool.name));
1796
1759
  for (const toolName of allToolNames) {
1797
1760
  const metrics = this.toolExecutionMetrics.get(toolName);
1798
1761
  const circuitBreaker = this.toolCircuitBreakers.get(toolName);
@@ -1950,16 +1913,16 @@ export class NeuroLink {
1950
1913
  */
1951
1914
  listExternalMCPServers() {
1952
1915
  const serverStatuses = this.externalServerManager.getServerStatuses();
1953
- const allServers = this.externalServerManager.getAllServers();
1916
+ const allServers = this.externalServerManager.listServers();
1954
1917
  return serverStatuses.map((health) => {
1955
- const server = allServers.get(health.serverId);
1918
+ const server = allServers.find((s) => s.id === health.serverId);
1956
1919
  return {
1957
1920
  serverId: health.serverId,
1958
1921
  status: health.status,
1959
1922
  toolCount: health.toolCount,
1960
1923
  uptime: health.performance.uptime,
1961
1924
  isHealthy: health.isHealthy,
1962
- config: server?.config || {},
1925
+ config: server || {},
1963
1926
  };
1964
1927
  });
1965
1928
  }
@@ -90,6 +90,12 @@ export declare class GoogleVertexProvider extends BaseProvider {
90
90
  * @returns The current tool execution context
91
91
  */
92
92
  getToolContext(): Record<string, unknown>;
93
+ /**
94
+ * Set the tool executor function for custom tool execution
95
+ * This method is called by BaseProvider.setupToolExecutor()
96
+ * @param executor Function to execute tools by name
97
+ */
98
+ setToolExecutor(executor: (toolName: string, params: unknown) => Promise<unknown>): void;
93
99
  /**
94
100
  * Clear all static caches - useful for testing and memory cleanup
95
101
  * Public method to allow external cache management
@@ -504,6 +504,17 @@ export class GoogleVertexProvider extends BaseProvider {
504
504
  getToolContext() {
505
505
  return { ...this.toolContext };
506
506
  }
507
+ /**
508
+ * Set the tool executor function for custom tool execution
509
+ * This method is called by BaseProvider.setupToolExecutor()
510
+ * @param executor Function to execute tools by name
511
+ */
512
+ setToolExecutor(executor) {
513
+ this.toolExecutor = executor;
514
+ logger.debug("GoogleVertexProvider.setToolExecutor: Tool executor set", {
515
+ hasExecutor: typeof executor === "function",
516
+ });
517
+ }
507
518
  /**
508
519
  * Clear all static caches - useful for testing and memory cleanup
509
520
  * Public method to allow external cache management
@@ -87,7 +87,7 @@ export class HuggingFaceProvider extends BaseProvider {
87
87
  "openchat",
88
88
  "wizardcoder",
89
89
  ];
90
- // Check if current model matches any tool-capable model patterns
90
+ // Check if current model matches tool-capable model patterns
91
91
  const isToolCapable = toolCapableModels.some((capableModel) => modelName.includes(capableModel));
92
92
  if (isToolCapable) {
93
93
  logger.debug("HuggingFace tool calling enabled", {
@@ -21,11 +21,11 @@ const getDefaultMistralModel = () => {
21
21
  export class MistralProvider extends BaseProvider {
22
22
  model;
23
23
  constructor(modelName, sdk) {
24
- // Type guard for NeuroLinkSDK parameter validation
25
- const validatedSdk = sdk && typeof sdk === "object" && "getInMemoryServers" in sdk
24
+ // Type guard for NeuroLink parameter validation
25
+ const validatedNeurolink = sdk && typeof sdk === "object" && "getInMemoryServers" in sdk
26
26
  ? sdk
27
27
  : undefined;
28
- super(modelName, "mistral", validatedSdk);
28
+ super(modelName, "mistral", validatedNeurolink);
29
29
  // Initialize Mistral model with API key validation
30
30
  const apiKey = getMistralApiKey();
31
31
  const mistral = createMistral({
@@ -270,7 +270,7 @@ export class OllamaProvider extends BaseProvider {
270
270
  // Get tool-capable models from configuration
271
271
  const ollamaConfig = modelConfig.getProviderConfig("ollama");
272
272
  const toolCapableModels = ollamaConfig?.modelBehavior?.toolCapableModels || [];
273
- // Check if current model matches any tool-capable model patterns
273
+ // Check if current model matches tool-capable model patterns
274
274
  const isToolCapable = toolCapableModels.some((capableModel) => modelName.includes(capableModel));
275
275
  if (isToolCapable) {
276
276
  logger.debug("Ollama tool calling enabled", {