@juspay/neurolink 1.10.0 → 1.11.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 (144) hide show
  1. package/CHANGELOG.md +43 -33
  2. package/README.md +16 -0
  3. package/dist/agent/direct-tools.d.ts +9 -9
  4. package/dist/cli/commands/agent-generate.d.ts +1 -2
  5. package/dist/cli/commands/agent-generate.js +5 -8
  6. package/dist/cli/commands/config.d.ts +2 -2
  7. package/dist/cli/commands/config.js +1 -1
  8. package/dist/cli/commands/mcp.js +91 -100
  9. package/dist/cli/commands/ollama.d.ts +2 -7
  10. package/dist/cli/commands/ollama.js +5 -8
  11. package/dist/cli/index.js +185 -276
  12. package/dist/core/factory.js +9 -10
  13. package/dist/index.d.ts +23 -0
  14. package/dist/index.js +35 -0
  15. package/dist/lib/agent/direct-tools.d.ts +9 -9
  16. package/dist/lib/core/factory.js +9 -10
  17. package/dist/lib/index.d.ts +23 -0
  18. package/dist/lib/index.js +35 -0
  19. package/dist/lib/mcp/adapters/plugin-bridge.d.ts +39 -0
  20. package/dist/lib/mcp/adapters/plugin-bridge.js +82 -0
  21. package/dist/lib/mcp/auto-discovery.d.ts +38 -96
  22. package/dist/lib/mcp/auto-discovery.js +100 -744
  23. package/dist/lib/mcp/client.js +4 -4
  24. package/dist/lib/mcp/context-manager.js +72 -1
  25. package/dist/lib/mcp/contracts/mcp-contract.d.ts +162 -0
  26. package/dist/lib/mcp/contracts/mcp-contract.js +58 -0
  27. package/dist/lib/mcp/core/plugin-manager.d.ts +45 -0
  28. package/dist/lib/mcp/core/plugin-manager.js +110 -0
  29. package/dist/lib/mcp/demo/plugin-demo.d.ts +20 -0
  30. package/dist/lib/mcp/demo/plugin-demo.js +116 -0
  31. package/dist/lib/mcp/ecosystem.d.ts +75 -0
  32. package/dist/lib/mcp/ecosystem.js +161 -0
  33. package/dist/lib/mcp/external-client.d.ts +88 -0
  34. package/dist/lib/mcp/external-client.js +323 -0
  35. package/dist/lib/mcp/external-manager.d.ts +112 -0
  36. package/dist/lib/mcp/external-manager.js +302 -0
  37. package/dist/lib/mcp/factory.d.ts +4 -4
  38. package/dist/lib/mcp/function-calling.js +59 -34
  39. package/dist/lib/mcp/index.d.ts +39 -184
  40. package/dist/lib/mcp/index.js +72 -150
  41. package/dist/lib/mcp/initialize.js +5 -5
  42. package/dist/lib/mcp/logging.d.ts +27 -60
  43. package/dist/lib/mcp/logging.js +77 -165
  44. package/dist/lib/mcp/neurolink-mcp-client.js +31 -3
  45. package/dist/lib/mcp/orchestrator.d.ts +1 -1
  46. package/dist/lib/mcp/orchestrator.js +13 -12
  47. package/dist/lib/mcp/plugin-manager.d.ts +98 -0
  48. package/dist/lib/mcp/plugin-manager.js +294 -0
  49. package/dist/lib/mcp/plugins/core/filesystem-mcp.d.ts +35 -0
  50. package/dist/lib/mcp/plugins/core/filesystem-mcp.js +139 -0
  51. package/dist/lib/mcp/plugins/filesystem-mcp.d.ts +36 -0
  52. package/dist/lib/mcp/plugins/filesystem-mcp.js +54 -0
  53. package/dist/lib/mcp/registry.d.ts +27 -176
  54. package/dist/lib/mcp/registry.js +31 -372
  55. package/dist/lib/mcp/security-manager.d.ts +85 -0
  56. package/dist/lib/mcp/security-manager.js +344 -0
  57. package/dist/lib/mcp/servers/ai-providers/ai-workflow-tools.d.ts +2 -2
  58. package/dist/lib/mcp/tool-integration.d.ts +4 -14
  59. package/dist/lib/mcp/tool-integration.js +43 -21
  60. package/dist/lib/mcp/tool-registry.d.ts +66 -0
  61. package/dist/lib/mcp/tool-registry.js +160 -0
  62. package/dist/lib/mcp/unified-mcp.d.ts +123 -0
  63. package/dist/lib/mcp/unified-mcp.js +246 -0
  64. package/dist/lib/mcp/unified-registry.d.ts +42 -229
  65. package/dist/lib/mcp/unified-registry.js +96 -1346
  66. package/dist/lib/neurolink.d.ts +3 -4
  67. package/dist/lib/neurolink.js +17 -18
  68. package/dist/lib/providers/agent-enhanced-provider.js +2 -2
  69. package/dist/lib/providers/amazonBedrock.js +2 -2
  70. package/dist/lib/providers/anthropic.js +3 -3
  71. package/dist/lib/providers/azureOpenAI.js +3 -3
  72. package/dist/lib/providers/function-calling-provider.js +34 -25
  73. package/dist/lib/providers/googleAIStudio.js +9 -3
  74. package/dist/lib/providers/googleVertexAI.js +2 -2
  75. package/dist/lib/providers/huggingFace.js +2 -2
  76. package/dist/lib/providers/mcp-provider.js +33 -5
  77. package/dist/lib/providers/mistralAI.js +2 -2
  78. package/dist/lib/providers/ollama.js +2 -2
  79. package/dist/lib/providers/openAI.js +2 -2
  80. package/dist/lib/utils/providerUtils-fixed.js +9 -9
  81. package/dist/mcp/adapters/plugin-bridge.d.ts +39 -0
  82. package/dist/mcp/adapters/plugin-bridge.js +82 -0
  83. package/dist/mcp/auto-discovery.d.ts +38 -96
  84. package/dist/mcp/auto-discovery.js +100 -745
  85. package/dist/mcp/client.js +4 -4
  86. package/dist/mcp/context-manager.js +72 -1
  87. package/dist/mcp/contracts/mcp-contract.d.ts +162 -0
  88. package/dist/mcp/contracts/mcp-contract.js +58 -0
  89. package/dist/mcp/core/plugin-manager.d.ts +45 -0
  90. package/dist/mcp/core/plugin-manager.js +110 -0
  91. package/dist/mcp/demo/plugin-demo.d.ts +20 -0
  92. package/dist/mcp/demo/plugin-demo.js +116 -0
  93. package/dist/mcp/ecosystem.d.ts +75 -0
  94. package/dist/mcp/ecosystem.js +162 -0
  95. package/dist/mcp/external-client.d.ts +88 -0
  96. package/dist/mcp/external-client.js +323 -0
  97. package/dist/mcp/external-manager.d.ts +112 -0
  98. package/dist/mcp/external-manager.js +302 -0
  99. package/dist/mcp/factory.d.ts +4 -4
  100. package/dist/mcp/function-calling.js +59 -34
  101. package/dist/mcp/index.d.ts +39 -184
  102. package/dist/mcp/index.js +72 -150
  103. package/dist/mcp/initialize.js +5 -5
  104. package/dist/mcp/logging.d.ts +27 -60
  105. package/dist/mcp/logging.js +77 -165
  106. package/dist/mcp/neurolink-mcp-client.js +31 -3
  107. package/dist/mcp/orchestrator.d.ts +1 -1
  108. package/dist/mcp/orchestrator.js +13 -12
  109. package/dist/mcp/plugin-manager.d.ts +98 -0
  110. package/dist/mcp/plugin-manager.js +295 -0
  111. package/dist/mcp/plugins/core/filesystem-mcp.d.ts +35 -0
  112. package/dist/mcp/plugins/core/filesystem-mcp.js +139 -0
  113. package/dist/mcp/plugins/core/neurolink-mcp.json +17 -0
  114. package/dist/mcp/plugins/filesystem-mcp.d.ts +36 -0
  115. package/dist/mcp/plugins/filesystem-mcp.js +54 -0
  116. package/dist/mcp/registry.d.ts +27 -176
  117. package/dist/mcp/registry.js +31 -372
  118. package/dist/mcp/security-manager.d.ts +85 -0
  119. package/dist/mcp/security-manager.js +344 -0
  120. package/dist/mcp/servers/ai-providers/ai-workflow-tools.d.ts +2 -2
  121. package/dist/mcp/tool-integration.d.ts +4 -14
  122. package/dist/mcp/tool-integration.js +43 -21
  123. package/dist/mcp/tool-registry.d.ts +66 -0
  124. package/dist/mcp/tool-registry.js +160 -0
  125. package/dist/mcp/unified-mcp.d.ts +123 -0
  126. package/dist/mcp/unified-mcp.js +246 -0
  127. package/dist/mcp/unified-registry.d.ts +42 -229
  128. package/dist/mcp/unified-registry.js +96 -1345
  129. package/dist/neurolink.d.ts +3 -4
  130. package/dist/neurolink.js +17 -18
  131. package/dist/providers/agent-enhanced-provider.js +2 -2
  132. package/dist/providers/amazonBedrock.js +2 -2
  133. package/dist/providers/anthropic.js +3 -3
  134. package/dist/providers/azureOpenAI.js +3 -3
  135. package/dist/providers/function-calling-provider.js +34 -25
  136. package/dist/providers/googleAIStudio.js +9 -3
  137. package/dist/providers/googleVertexAI.js +2 -2
  138. package/dist/providers/huggingFace.js +2 -2
  139. package/dist/providers/mcp-provider.js +33 -5
  140. package/dist/providers/mistralAI.js +2 -2
  141. package/dist/providers/ollama.js +2 -2
  142. package/dist/providers/openAI.js +2 -2
  143. package/dist/utils/providerUtils-fixed.js +9 -9
  144. package/package.json +1 -1
@@ -0,0 +1,161 @@
1
+ /**
2
+ * MCP Ecosystem Integration - Bridge Between Research Blueprint and NeuroLink
3
+ * Provides unified interface for plugin management and execution
4
+ */
5
+ import { pluginManager } from "./plugin-manager.js";
6
+ import { SecurityManager } from "./security-manager.js";
7
+ import { mcpLogger } from "./logging.js";
8
+ import { tool } from "ai";
9
+ import { z } from "zod";
10
+ /**
11
+ * MCP Ecosystem - Main Interface for Plugin Operations
12
+ */
13
+ export class MCPEcosystem {
14
+ static instance;
15
+ securityManager;
16
+ initialized = false;
17
+ constructor() {
18
+ this.securityManager = new SecurityManager("moderate");
19
+ }
20
+ static getInstance() {
21
+ if (!MCPEcosystem.instance) {
22
+ MCPEcosystem.instance = new MCPEcosystem();
23
+ }
24
+ return MCPEcosystem.instance;
25
+ }
26
+ /**
27
+ * Initialize the MCP ecosystem
28
+ */
29
+ async initialize() {
30
+ if (this.initialized) {
31
+ return;
32
+ }
33
+ mcpLogger.info("[MCPEcosystem] Initializing MCP ecosystem...");
34
+ await pluginManager.initialize();
35
+ this.initialized = true;
36
+ const stats = pluginManager.getDiscoveryStats();
37
+ mcpLogger.info("[MCPEcosystem] MCP ecosystem initialized", stats);
38
+ }
39
+ /**
40
+ * List all available MCPs
41
+ */
42
+ async list() {
43
+ await this.ensureInitialized();
44
+ return pluginManager.listDiscovered();
45
+ }
46
+ /**
47
+ * Get metadata for a specific MCP
48
+ */
49
+ async getMetadata(name) {
50
+ await this.ensureInitialized();
51
+ return pluginManager.getMetadata(name);
52
+ }
53
+ /**
54
+ * Create and execute an MCP instance
55
+ */
56
+ async execute(name, config, args, context) {
57
+ await this.ensureInitialized();
58
+ const functionTag = "MCPEcosystem.execute";
59
+ try {
60
+ // Get MCP metadata for permissions
61
+ const metadata = await this.getMetadata(name);
62
+ if (!metadata) {
63
+ throw new Error(`MCP ${name} not found`);
64
+ }
65
+ // Create execution context
66
+ const executionContext = this.securityManager.createExecutionContext(context?.sessionId || `mcp-${Date.now()}`, context?.userId || "mcp-user", metadata.permissions, config?.basePath);
67
+ // Create MCP instance
68
+ const mcpInstance = await pluginManager.createInstance(name, config);
69
+ // Execute the MCP
70
+ mcpLogger.debug(`[${functionTag}] Executing ${name}`, { args });
71
+ const result = await mcpInstance.execute(executionContext, args);
72
+ mcpLogger.debug(`[${functionTag}] ${name} execution completed`, {
73
+ success: true,
74
+ resultType: typeof result,
75
+ });
76
+ return result;
77
+ }
78
+ catch (error) {
79
+ mcpLogger.error(`[${functionTag}] ${name} execution failed:`, error);
80
+ throw error;
81
+ }
82
+ }
83
+ /**
84
+ * Execute filesystem operations using FileSystemMCP
85
+ */
86
+ async filesystem(operation) {
87
+ return this.execute("@neurolink-mcp/filesystem", { basePath: operation.basePath || process.cwd() }, {
88
+ operation: operation.action,
89
+ path: operation.path,
90
+ content: operation.content,
91
+ });
92
+ }
93
+ /**
94
+ * Get ecosystem statistics
95
+ */
96
+ async getStats() {
97
+ const available = await this.list();
98
+ return {
99
+ initialized: this.initialized,
100
+ pluginsDiscovered: available.length,
101
+ pluginsBySource: pluginManager.getDiscoveryStats(),
102
+ availablePlugins: available.map((p) => p.name),
103
+ };
104
+ }
105
+ /**
106
+ * Create an MCP instance for direct use
107
+ */
108
+ async createInstance(name, config) {
109
+ await this.ensureInitialized();
110
+ const metadata = await this.getMetadata(name);
111
+ if (!metadata) {
112
+ throw new Error(`MCP ${name} not found`);
113
+ }
114
+ return pluginManager.createInstance(name, config);
115
+ }
116
+ /**
117
+ * Create execution context for manual MCP usage
118
+ */
119
+ createExecutionContext(sessionId, userId, permissions, basePath) {
120
+ return this.securityManager.createExecutionContext(sessionId, userId, permissions, basePath);
121
+ }
122
+ /**
123
+ * Ensure ecosystem is initialized
124
+ */
125
+ async ensureInitialized() {
126
+ if (!this.initialized) {
127
+ await this.initialize();
128
+ }
129
+ }
130
+ /**
131
+ * Get all tools formatted for AI providers
132
+ */
133
+ async getToolsForAI() {
134
+ await this.ensureInitialized();
135
+ const plugins = await this.list();
136
+ const tools = {};
137
+ for (const plugin of plugins) {
138
+ // This is a simplified representation. A real implementation
139
+ // would parse the plugin's metadata to get tool definitions.
140
+ if (plugin.name.includes("filesystem")) {
141
+ tools["filesystem_list"] = tool({
142
+ description: "List files in a directory",
143
+ parameters: z.object({
144
+ path: z.string().describe("The path to list files from"),
145
+ }),
146
+ execute: async ({ path }) => this.filesystem({ action: "listFiles", path }),
147
+ });
148
+ }
149
+ }
150
+ return tools;
151
+ }
152
+ /**
153
+ * Dispose of all resources
154
+ */
155
+ async dispose() {
156
+ await pluginManager.dispose();
157
+ this.initialized = false;
158
+ }
159
+ }
160
+ // Export singleton instance
161
+ export const mcpEcosystem = MCPEcosystem.getInstance();
@@ -0,0 +1,88 @@
1
+ /**
2
+ * NeuroLink External MCP Client
3
+ * Connects to external MCP servers via stdio transport following MCP specification
4
+ * Bridges external tools into NeuroLink's factory pattern ecosystem
5
+ */
6
+ import { EventEmitter } from "events";
7
+ import type { NeuroLinkMCPTool, NeuroLinkExecutionContext, ToolResult } from "./factory.js";
8
+ /**
9
+ * External MCP Server Configuration
10
+ */
11
+ export interface ExternalMCPServerConfig {
12
+ name: string;
13
+ command: string;
14
+ args: string[];
15
+ transport: "stdio";
16
+ env?: Record<string, string>;
17
+ timeout?: number;
18
+ retryAttempts?: number;
19
+ }
20
+ /**
21
+ * External MCP Client for stdio transport
22
+ */
23
+ export declare class ExternalMCPClient extends EventEmitter {
24
+ private config;
25
+ private process;
26
+ private isConnected;
27
+ private messageId;
28
+ private pendingRequests;
29
+ private tools;
30
+ private buffer;
31
+ constructor(config: ExternalMCPServerConfig);
32
+ /**
33
+ * Connect to the external MCP server
34
+ */
35
+ connect(): Promise<void>;
36
+ /**
37
+ * Initialize MCP session
38
+ */
39
+ private initialize;
40
+ /**
41
+ * Discover available tools from the server
42
+ */
43
+ private discoverTools;
44
+ /**
45
+ * Execute a tool on the external server
46
+ */
47
+ executeTool(toolName: string, params: any, context: NeuroLinkExecutionContext): Promise<ToolResult>;
48
+ /**
49
+ * Get available tools as NeuroLink MCP tools
50
+ */
51
+ getNeuroLinkTools(): Record<string, NeuroLinkMCPTool>;
52
+ /**
53
+ * Send a request to the MCP server
54
+ */
55
+ private sendRequest;
56
+ /**
57
+ * Handle incoming messages from the server
58
+ */
59
+ private handleMessage;
60
+ /**
61
+ * Process a parsed MCP message
62
+ */
63
+ private processMessage;
64
+ /**
65
+ * Disconnect from the server
66
+ */
67
+ disconnect(): Promise<void>;
68
+ /**
69
+ * Check if connected
70
+ */
71
+ isConnectedToServer(): boolean;
72
+ /**
73
+ * Get server information
74
+ */
75
+ getServerInfo(): {
76
+ name: string;
77
+ command: string;
78
+ args: string[];
79
+ transport: "stdio";
80
+ isConnected: boolean;
81
+ toolCount: number;
82
+ tools: string[];
83
+ };
84
+ }
85
+ /**
86
+ * Create an external MCP client
87
+ */
88
+ export declare function createExternalMCPClient(config: ExternalMCPServerConfig): ExternalMCPClient;
@@ -0,0 +1,323 @@
1
+ /**
2
+ * NeuroLink External MCP Client
3
+ * Connects to external MCP servers via stdio transport following MCP specification
4
+ * Bridges external tools into NeuroLink's factory pattern ecosystem
5
+ */
6
+ import { spawn } from "child_process";
7
+ import { EventEmitter } from "events";
8
+ import { mcpLogger as logger } from "./logging.js";
9
+ /**
10
+ * External MCP Client for stdio transport
11
+ */
12
+ export class ExternalMCPClient extends EventEmitter {
13
+ config;
14
+ process = null;
15
+ isConnected = false;
16
+ messageId = 0;
17
+ pendingRequests = new Map();
18
+ tools = new Map();
19
+ buffer = "";
20
+ constructor(config) {
21
+ super();
22
+ this.config = {
23
+ timeout: 30000,
24
+ retryAttempts: 3,
25
+ ...config,
26
+ };
27
+ }
28
+ /**
29
+ * Connect to the external MCP server
30
+ */
31
+ async connect() {
32
+ if (this.isConnected) {
33
+ logger.debug(`[External MCP] Already connected to ${this.config.name}`);
34
+ return;
35
+ }
36
+ try {
37
+ logger.info(`[External MCP] Connecting to ${this.config.name}...`);
38
+ // Spawn the MCP server process
39
+ this.process = spawn(this.config.command, this.config.args, {
40
+ stdio: ["pipe", "pipe", "pipe"],
41
+ env: { ...process.env, ...this.config.env },
42
+ });
43
+ if (!this.process.stdout || !this.process.stdin || !this.process.stderr) {
44
+ throw new Error("Failed to create stdio pipes");
45
+ }
46
+ // Setup stdout handler for receiving messages
47
+ this.process.stdout.on("data", (data) => {
48
+ this.handleMessage(data.toString());
49
+ });
50
+ // Setup stderr handler for debugging
51
+ this.process.stderr.on("data", (data) => {
52
+ logger.debug(`[External MCP] ${this.config.name} stderr:`, data.toString().trim());
53
+ });
54
+ // Handle process exit
55
+ this.process.on("exit", (code, signal) => {
56
+ logger.warn(`[External MCP] ${this.config.name} process exited`, {
57
+ code,
58
+ signal,
59
+ });
60
+ this.isConnected = false;
61
+ this.emit("disconnected", { code, signal });
62
+ });
63
+ // Handle process errors
64
+ this.process.on("error", (error) => {
65
+ logger.error(`[External MCP] ${this.config.name} process error:`, error);
66
+ this.emit("error", error);
67
+ });
68
+ // Initialize MCP session
69
+ await this.initialize();
70
+ // Discover available tools
71
+ await this.discoverTools();
72
+ this.isConnected = true;
73
+ logger.info(`[External MCP] Connected to ${this.config.name} with ${this.tools.size} tools`);
74
+ this.emit("connected");
75
+ }
76
+ catch (error) {
77
+ logger.error(`[External MCP] Failed to connect to ${this.config.name}:`, error);
78
+ await this.disconnect();
79
+ throw error;
80
+ }
81
+ }
82
+ /**
83
+ * Initialize MCP session
84
+ */
85
+ async initialize() {
86
+ const initResponse = await this.sendRequest("initialize", {
87
+ protocolVersion: "2024-11-05",
88
+ capabilities: {
89
+ tools: {},
90
+ },
91
+ clientInfo: {
92
+ name: "neurolink-mcp-client",
93
+ version: "1.0.0",
94
+ },
95
+ });
96
+ logger.debug(`[External MCP] ${this.config.name} initialized:`, initResponse);
97
+ }
98
+ /**
99
+ * Discover available tools from the server
100
+ */
101
+ async discoverTools() {
102
+ try {
103
+ const response = await this.sendRequest("tools/list", {});
104
+ if (response.tools && Array.isArray(response.tools)) {
105
+ this.tools.clear();
106
+ for (const tool of response.tools) {
107
+ this.tools.set(tool.name, {
108
+ name: tool.name,
109
+ description: tool.description,
110
+ inputSchema: tool.inputSchema,
111
+ });
112
+ }
113
+ logger.debug(`[External MCP] Discovered ${this.tools.size} tools from ${this.config.name}`);
114
+ }
115
+ }
116
+ catch (error) {
117
+ logger.warn(`[External MCP] Failed to discover tools from ${this.config.name}:`, error);
118
+ }
119
+ }
120
+ /**
121
+ * Execute a tool on the external server
122
+ */
123
+ async executeTool(toolName, params, context) {
124
+ if (!this.isConnected) {
125
+ throw new Error(`Not connected to MCP server: ${this.config.name}`);
126
+ }
127
+ const startTime = Date.now();
128
+ try {
129
+ logger.debug(`[External MCP] Executing tool ${toolName} on ${this.config.name}`);
130
+ const response = await this.sendRequest("tools/call", {
131
+ name: toolName,
132
+ arguments: params,
133
+ });
134
+ const executionTime = Date.now() - startTime;
135
+ // Transform MCP response to NeuroLink format
136
+ const result = {
137
+ success: !response.isError,
138
+ data: response.content || response.result || response,
139
+ metadata: {
140
+ toolName,
141
+ serverId: this.config.name,
142
+ serverTitle: this.config.name,
143
+ sessionId: context.sessionId,
144
+ timestamp: Date.now(),
145
+ executionTime,
146
+ },
147
+ };
148
+ if (response.isError) {
149
+ result.error = response.content?.[0]?.text || "Tool execution failed";
150
+ }
151
+ logger.debug(`[External MCP] Tool ${toolName} executed in ${executionTime}ms`);
152
+ return result;
153
+ }
154
+ catch (error) {
155
+ const executionTime = Date.now() - startTime;
156
+ const errorMessage = error instanceof Error ? error.message : String(error);
157
+ logger.error(`[External MCP] Tool execution failed: ${toolName}`, error);
158
+ return {
159
+ success: false,
160
+ error: errorMessage,
161
+ metadata: {
162
+ toolName,
163
+ serverId: this.config.name,
164
+ serverTitle: this.config.name,
165
+ sessionId: context.sessionId,
166
+ timestamp: Date.now(),
167
+ executionTime,
168
+ },
169
+ };
170
+ }
171
+ }
172
+ /**
173
+ * Get available tools as NeuroLink MCP tools
174
+ */
175
+ getNeuroLinkTools() {
176
+ const neurolinkTools = {};
177
+ for (const [name, toolInfo] of this.tools) {
178
+ neurolinkTools[name] = {
179
+ name,
180
+ description: toolInfo.description || `External tool from ${this.config.name}`,
181
+ category: "external",
182
+ isImplemented: true,
183
+ execute: async (params, context) => {
184
+ return this.executeTool(name, params, context);
185
+ },
186
+ inputSchema: toolInfo.inputSchema,
187
+ metadata: {
188
+ serverId: this.config.name,
189
+ serverTitle: this.config.name,
190
+ external: true,
191
+ transport: "stdio",
192
+ },
193
+ };
194
+ }
195
+ return neurolinkTools;
196
+ }
197
+ /**
198
+ * Send a request to the MCP server
199
+ */
200
+ async sendRequest(method, params) {
201
+ return new Promise((resolve, reject) => {
202
+ if (!this.process?.stdin) {
203
+ reject(new Error("Process not available"));
204
+ return;
205
+ }
206
+ const id = ++this.messageId;
207
+ const message = {
208
+ jsonrpc: "2.0",
209
+ id,
210
+ method,
211
+ params,
212
+ };
213
+ // Setup timeout
214
+ const timeout = setTimeout(() => {
215
+ this.pendingRequests.delete(id);
216
+ reject(new Error(`Request timeout: ${method}`));
217
+ }, this.config.timeout);
218
+ // Store request for response handling
219
+ this.pendingRequests.set(id, { resolve, reject, timeout });
220
+ // Send message
221
+ const messageStr = JSON.stringify(message) + "\n";
222
+ this.process.stdin.write(messageStr);
223
+ logger.debug(`[External MCP] Sent request ${id}: ${method}`);
224
+ });
225
+ }
226
+ /**
227
+ * Handle incoming messages from the server
228
+ */
229
+ handleMessage(data) {
230
+ this.buffer += data;
231
+ let lineEnd;
232
+ while ((lineEnd = this.buffer.indexOf("\n")) !== -1) {
233
+ const line = this.buffer.slice(0, lineEnd);
234
+ this.buffer = this.buffer.slice(lineEnd + 1);
235
+ if (line.trim()) {
236
+ try {
237
+ const message = JSON.parse(line);
238
+ this.processMessage(message);
239
+ }
240
+ catch (error) {
241
+ logger.warn(`[External MCP] Failed to parse message from ${this.config.name}:`, line);
242
+ }
243
+ }
244
+ }
245
+ }
246
+ /**
247
+ * Process a parsed MCP message
248
+ */
249
+ processMessage(message) {
250
+ if (message.id !== undefined && this.pendingRequests.has(message.id)) {
251
+ // Response to our request
252
+ const pending = this.pendingRequests.get(message.id);
253
+ this.pendingRequests.delete(message.id);
254
+ clearTimeout(pending.timeout);
255
+ if (message.error) {
256
+ pending.reject(new Error(message.error.message));
257
+ }
258
+ else {
259
+ pending.resolve(message.result);
260
+ }
261
+ }
262
+ else if (message.method) {
263
+ // Notification or request from server
264
+ logger.debug(`[External MCP] Received notification: ${message.method}`);
265
+ this.emit("notification", message);
266
+ }
267
+ }
268
+ /**
269
+ * Disconnect from the server
270
+ */
271
+ async disconnect() {
272
+ if (!this.isConnected && !this.process) {
273
+ return;
274
+ }
275
+ logger.info(`[External MCP] Disconnecting from ${this.config.name}`);
276
+ // Clear pending requests
277
+ for (const pending of this.pendingRequests.values()) {
278
+ clearTimeout(pending.timeout);
279
+ pending.reject(new Error("Connection closed"));
280
+ }
281
+ this.pendingRequests.clear();
282
+ // Close process
283
+ if (this.process) {
284
+ this.process.kill("SIGTERM");
285
+ // Force kill after timeout
286
+ setTimeout(() => {
287
+ if (this.process && !this.process.killed) {
288
+ this.process.kill("SIGKILL");
289
+ }
290
+ }, 5000);
291
+ this.process = null;
292
+ }
293
+ this.isConnected = false;
294
+ this.tools.clear();
295
+ this.emit("disconnected");
296
+ }
297
+ /**
298
+ * Check if connected
299
+ */
300
+ isConnectedToServer() {
301
+ return this.isConnected && this.process !== null;
302
+ }
303
+ /**
304
+ * Get server information
305
+ */
306
+ getServerInfo() {
307
+ return {
308
+ name: this.config.name,
309
+ command: this.config.command,
310
+ args: this.config.args,
311
+ transport: this.config.transport,
312
+ isConnected: this.isConnected,
313
+ toolCount: this.tools.size,
314
+ tools: Array.from(this.tools.keys()),
315
+ };
316
+ }
317
+ }
318
+ /**
319
+ * Create an external MCP client
320
+ */
321
+ export function createExternalMCPClient(config) {
322
+ return new ExternalMCPClient(config);
323
+ }
@@ -0,0 +1,112 @@
1
+ /**
2
+ * NeuroLink External MCP Manager
3
+ * Manages external MCP servers and bridges them into the NeuroLink factory ecosystem
4
+ * Reads .mcp-config.json and spawns external clients
5
+ */
6
+ import { ExternalMCPClient } from "./external-client.js";
7
+ import type { NeuroLinkMCPServer, NeuroLinkExecutionContext, ToolResult } from "./factory.js";
8
+ import { MCPToolRegistry } from "./tool-registry.js";
9
+ /**
10
+ * External server connection info
11
+ */
12
+ interface ExternalServerInfo {
13
+ name: string;
14
+ client: ExternalMCPClient;
15
+ server: NeuroLinkMCPServer;
16
+ status: "connecting" | "connected" | "disconnected" | "error";
17
+ lastError?: string;
18
+ toolCount: number;
19
+ retryCount: number;
20
+ }
21
+ /**
22
+ * External MCP Manager
23
+ * Bridges external MCP servers into NeuroLink's factory pattern ecosystem
24
+ */
25
+ export declare class ExternalMCPManager {
26
+ private servers;
27
+ private registry;
28
+ private configPath;
29
+ private config;
30
+ private isInitialized;
31
+ constructor(configPath?: string, registry?: MCPToolRegistry);
32
+ /**
33
+ * Initialize the external MCP manager
34
+ * Reads config and connects to all external servers
35
+ */
36
+ initialize(): Promise<void>;
37
+ /**
38
+ * Load MCP configuration from file
39
+ */
40
+ private loadConfig;
41
+ /**
42
+ * Connect to a specific external server
43
+ */
44
+ connectToServer(serverName: string): Promise<ExternalServerInfo | null>;
45
+ /**
46
+ * Register tools from an external server with the NeuroLink registry
47
+ */
48
+ private registerServerTools;
49
+ /**
50
+ * Get all connected external servers
51
+ */
52
+ getConnectedServers(): ExternalServerInfo[];
53
+ /**
54
+ * Get server status
55
+ */
56
+ getServerStatus(serverName: string): ExternalServerInfo | undefined;
57
+ /**
58
+ * Get all server statuses
59
+ */
60
+ getAllServerStatuses(): Record<string, ExternalServerInfo>;
61
+ /**
62
+ * Execute a tool on any connected server
63
+ */
64
+ executeTool(toolName: string, params: any, context: NeuroLinkExecutionContext): Promise<ToolResult>;
65
+ /**
66
+ * List all available tools from external servers
67
+ */
68
+ listExternalTools(): Promise<import("./tool-registry.js").ToolInfo[]>;
69
+ /**
70
+ * Get registry instance
71
+ */
72
+ getRegistry(): MCPToolRegistry;
73
+ /**
74
+ * Disconnect from a specific server
75
+ */
76
+ disconnectServer(serverName: string): Promise<boolean>;
77
+ /**
78
+ * Disconnect from all servers
79
+ */
80
+ disconnectAll(): Promise<void>;
81
+ /**
82
+ * Refresh connections - reload config and reconnect
83
+ */
84
+ refresh(): Promise<void>;
85
+ /**
86
+ * Get comprehensive status
87
+ */
88
+ getStatus(): {
89
+ isInitialized: boolean;
90
+ configPath: string;
91
+ totalServers: number;
92
+ connected: number;
93
+ connecting: number;
94
+ disconnected: number;
95
+ errors: number;
96
+ totalTools: number;
97
+ servers: Record<string, ExternalServerInfo>;
98
+ };
99
+ }
100
+ /**
101
+ * Default external MCP manager instance
102
+ */
103
+ export declare const defaultExternalMCPManager: ExternalMCPManager;
104
+ /**
105
+ * Initialize external MCP servers with default manager
106
+ */
107
+ export declare function initializeExternalMCP(configPath?: string): Promise<void>;
108
+ /**
109
+ * Get the default external MCP manager
110
+ */
111
+ export declare function getExternalMCPManager(): ExternalMCPManager;
112
+ export {};