@juspay/neurolink 6.1.0 โ†’ 6.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (283) hide show
  1. package/CHANGELOG.md +10 -6
  2. package/dist/cli/commands/config.d.ts +13 -13
  3. package/dist/cli/index.js +3 -9
  4. package/dist/core/analytics.d.ts +11 -1
  5. package/dist/core/analytics.js +2 -2
  6. package/dist/core/base-provider.js +4 -18
  7. package/dist/core/dynamic-models.d.ts +8 -8
  8. package/dist/core/factory.js +3 -11
  9. package/dist/index.d.ts +2 -4
  10. package/dist/index.js +2 -11
  11. package/dist/lib/core/analytics.d.ts +11 -1
  12. package/dist/lib/core/analytics.js +2 -2
  13. package/dist/lib/core/base-provider.js +4 -18
  14. package/dist/lib/core/dynamic-models.d.ts +8 -8
  15. package/dist/lib/core/factory.js +3 -11
  16. package/dist/lib/index.d.ts +2 -4
  17. package/dist/lib/index.js +2 -11
  18. package/dist/lib/mcp/factory.d.ts +1 -1
  19. package/dist/lib/mcp/index.d.ts +7 -19
  20. package/dist/lib/mcp/index.js +15 -56
  21. package/dist/lib/neurolink.d.ts +1 -9
  22. package/dist/lib/neurolink.js +21 -70
  23. package/dist/lib/providers/amazon-bedrock.js +5 -16
  24. package/dist/lib/providers/anthropic-baseprovider.js +3 -21
  25. package/dist/lib/providers/anthropic.js +4 -7
  26. package/dist/lib/providers/azure-openai.js +4 -2
  27. package/dist/lib/providers/google-vertex.js +5 -9
  28. package/dist/lib/providers/huggingFace.js +5 -10
  29. package/dist/lib/providers/mistral.js +5 -8
  30. package/dist/lib/providers/openAI.js +4 -7
  31. package/dist/lib/utils/providerConfig.d.ts +117 -0
  32. package/dist/lib/utils/providerConfig.js +353 -0
  33. package/dist/lib/utils/providerUtils.d.ts +2 -1
  34. package/dist/lib/utils/providerUtils.js +53 -36
  35. package/dist/lib/utils/timeout.d.ts +72 -1
  36. package/dist/lib/utils/timeout.js +203 -2
  37. package/dist/mcp/factory.d.ts +1 -1
  38. package/dist/mcp/index.d.ts +7 -19
  39. package/dist/mcp/index.js +15 -56
  40. package/dist/neurolink.d.ts +1 -9
  41. package/dist/neurolink.js +21 -70
  42. package/dist/providers/amazon-bedrock.js +5 -16
  43. package/dist/providers/anthropic-baseprovider.js +3 -21
  44. package/dist/providers/anthropic.js +4 -7
  45. package/dist/providers/azure-openai.js +4 -2
  46. package/dist/providers/google-vertex.js +5 -9
  47. package/dist/providers/huggingFace.js +5 -10
  48. package/dist/providers/mistral.js +5 -8
  49. package/dist/providers/openAI.js +4 -7
  50. package/dist/utils/providerConfig.d.ts +117 -0
  51. package/dist/utils/providerConfig.js +353 -0
  52. package/dist/utils/providerUtils.d.ts +2 -1
  53. package/dist/utils/providerUtils.js +53 -36
  54. package/dist/utils/timeout.d.ts +72 -1
  55. package/dist/utils/timeout.js +203 -2
  56. package/package.json +1 -1
  57. package/dist/chat/client-utils.d.ts +0 -95
  58. package/dist/chat/client-utils.js +0 -315
  59. package/dist/chat/index.d.ts +0 -24
  60. package/dist/chat/index.js +0 -33
  61. package/dist/chat/session-storage.d.ts +0 -77
  62. package/dist/chat/session-storage.js +0 -233
  63. package/dist/chat/session.d.ts +0 -96
  64. package/dist/chat/session.js +0 -257
  65. package/dist/chat/sse-handler.d.ts +0 -49
  66. package/dist/chat/sse-handler.js +0 -259
  67. package/dist/chat/types.d.ts +0 -74
  68. package/dist/chat/types.js +0 -5
  69. package/dist/chat/websocket-chat-handler.d.ts +0 -37
  70. package/dist/chat/websocket-chat-handler.js +0 -262
  71. package/dist/cli/commands/mcp.d.ts +0 -20
  72. package/dist/cli/commands/mcp.js +0 -1272
  73. package/dist/core/defaults.d.ts +0 -19
  74. package/dist/core/defaults.js +0 -29
  75. package/dist/core/evaluation-config.d.ts +0 -29
  76. package/dist/core/evaluation-config.js +0 -144
  77. package/dist/factories/compatibility-factory.d.ts +0 -35
  78. package/dist/factories/compatibility-factory.js +0 -71
  79. package/dist/factories/provider-generate-factory.d.ts +0 -20
  80. package/dist/factories/provider-generate-factory.js +0 -93
  81. package/dist/lib/chat/client-utils.d.ts +0 -95
  82. package/dist/lib/chat/client-utils.js +0 -315
  83. package/dist/lib/chat/index.d.ts +0 -24
  84. package/dist/lib/chat/index.js +0 -33
  85. package/dist/lib/chat/session-storage.d.ts +0 -77
  86. package/dist/lib/chat/session-storage.js +0 -233
  87. package/dist/lib/chat/session.d.ts +0 -96
  88. package/dist/lib/chat/session.js +0 -257
  89. package/dist/lib/chat/sse-handler.d.ts +0 -49
  90. package/dist/lib/chat/sse-handler.js +0 -259
  91. package/dist/lib/chat/types.d.ts +0 -74
  92. package/dist/lib/chat/types.js +0 -5
  93. package/dist/lib/chat/websocket-chat-handler.d.ts +0 -37
  94. package/dist/lib/chat/websocket-chat-handler.js +0 -262
  95. package/dist/lib/core/defaults.d.ts +0 -19
  96. package/dist/lib/core/defaults.js +0 -29
  97. package/dist/lib/core/evaluation-config.d.ts +0 -29
  98. package/dist/lib/core/evaluation-config.js +0 -144
  99. package/dist/lib/factories/compatibility-factory.d.ts +0 -35
  100. package/dist/lib/factories/compatibility-factory.js +0 -71
  101. package/dist/lib/factories/provider-generate-factory.d.ts +0 -20
  102. package/dist/lib/factories/provider-generate-factory.js +0 -93
  103. package/dist/lib/mcp/adapters/plugin-bridge.d.ts +0 -40
  104. package/dist/lib/mcp/adapters/plugin-bridge.js +0 -89
  105. package/dist/lib/mcp/auto-discovery.d.ts +0 -62
  106. package/dist/lib/mcp/auto-discovery.js +0 -149
  107. package/dist/lib/mcp/client.d.ts +0 -68
  108. package/dist/lib/mcp/client.js +0 -248
  109. package/dist/lib/mcp/config.d.ts +0 -31
  110. package/dist/lib/mcp/config.js +0 -99
  111. package/dist/lib/mcp/context-manager.d.ts +0 -171
  112. package/dist/lib/mcp/context-manager.js +0 -362
  113. package/dist/lib/mcp/contracts/mcp-contract.d.ts +0 -169
  114. package/dist/lib/mcp/contracts/mcp-contract.js +0 -58
  115. package/dist/lib/mcp/core/plugin-manager.d.ts +0 -46
  116. package/dist/lib/mcp/core/plugin-manager.js +0 -110
  117. package/dist/lib/mcp/demo/plugin-demo.d.ts +0 -20
  118. package/dist/lib/mcp/demo/plugin-demo.js +0 -118
  119. package/dist/lib/mcp/dynamic-chain-executor.d.ts +0 -225
  120. package/dist/lib/mcp/dynamic-chain-executor.js +0 -489
  121. package/dist/lib/mcp/dynamic-orchestrator.d.ts +0 -115
  122. package/dist/lib/mcp/dynamic-orchestrator.js +0 -351
  123. package/dist/lib/mcp/ecosystem.d.ts +0 -75
  124. package/dist/lib/mcp/ecosystem.js +0 -161
  125. package/dist/lib/mcp/error-manager.d.ts +0 -254
  126. package/dist/lib/mcp/error-manager.js +0 -501
  127. package/dist/lib/mcp/error-recovery.d.ts +0 -159
  128. package/dist/lib/mcp/error-recovery.js +0 -405
  129. package/dist/lib/mcp/external-client.d.ts +0 -88
  130. package/dist/lib/mcp/external-client.js +0 -331
  131. package/dist/lib/mcp/external-manager.d.ts +0 -112
  132. package/dist/lib/mcp/external-manager.js +0 -308
  133. package/dist/lib/mcp/function-calling.d.ts +0 -65
  134. package/dist/lib/mcp/function-calling.js +0 -642
  135. package/dist/lib/mcp/health-monitor.d.ts +0 -257
  136. package/dist/lib/mcp/health-monitor.js +0 -630
  137. package/dist/lib/mcp/initialize-tools.d.ts +0 -29
  138. package/dist/lib/mcp/initialize-tools.js +0 -261
  139. package/dist/lib/mcp/initialize.d.ts +0 -18
  140. package/dist/lib/mcp/initialize.js +0 -62
  141. package/dist/lib/mcp/manager.d.ts +0 -68
  142. package/dist/lib/mcp/manager.js +0 -176
  143. package/dist/lib/mcp/neurolink-mcp-client.d.ts +0 -97
  144. package/dist/lib/mcp/neurolink-mcp-client.js +0 -462
  145. package/dist/lib/mcp/orchestrator.d.ts +0 -302
  146. package/dist/lib/mcp/orchestrator.js +0 -703
  147. package/dist/lib/mcp/plugin-manager.d.ts +0 -98
  148. package/dist/lib/mcp/plugin-manager.js +0 -296
  149. package/dist/lib/mcp/plugins/core/filesystem-mcp.d.ts +0 -36
  150. package/dist/lib/mcp/plugins/core/filesystem-mcp.js +0 -142
  151. package/dist/lib/mcp/plugins/filesystem-mcp.d.ts +0 -37
  152. package/dist/lib/mcp/plugins/filesystem-mcp.js +0 -54
  153. package/dist/lib/mcp/security-manager.d.ts +0 -87
  154. package/dist/lib/mcp/security-manager.js +0 -344
  155. package/dist/lib/mcp/semaphore-manager.d.ts +0 -137
  156. package/dist/lib/mcp/semaphore-manager.js +0 -329
  157. package/dist/lib/mcp/session-manager.d.ts +0 -187
  158. package/dist/lib/mcp/session-manager.js +0 -400
  159. package/dist/lib/mcp/session-persistence.d.ts +0 -93
  160. package/dist/lib/mcp/session-persistence.js +0 -301
  161. package/dist/lib/mcp/tool-integration.d.ts +0 -58
  162. package/dist/lib/mcp/tool-integration.js +0 -203
  163. package/dist/lib/mcp/transport-manager.d.ts +0 -154
  164. package/dist/lib/mcp/transport-manager.js +0 -334
  165. package/dist/lib/mcp/unified-mcp.d.ts +0 -133
  166. package/dist/lib/mcp/unified-mcp.js +0 -251
  167. package/dist/lib/mcp/unified-registry.d.ts +0 -165
  168. package/dist/lib/mcp/unified-registry.js +0 -538
  169. package/dist/lib/providers/analytics-helper.d.ts +0 -38
  170. package/dist/lib/providers/analytics-helper.js +0 -216
  171. package/dist/lib/providers/function-calling-provider.d.ts +0 -142
  172. package/dist/lib/providers/function-calling-provider.js +0 -630
  173. package/dist/lib/providers/mcp-provider.d.ts +0 -75
  174. package/dist/lib/providers/mcp-provider.js +0 -283
  175. package/dist/lib/providers/timeout-wrapper.d.ts +0 -40
  176. package/dist/lib/providers/timeout-wrapper.js +0 -100
  177. package/dist/lib/sdk/tool-extension.d.ts +0 -181
  178. package/dist/lib/sdk/tool-extension.js +0 -284
  179. package/dist/lib/services/streaming/streaming-manager.d.ts +0 -29
  180. package/dist/lib/services/streaming/streaming-manager.js +0 -245
  181. package/dist/lib/services/types.d.ts +0 -156
  182. package/dist/lib/services/types.js +0 -2
  183. package/dist/lib/services/websocket/websocket-server.d.ts +0 -34
  184. package/dist/lib/services/websocket/websocket-server.js +0 -305
  185. package/dist/lib/utils/provider-validation.d.ts +0 -36
  186. package/dist/lib/utils/provider-validation.js +0 -625
  187. package/dist/lib/utils/providerUtils-fixed.d.ts +0 -8
  188. package/dist/lib/utils/providerUtils-fixed.js +0 -94
  189. package/dist/lib/utils/streaming-utils.d.ts +0 -79
  190. package/dist/lib/utils/streaming-utils.js +0 -198
  191. package/dist/lib/utils/timeout-manager.d.ts +0 -75
  192. package/dist/lib/utils/timeout-manager.js +0 -244
  193. package/dist/mcp/adapters/plugin-bridge.d.ts +0 -40
  194. package/dist/mcp/adapters/plugin-bridge.js +0 -89
  195. package/dist/mcp/auto-discovery.d.ts +0 -62
  196. package/dist/mcp/auto-discovery.js +0 -149
  197. package/dist/mcp/client.d.ts +0 -68
  198. package/dist/mcp/client.js +0 -248
  199. package/dist/mcp/config.d.ts +0 -31
  200. package/dist/mcp/config.js +0 -99
  201. package/dist/mcp/context-manager.d.ts +0 -171
  202. package/dist/mcp/context-manager.js +0 -362
  203. package/dist/mcp/contracts/mcp-contract.d.ts +0 -169
  204. package/dist/mcp/contracts/mcp-contract.js +0 -58
  205. package/dist/mcp/core/plugin-manager.d.ts +0 -46
  206. package/dist/mcp/core/plugin-manager.js +0 -110
  207. package/dist/mcp/demo/plugin-demo.d.ts +0 -20
  208. package/dist/mcp/demo/plugin-demo.js +0 -118
  209. package/dist/mcp/dynamic-chain-executor.d.ts +0 -225
  210. package/dist/mcp/dynamic-chain-executor.js +0 -489
  211. package/dist/mcp/dynamic-orchestrator.d.ts +0 -115
  212. package/dist/mcp/dynamic-orchestrator.js +0 -351
  213. package/dist/mcp/ecosystem.d.ts +0 -75
  214. package/dist/mcp/ecosystem.js +0 -162
  215. package/dist/mcp/error-manager.d.ts +0 -254
  216. package/dist/mcp/error-manager.js +0 -501
  217. package/dist/mcp/error-recovery.d.ts +0 -159
  218. package/dist/mcp/error-recovery.js +0 -405
  219. package/dist/mcp/external-client.d.ts +0 -88
  220. package/dist/mcp/external-client.js +0 -331
  221. package/dist/mcp/external-manager.d.ts +0 -112
  222. package/dist/mcp/external-manager.js +0 -308
  223. package/dist/mcp/function-calling.d.ts +0 -65
  224. package/dist/mcp/function-calling.js +0 -642
  225. package/dist/mcp/health-monitor.d.ts +0 -257
  226. package/dist/mcp/health-monitor.js +0 -630
  227. package/dist/mcp/initialize-tools.d.ts +0 -29
  228. package/dist/mcp/initialize-tools.js +0 -262
  229. package/dist/mcp/initialize.d.ts +0 -18
  230. package/dist/mcp/initialize.js +0 -62
  231. package/dist/mcp/manager.d.ts +0 -68
  232. package/dist/mcp/manager.js +0 -176
  233. package/dist/mcp/neurolink-mcp-client.d.ts +0 -97
  234. package/dist/mcp/neurolink-mcp-client.js +0 -462
  235. package/dist/mcp/orchestrator.d.ts +0 -302
  236. package/dist/mcp/orchestrator.js +0 -703
  237. package/dist/mcp/plugin-manager.d.ts +0 -98
  238. package/dist/mcp/plugin-manager.js +0 -297
  239. package/dist/mcp/plugins/core/filesystem-mcp.d.ts +0 -36
  240. package/dist/mcp/plugins/core/filesystem-mcp.js +0 -142
  241. package/dist/mcp/plugins/core/neurolink-mcp.json +0 -17
  242. package/dist/mcp/plugins/filesystem-mcp.d.ts +0 -37
  243. package/dist/mcp/plugins/filesystem-mcp.js +0 -54
  244. package/dist/mcp/security-manager.d.ts +0 -87
  245. package/dist/mcp/security-manager.js +0 -344
  246. package/dist/mcp/semaphore-manager.d.ts +0 -137
  247. package/dist/mcp/semaphore-manager.js +0 -329
  248. package/dist/mcp/session-manager.d.ts +0 -187
  249. package/dist/mcp/session-manager.js +0 -400
  250. package/dist/mcp/session-persistence.d.ts +0 -93
  251. package/dist/mcp/session-persistence.js +0 -302
  252. package/dist/mcp/tool-integration.d.ts +0 -58
  253. package/dist/mcp/tool-integration.js +0 -203
  254. package/dist/mcp/transport-manager.d.ts +0 -154
  255. package/dist/mcp/transport-manager.js +0 -335
  256. package/dist/mcp/unified-mcp.d.ts +0 -133
  257. package/dist/mcp/unified-mcp.js +0 -251
  258. package/dist/mcp/unified-registry.d.ts +0 -165
  259. package/dist/mcp/unified-registry.js +0 -539
  260. package/dist/providers/analytics-helper.d.ts +0 -38
  261. package/dist/providers/analytics-helper.js +0 -216
  262. package/dist/providers/function-calling-provider.d.ts +0 -142
  263. package/dist/providers/function-calling-provider.js +0 -630
  264. package/dist/providers/mcp-provider.d.ts +0 -75
  265. package/dist/providers/mcp-provider.js +0 -283
  266. package/dist/providers/timeout-wrapper.d.ts +0 -40
  267. package/dist/providers/timeout-wrapper.js +0 -100
  268. package/dist/sdk/tool-extension.d.ts +0 -181
  269. package/dist/sdk/tool-extension.js +0 -284
  270. package/dist/services/streaming/streaming-manager.d.ts +0 -29
  271. package/dist/services/streaming/streaming-manager.js +0 -245
  272. package/dist/services/types.d.ts +0 -156
  273. package/dist/services/types.js +0 -2
  274. package/dist/services/websocket/websocket-server.d.ts +0 -34
  275. package/dist/services/websocket/websocket-server.js +0 -306
  276. package/dist/utils/provider-validation.d.ts +0 -36
  277. package/dist/utils/provider-validation.js +0 -625
  278. package/dist/utils/providerUtils-fixed.d.ts +0 -8
  279. package/dist/utils/providerUtils-fixed.js +0 -94
  280. package/dist/utils/streaming-utils.d.ts +0 -79
  281. package/dist/utils/streaming-utils.js +0 -198
  282. package/dist/utils/timeout-manager.d.ts +0 -75
  283. package/dist/utils/timeout-manager.js +0 -244
@@ -1,1272 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * MCP Server Management Commands
4
- * Real MCP server connectivity and management
5
- */
6
- import ora from "ora";
7
- import chalk from "chalk";
8
- import fs from "fs";
9
- import { spawn } from "child_process";
10
- import path from "path";
11
- import { discoverMCPServers } from "../../lib/mcp/auto-discovery.js";
12
- import { unifiedRegistry } from "../../lib/mcp/unified-registry.js";
13
- import { ContextManager } from "../../lib/mcp/context-manager.js";
14
- import { MCPOrchestrator } from "../../lib/mcp/orchestrator.js";
15
- import { initializeNeuroLinkMCP } from "../../lib/mcp/initialize.js";
16
- import { mcpLogger, setGlobalMCPLogLevel } from "../../lib/mcp/logging.js";
17
- // import type { LogLevel } from "../../lib/mcp/logging.js"; // Commented out as unused
18
- import { defaultTimeoutManager } from "../../lib/utils/timeout-manager.js";
19
- // Default MCP config file location
20
- const MCP_CONFIG_FILE = path.join(process.cwd(), ".mcp-config.json");
21
- // Load MCP configuration
22
- function loadMCPConfig() {
23
- if (!fs.existsSync(MCP_CONFIG_FILE)) {
24
- return { mcpServers: {} };
25
- }
26
- try {
27
- const content = fs.readFileSync(MCP_CONFIG_FILE, "utf-8");
28
- return JSON.parse(content);
29
- }
30
- catch (error) {
31
- throw new Error(`Invalid MCP config file: ${error.message}`);
32
- }
33
- }
34
- // Save MCP configuration
35
- function saveMCPConfig(config) {
36
- fs.writeFileSync(MCP_CONFIG_FILE, JSON.stringify(config, null, 2));
37
- }
38
- // Check if MCP server process is running
39
- async function checkMCPServerStatus(serverConfig) {
40
- try {
41
- if (serverConfig.transport === "stdio") {
42
- // For stdio servers, use timeout manager for proper cleanup
43
- const result = await defaultTimeoutManager.wrapMCPOperation(async () => {
44
- const child = spawn(serverConfig.command, serverConfig.args || [], {
45
- stdio: ["pipe", "pipe", "pipe"],
46
- env: { ...process.env, ...serverConfig.env },
47
- cwd: serverConfig.cwd,
48
- });
49
- return new Promise((resolve, reject) => {
50
- child.on("spawn", () => {
51
- child.kill();
52
- resolve(true);
53
- });
54
- child.on("error", (error) => {
55
- reject(error);
56
- });
57
- child.on("exit", (code) => {
58
- if (code === null) {
59
- // Process was terminated (expected for quick check)
60
- resolve(true);
61
- }
62
- else {
63
- resolve(false);
64
- }
65
- });
66
- });
67
- }, "server-status-check", 10000);
68
- return result.success && result.data === true;
69
- }
70
- else if (serverConfig.transport === "sse" && serverConfig.url) {
71
- // For SSE servers, check if URL is accessible with timeout
72
- const result = await defaultTimeoutManager.wrapMCPOperation(async () => {
73
- if (!serverConfig.url) {
74
- throw new Error("SSE URL not configured");
75
- }
76
- const response = await fetch(serverConfig.url, { method: "HEAD" });
77
- return response.ok;
78
- }, "sse-status-check", 10000);
79
- return result.success && result.data === true;
80
- }
81
- return false;
82
- }
83
- catch {
84
- return false;
85
- }
86
- }
87
- // Connect to MCP server and get capabilities
88
- async function getMCPServerCapabilities(serverConfig) {
89
- if (serverConfig.transport === "stdio") {
90
- // Use timeout manager for proper cleanup and longer timeout
91
- const result = await defaultTimeoutManager.wrapMCPOperation(async () => {
92
- const child = spawn(serverConfig.command, serverConfig.args || [], {
93
- stdio: ["pipe", "pipe", "pipe"],
94
- env: { ...process.env, ...serverConfig.env },
95
- cwd: serverConfig.cwd,
96
- });
97
- return new Promise((resolve, reject) => {
98
- let responseData = "";
99
- child.stdout?.on("data", (data) => {
100
- responseData += data.toString();
101
- // Look for JSON-RPC response
102
- try {
103
- const lines = responseData.split("\n");
104
- for (const line of lines) {
105
- if (line.trim() && line.includes('"result"')) {
106
- const response = JSON.parse(line.trim());
107
- if (response.result && response.result.capabilities) {
108
- child.kill();
109
- resolve(response.result);
110
- return;
111
- }
112
- }
113
- }
114
- }
115
- catch {
116
- // Continue parsing
117
- }
118
- });
119
- child.on("spawn", () => {
120
- // Send initialize request
121
- const initRequest = {
122
- jsonrpc: "2.0",
123
- id: 1,
124
- method: "initialize",
125
- params: {
126
- protocolVersion: "2024-11-05",
127
- capabilities: {},
128
- clientInfo: {
129
- name: "neurolink-cli",
130
- version: "1.0.0",
131
- },
132
- },
133
- };
134
- child.stdin?.write(JSON.stringify(initRequest) + "\n");
135
- });
136
- child.on("error", (error) => {
137
- reject(error);
138
- });
139
- });
140
- }, "server-capabilities-check", 15000);
141
- if (result.success) {
142
- return result.data;
143
- }
144
- else {
145
- throw result.error || new Error("Failed to get MCP server capabilities");
146
- }
147
- }
148
- throw new Error("SSE transport not yet implemented for capabilities");
149
- }
150
- // List available tools from MCP server
151
- async function listMCPServerTools(serverConfig) {
152
- if (serverConfig.transport === "stdio") {
153
- // Use timeout manager for proper cleanup and longer timeout
154
- const result = await defaultTimeoutManager.wrapMCPOperation(async () => {
155
- const child = spawn(serverConfig.command, serverConfig.args || [], {
156
- stdio: ["pipe", "pipe", "pipe"],
157
- env: { ...process.env, ...serverConfig.env },
158
- cwd: serverConfig.cwd,
159
- });
160
- return new Promise((resolve, reject) => {
161
- let responseData = "";
162
- // let initialized = false; // Commented out as unused
163
- child.stdout?.on("data", (data) => {
164
- responseData += data.toString();
165
- try {
166
- const lines = responseData.split("\n");
167
- for (const line of lines) {
168
- if (line.trim() && line.includes('"result"')) {
169
- const response = JSON.parse(line.trim());
170
- if (response.id === 1 && response.result.capabilities) {
171
- // Initialize successful, now list tools
172
- // initialized = true; // Commented out as unused
173
- const listToolsRequest = {
174
- jsonrpc: "2.0",
175
- id: 2,
176
- method: "tools/list",
177
- params: {},
178
- };
179
- child.stdin?.write(JSON.stringify(listToolsRequest) + "\n");
180
- }
181
- else if (response.id === 2 && response.result.tools) {
182
- child.kill();
183
- resolve(response.result.tools);
184
- return;
185
- }
186
- }
187
- }
188
- }
189
- catch {
190
- // Continue parsing
191
- }
192
- });
193
- child.on("spawn", () => {
194
- // Send initialize request first
195
- const initRequest = {
196
- jsonrpc: "2.0",
197
- id: 1,
198
- method: "initialize",
199
- params: {
200
- protocolVersion: "2024-11-05",
201
- capabilities: {},
202
- clientInfo: {
203
- name: "neurolink-cli",
204
- version: "1.0.0",
205
- },
206
- },
207
- };
208
- child.stdin?.write(JSON.stringify(initRequest) + "\n");
209
- });
210
- child.on("error", (error) => {
211
- reject(error);
212
- });
213
- });
214
- }, "server-tools-list", 15000);
215
- if (result.success) {
216
- return result.data || [];
217
- }
218
- else {
219
- throw result.error || new Error("Failed to list MCP server tools");
220
- }
221
- }
222
- throw new Error("SSE transport not yet implemented for tool listing");
223
- }
224
- // Execute tool on MCP server
225
- export async function executeMCPTool(serverConfig, toolName, toolParams) {
226
- if (serverConfig.transport === "stdio") {
227
- // Use timeout manager for proper cleanup and configurable timeout
228
- const result = await defaultTimeoutManager.wrapMCPOperation(async () => {
229
- const child = spawn(serverConfig.command, serverConfig.args || [], {
230
- stdio: ["pipe", "pipe", "pipe"],
231
- env: { ...process.env, ...serverConfig.env },
232
- cwd: serverConfig.cwd,
233
- });
234
- return new Promise((resolve, reject) => {
235
- let responseData = "";
236
- // let initialized = false; // Commented out as unused
237
- child.stdout?.on("data", (data) => {
238
- responseData += data.toString();
239
- try {
240
- const lines = responseData.split("\n");
241
- for (const line of lines) {
242
- if (line.trim() && line.includes('"result"')) {
243
- const response = JSON.parse(line.trim());
244
- if (response.id === 1 && response.result.capabilities) {
245
- // Initialize successful, now execute tool
246
- // initialized = true; // Commented out as unused
247
- const toolCallRequest = {
248
- jsonrpc: "2.0",
249
- id: 2,
250
- method: "tools/call",
251
- params: {
252
- name: toolName,
253
- arguments: toolParams,
254
- },
255
- };
256
- child.stdin?.write(JSON.stringify(toolCallRequest) + "\n");
257
- }
258
- else if (response.id === 2) {
259
- child.kill();
260
- if (response.result) {
261
- resolve(response.result);
262
- }
263
- else if (response.error) {
264
- reject(new Error(`MCP Error: ${response.error.message || "Unknown error"}`));
265
- }
266
- else {
267
- reject(new Error("Unknown MCP response format"));
268
- }
269
- return;
270
- }
271
- }
272
- else if (line.trim() && line.includes('"error"')) {
273
- const response = JSON.parse(line.trim());
274
- if (response.error) {
275
- child.kill();
276
- reject(new Error(`MCP Error: ${response.error.message || "Unknown error"}`));
277
- return;
278
- }
279
- }
280
- }
281
- }
282
- catch {
283
- // Continue parsing
284
- }
285
- });
286
- child.stderr?.on("data", (data) => {
287
- console.error(chalk.red(`MCP Server Error: ${data.toString()}`));
288
- });
289
- child.on("spawn", () => {
290
- // Send initialize request first
291
- const initRequest = {
292
- jsonrpc: "2.0",
293
- id: 1,
294
- method: "initialize",
295
- params: {
296
- protocolVersion: "2024-11-05",
297
- capabilities: {},
298
- clientInfo: {
299
- name: "neurolink-cli",
300
- version: "1.0.0",
301
- },
302
- },
303
- };
304
- child.stdin?.write(JSON.stringify(initRequest) + "\n");
305
- });
306
- child.on("error", (error) => {
307
- reject(error);
308
- });
309
- });
310
- }, "tool-execution", 30000);
311
- if (result.success) {
312
- return result.data || null;
313
- }
314
- else {
315
- throw result.error || new Error("Failed to execute MCP tool");
316
- }
317
- }
318
- throw new Error("SSE transport not yet implemented for tool execution");
319
- }
320
- /**
321
- * Display discovery results in table format
322
- */
323
- function _displayTable(discoveryResult) {
324
- console.log(chalk.green(`\n๐Ÿ“‹ Found ${discoveryResult.discovered.length} MCP servers:`));
325
- console.log(chalk.gray("โ”€".repeat(80)));
326
- discoveryResult.discovered.forEach((server, index) => {
327
- const source = server.source;
328
- const sourceIcon = getSourceIcon(source?.tool);
329
- const typeColor = source?.type === "global"
330
- ? chalk.blue
331
- : source?.type === "workspace"
332
- ? chalk.green
333
- : chalk.gray;
334
- console.log(`${chalk.white(`${index + 1}.`)} ${sourceIcon} ${chalk.cyan(server.id)}`);
335
- console.log(` ${chalk.gray("Title:")} ${server.title}`);
336
- console.log(` ${chalk.gray("Source:")} ${source?.tool} ${typeColor(`(${source?.type})`)}`);
337
- console.log(` ${chalk.gray("Command:")} ${server.command} ${server.args?.join(" ") || ""}`);
338
- console.log(` ${chalk.gray("Config:")} ${server.configPath}`);
339
- if (server.env && Object.keys(server.env).length > 0) {
340
- console.log(` ${chalk.gray("Environment:")} ${Object.keys(server.env).length} variable(s)`);
341
- }
342
- console.log();
343
- });
344
- // Display statistics
345
- console.log(chalk.blue("๐Ÿ“Š Discovery Statistics:"));
346
- console.log(` ${chalk.gray("Execution time:")} ${discoveryResult.stats.executionTime}ms`);
347
- console.log(` ${chalk.gray("Config files found:")} ${discoveryResult.stats.configFilesFound}`);
348
- console.log(` ${chalk.gray("Servers discovered:")} ${discoveryResult.stats.serversDiscovered}`);
349
- console.log(` ${chalk.gray("Duplicates removed:")} ${discoveryResult.stats.duplicatesRemoved}`);
350
- // Display sources
351
- if (discoveryResult.sources.length > 0) {
352
- console.log(chalk.blue("\n๐ŸŽฏ Search Sources:"));
353
- const sourcesByTool = discoveryResult.sources.reduce((acc, source) => {
354
- const tool = String(source.tool || "unknown");
355
- acc[tool] = (Number(acc[tool]) || 0) + 1;
356
- return acc;
357
- }, {});
358
- Object.entries(sourcesByTool).forEach(([tool, count]) => {
359
- const icon = getSourceIcon(tool);
360
- console.log(` ${icon} ${tool}: ${count} location(s)`);
361
- });
362
- }
363
- }
364
- /**
365
- * Display discovery results in summary format
366
- */
367
- function _displaySummary(discoveryResult) {
368
- console.log(chalk.green(`\n๐Ÿ“Š Discovery Summary`));
369
- console.log(chalk.gray("==================="));
370
- console.log(`${chalk.cyan("Total servers found:")} ${discoveryResult.discovered.length}`);
371
- console.log(`${chalk.cyan("Execution time:")} ${discoveryResult.stats.executionTime}ms`);
372
- console.log(`${chalk.cyan("Config files found:")} ${discoveryResult.stats.configFilesFound}`);
373
- console.log(`${chalk.cyan("Duplicates removed:")} ${discoveryResult.stats.duplicatesRemoved}`);
374
- // Group by source tool
375
- const serversByTool = discoveryResult.discovered.reduce((acc, server) => {
376
- const tool = String(server.source?.tool || "unknown");
377
- acc[tool] = (Number(acc[tool]) || 0) + 1;
378
- return acc;
379
- }, {});
380
- if (Object.keys(serversByTool).length > 0) {
381
- console.log(chalk.blue("\n๐Ÿ”ง Servers by Tool:"));
382
- Object.entries(serversByTool).forEach(([tool, count]) => {
383
- const icon = getSourceIcon(tool);
384
- console.log(` ${icon} ${tool}: ${count} server(s)`);
385
- });
386
- }
387
- // Group by type
388
- const serversByType = discoveryResult.discovered.reduce((acc, server) => {
389
- const type = String(server.source?.type || "unknown");
390
- acc[type] = (Number(acc[type]) || 0) + 1;
391
- return acc;
392
- }, {});
393
- if (Object.keys(serversByType).length > 0) {
394
- console.log(chalk.blue("\n๐Ÿ“ Servers by Type:"));
395
- Object.entries(serversByType).forEach(([type, count]) => {
396
- const typeColor = type === "global"
397
- ? chalk.blue
398
- : type === "workspace"
399
- ? chalk.green
400
- : chalk.gray;
401
- console.log(` ${typeColor(`${type}:`)} ${count} server(s)`);
402
- });
403
- }
404
- }
405
- /**
406
- * Get icon for source tool
407
- */
408
- function getSourceIcon(tool) {
409
- const icons = {
410
- "Claude Desktop": "๐Ÿค–",
411
- "VS Code": "๐Ÿ“",
412
- Cursor: "๐Ÿ–ฑ๏ธ",
413
- Windsurf: "๐Ÿ„",
414
- "Roo Code": "๐Ÿฆ˜",
415
- Generic: "โš™๏ธ",
416
- "Cline AI Coder": "๐Ÿ”ง",
417
- "Continue Dev": "๐Ÿ”„",
418
- Aider: "๐Ÿ› ๏ธ",
419
- };
420
- return icons[tool] || "๐Ÿ”ง";
421
- }
422
- /**
423
- * Get icon for source type
424
- */
425
- function getSourceTypeIcon(sourceType) {
426
- const icons = {
427
- manual: "๐Ÿ“",
428
- auto: "๐Ÿ”",
429
- default: "โš™๏ธ",
430
- };
431
- return icons[sourceType] || "โ“";
432
- }
433
- /**
434
- * Get icon for server status
435
- */
436
- function _getStatusIcon(status) {
437
- const icons = {
438
- available: "โœ…",
439
- unavailable: "โŒ",
440
- unknown: "โ“",
441
- };
442
- return icons[status] || "โ“";
443
- }
444
- // Export the tool execution function for use in other parts of the CLI
445
- export async function mcpExecuteTool(serverName, toolName, toolParams) {
446
- // First try unified registry (includes built-in NeuroLink servers)
447
- try {
448
- await unifiedRegistry.initialize();
449
- const orchestrator = new MCPOrchestrator(unifiedRegistry);
450
- const result = await orchestrator.executeTool(toolName, toolParams, {
451
- sessionId: `cli-${Date.now()}`,
452
- userId: "cli-user",
453
- aiProvider: "unified-mcp",
454
- }, {
455
- preferredSource: "default", // Try built-in servers first
456
- fallbackEnabled: true,
457
- validateBeforeExecution: true,
458
- timeoutMs: 30000,
459
- });
460
- if (result.success) {
461
- return result.data;
462
- }
463
- }
464
- catch (error) {
465
- mcpLogger.debug("[mcpExecuteTool] Unified registry failed, trying manual config:", {
466
- error: error instanceof Error ? error.message : String(error),
467
- serverName,
468
- toolName: toolName,
469
- });
470
- }
471
- // Fallback to manual configuration (legacy behavior)
472
- const config = loadMCPConfig();
473
- const serverConfig = config.mcpServers[serverName];
474
- if (!serverConfig) {
475
- throw new Error(`MCP server '${serverName}' not found`);
476
- }
477
- const result = await executeMCPTool(serverConfig, toolName, toolParams);
478
- mcpLogger.debug("[mcpExecuteTool] Tool executed via manual config:", {
479
- serverName,
480
- toolName,
481
- hasResult: !!result,
482
- resultType: typeof result,
483
- });
484
- // Extract the text content from MCP result format
485
- if (result &&
486
- result.content &&
487
- Array.isArray(result.content)) {
488
- const textContent = result.content.find((item) => item.type === "text");
489
- if (textContent) {
490
- return JSON.parse(textContent.text);
491
- }
492
- }
493
- return result;
494
- }
495
- // MCP Commands for yargs
496
- export function addMCPCommands(yargs) {
497
- return yargs.command("mcp <subcommand>", "Manage MCP (Model Context Protocol) servers", (yargsBuilder) => {
498
- yargsBuilder
499
- .usage("Usage: $0 mcp <subcommand> [options]")
500
- // List MCP servers
501
- .command("list", "List configured MCP servers", (y) => y
502
- .usage("Usage: $0 mcp list [options]")
503
- .option("status", {
504
- type: "boolean",
505
- description: "Check server status",
506
- })
507
- .example("$0 mcp list", "List all MCP servers")
508
- .example("$0 mcp list --status", "List servers with status check"), async (argv) => {
509
- const config = loadMCPConfig();
510
- const servers = Object.entries(config.mcpServers);
511
- if (servers.length === 0) {
512
- console.log(chalk.yellow("๐Ÿ“ญ No MCP servers configured"));
513
- console.log(chalk.blue("๐Ÿ’ก Add a server with: neurolink mcp add <name> <command>"));
514
- return;
515
- }
516
- console.log(chalk.blue(`๐Ÿ“‹ Configured MCP servers (${servers.length}):\n`));
517
- for (const [name, serverConfig] of servers) {
518
- console.log(chalk.bold(`๐Ÿ”ง ${name}`));
519
- console.log(` Command: ${serverConfig.command} ${(serverConfig.args || []).join(" ")}`);
520
- console.log(` Transport: ${serverConfig.transport}`);
521
- if (argv.status) {
522
- const spinner = ora(`Checking ${name}...`).start();
523
- try {
524
- const isRunning = await checkMCPServerStatus(serverConfig);
525
- if (isRunning) {
526
- spinner.succeed(`${name}: ${chalk.green("โœ… Available")}`);
527
- }
528
- else {
529
- spinner.fail(`${name}: ${chalk.red("โŒ Not available")}`);
530
- }
531
- }
532
- catch (error) {
533
- spinner.fail(`${name}: ${chalk.red("โŒ Error")} - ${error.message}`);
534
- }
535
- }
536
- console.log(); // Empty line
537
- }
538
- })
539
- // Add MCP server
540
- .command("add <name> <command>", "Add a new MCP server", (y) => y
541
- .usage("Usage: $0 mcp add <name> <command> [options]")
542
- .positional("name", {
543
- type: "string",
544
- description: "Server name",
545
- demandOption: true,
546
- })
547
- .positional("command", {
548
- type: "string",
549
- description: "Command to run server",
550
- demandOption: true,
551
- })
552
- .option("args", {
553
- type: "array",
554
- description: "Command arguments",
555
- })
556
- .option("transport", {
557
- choices: ["stdio", "sse"],
558
- default: "stdio",
559
- description: "Transport type",
560
- })
561
- .option("url", {
562
- type: "string",
563
- description: "URL for SSE transport",
564
- })
565
- .option("env", {
566
- type: "string",
567
- description: "Environment variables (JSON)",
568
- })
569
- .option("cwd", {
570
- type: "string",
571
- description: "Working directory",
572
- })
573
- .example('$0 mcp add filesystem "npx @modelcontextprotocol/server-filesystem"', "Add filesystem server")
574
- .example('$0 mcp add github "npx @modelcontextprotocol/server-github"', "Add GitHub server"), async (argv) => {
575
- const config = loadMCPConfig();
576
- const serverConfig = {
577
- name: argv.name,
578
- command: argv.command,
579
- args: argv.args || [],
580
- transport: argv.transport,
581
- url: argv.url,
582
- cwd: argv.cwd,
583
- };
584
- if (argv.env) {
585
- try {
586
- serverConfig.env = JSON.parse(argv.env);
587
- }
588
- catch (error) {
589
- console.error(chalk.red("โŒ Invalid JSON for environment variables"));
590
- process.exit(1);
591
- }
592
- }
593
- config.mcpServers[argv.name] = serverConfig;
594
- saveMCPConfig(config);
595
- console.log(chalk.green(`โœ… Added MCP server: ${argv.name}`));
596
- console.log(chalk.blue(`๐Ÿ’ก Test it with: neurolink mcp test ${argv.name}`));
597
- })
598
- // Remove MCP server
599
- .command("remove <name>", "Remove an MCP server", (y) => y
600
- .usage("Usage: $0 mcp remove <name>")
601
- .positional("name", {
602
- type: "string",
603
- description: "Server name to remove",
604
- demandOption: true,
605
- })
606
- .example("$0 mcp remove filesystem", "Remove filesystem server"), async (argv) => {
607
- const config = loadMCPConfig();
608
- if (!config.mcpServers[argv.name]) {
609
- console.error(chalk.red(`โŒ MCP server '${argv.name}' not found`));
610
- process.exit(1);
611
- }
612
- delete config.mcpServers[argv.name];
613
- saveMCPConfig(config);
614
- console.log(chalk.green(`โœ… Removed MCP server: ${argv.name}`));
615
- })
616
- // Test MCP server
617
- .command("test <name>", "Test connection to an MCP server", (y) => y
618
- .usage("Usage: $0 mcp test <name>")
619
- .positional("name", {
620
- type: "string",
621
- description: "Server name to test",
622
- demandOption: true,
623
- })
624
- .example("$0 mcp test filesystem", "Test filesystem server"), async (argv) => {
625
- const config = loadMCPConfig();
626
- const serverConfig = config.mcpServers[argv.name];
627
- if (!serverConfig) {
628
- console.error(chalk.red(`โŒ MCP server '${argv.name}' not found`));
629
- process.exit(1);
630
- }
631
- console.log(chalk.blue(`๐Ÿ” Testing MCP server: ${argv.name}\n`));
632
- const spinner = ora("Connecting...").start();
633
- try {
634
- // Test basic connectivity
635
- const isRunning = await checkMCPServerStatus(serverConfig);
636
- if (!isRunning) {
637
- spinner.fail(chalk.red("โŒ Server not available"));
638
- return;
639
- }
640
- spinner.text = "Getting capabilities...";
641
- const capabilities = await getMCPServerCapabilities(serverConfig);
642
- spinner.text = "Listing tools...";
643
- const tools = await listMCPServerTools(serverConfig);
644
- spinner.succeed(chalk.green("โœ… Connection successful!"));
645
- console.log(chalk.blue("\n๐Ÿ“‹ Server Capabilities:"));
646
- console.log(` Protocol Version: ${capabilities.protocolVersion || "Unknown"}`);
647
- if (capabilities.tools) {
648
- console.log(` Tools: โœ… Supported`);
649
- }
650
- if (capabilities.resources) {
651
- console.log(` Resources: โœ… Supported`);
652
- }
653
- console.log(chalk.blue("\n๐Ÿ› ๏ธ Available Tools:"));
654
- if (tools.length === 0) {
655
- console.log(" No tools available");
656
- }
657
- else {
658
- tools.forEach((tool) => {
659
- const toolObj = tool;
660
- console.log(` โ€ข ${String(toolObj.name)}: ${String(toolObj.description) || "No description"}`);
661
- });
662
- }
663
- }
664
- catch (error) {
665
- spinner.fail(chalk.red("โŒ Connection failed"));
666
- console.error(chalk.red(`Error: ${error.message}`));
667
- }
668
- })
669
- // Install popular MCP servers
670
- .command("install <server>", "Install popular MCP servers", (y) => y
671
- .usage("Usage: $0 mcp install <server>")
672
- .positional("server", {
673
- type: "string",
674
- choices: [
675
- "filesystem",
676
- "github",
677
- "postgres",
678
- "brave-search",
679
- "puppeteer",
680
- ],
681
- description: "Server to install",
682
- demandOption: true,
683
- })
684
- .example("$0 mcp install filesystem", "Install filesystem server")
685
- .example("$0 mcp install github", "Install GitHub server"), async (argv) => {
686
- const serverName = argv.server;
687
- const config = loadMCPConfig();
688
- // Pre-configured popular MCP servers
689
- const serverConfigs = {
690
- filesystem: {
691
- name: "filesystem",
692
- command: "npx",
693
- args: ["-y", "@modelcontextprotocol/server-filesystem", "/"],
694
- transport: "stdio",
695
- },
696
- github: {
697
- name: "github",
698
- command: "npx",
699
- args: ["-y", "@modelcontextprotocol/server-github"],
700
- transport: "stdio",
701
- },
702
- postgres: {
703
- name: "postgres",
704
- command: "npx",
705
- args: ["-y", "@modelcontextprotocol/server-postgres"],
706
- transport: "stdio",
707
- },
708
- "brave-search": {
709
- name: "brave-search",
710
- command: "npx",
711
- args: ["-y", "@modelcontextprotocol/server-brave-search"],
712
- transport: "stdio",
713
- },
714
- puppeteer: {
715
- name: "puppeteer",
716
- command: "npx",
717
- args: ["-y", "@modelcontextprotocol/server-puppeteer"],
718
- transport: "stdio",
719
- },
720
- };
721
- const serverConfig = serverConfigs[serverName];
722
- if (!serverConfig) {
723
- console.error(chalk.red(`โŒ Unknown server: ${serverName}`));
724
- process.exit(1);
725
- }
726
- console.log(chalk.blue(`๐Ÿ“ฆ Installing MCP server: ${serverName}`));
727
- config.mcpServers[serverName] = serverConfig;
728
- saveMCPConfig(config);
729
- console.log(chalk.green(`โœ… Installed MCP server: ${serverName}`));
730
- console.log(chalk.blue(`๐Ÿ’ก Test it with: neurolink mcp test ${serverName}`));
731
- })
732
- // Execute tool from MCP server
733
- .command("exec <server> <tool>", "Execute a tool from an MCP server", (y) => y
734
- .usage("Usage: $0 mcp exec <server> <tool> [options]")
735
- .positional("server", {
736
- type: "string",
737
- description: "Server name",
738
- demandOption: true,
739
- })
740
- .positional("tool", {
741
- type: "string",
742
- description: "Tool name",
743
- demandOption: true,
744
- })
745
- .option("params", {
746
- type: "string",
747
- description: "Tool parameters (JSON)",
748
- })
749
- .example('$0 mcp exec filesystem read_file --params \'{"path": "README.md"}\'', "Read file using filesystem server"), async (argv) => {
750
- const config = loadMCPConfig();
751
- const serverConfig = config.mcpServers[argv.server];
752
- if (!serverConfig) {
753
- console.error(chalk.red(`โŒ MCP server '${argv.server}' not found`));
754
- process.exit(1);
755
- }
756
- let params = {};
757
- if (argv.params) {
758
- try {
759
- params = JSON.parse(argv.params);
760
- }
761
- catch (error) {
762
- console.error(chalk.red("โŒ Invalid JSON for parameters"));
763
- process.exit(1);
764
- }
765
- }
766
- console.log(chalk.blue(`๐Ÿ”ง Executing tool: ${argv.tool} on server: ${argv.server}`));
767
- const spinner = ora("Executing tool...").start();
768
- try {
769
- const result = await executeMCPTool(serverConfig, argv.tool, params);
770
- spinner.succeed(chalk.green("โœ… Tool executed successfully!"));
771
- console.log(chalk.blue("\n๐Ÿ“‹ Result:"));
772
- const resultObj = result;
773
- if (resultObj.content) {
774
- // Handle different content types
775
- if (Array.isArray(resultObj.content)) {
776
- resultObj.content.forEach((item) => {
777
- if (item.type === "text") {
778
- console.log(String(item.text));
779
- }
780
- else {
781
- console.log(JSON.stringify(item, null, 2));
782
- }
783
- });
784
- }
785
- else {
786
- console.log(JSON.stringify(resultObj.content, null, 2));
787
- }
788
- }
789
- else {
790
- console.log(JSON.stringify(result, null, 2));
791
- }
792
- }
793
- catch (error) {
794
- spinner.fail(chalk.red("โŒ Tool execution failed"));
795
- console.error(chalk.red(`Error: ${error.message}`));
796
- process.exit(1);
797
- }
798
- })
799
- // Enhanced unified list command
800
- .command("list-all", "List servers from all sources (manual + auto + default)", (y) => y
801
- .usage("Usage: $0 mcp list-all [options]")
802
- .option("source", {
803
- type: "string",
804
- choices: ["manual", "auto", "default", "all"],
805
- default: "all",
806
- description: "Filter by source type",
807
- })
808
- .option("format", {
809
- type: "string",
810
- choices: ["table", "json"],
811
- default: "table",
812
- description: "Output format",
813
- })
814
- .option("refresh", {
815
- type: "boolean",
816
- description: "Force refresh auto-discovery cache",
817
- })
818
- .example("$0 mcp list-all", "List all servers from all sources")
819
- .example("$0 mcp list-all --source auto", "List only auto-discovered servers")
820
- .example("$0 mcp list-all --refresh", "Refresh auto-discovery and list all"), async (argv) => {
821
- console.log(chalk.blue("๐ŸŒ NeuroLink Unified MCP Registry"));
822
- console.log(chalk.gray("==================================="));
823
- const spinner = ora("Initializing NeuroLink MCP...").start();
824
- try {
825
- // Initialize built-in NeuroLink servers first - register in unified registry
826
- await initializeNeuroLinkMCP(unifiedRegistry);
827
- // Initialize unified registry
828
- spinner.text = "Initializing unified registry...";
829
- await unifiedRegistry.initialize();
830
- // Force refresh if requested
831
- if (argv.refresh) {
832
- spinner.text = "Refreshing auto-discovery...";
833
- await unifiedRegistry.refresh();
834
- }
835
- spinner.succeed(chalk.green("Registry initialized!"));
836
- // Get servers based on source filter
837
- const servers = unifiedRegistry.list();
838
- const filteredServers = argv.source === "all"
839
- ? servers
840
- : servers.filter((s) => s.source === argv.source);
841
- if (filteredServers.length === 0) {
842
- console.log(chalk.yellow(`\n๐Ÿ“ญ No servers found from source: ${argv.source}`));
843
- return;
844
- }
845
- if (argv.format === "json") {
846
- console.log(JSON.stringify(filteredServers, null, 2));
847
- return;
848
- }
849
- // Table format
850
- console.log(chalk.green(`\n๐Ÿ“‹ Found ${filteredServers.length} servers:`));
851
- console.log(chalk.gray("โ”€".repeat(80)));
852
- filteredServers.forEach((server, index) => {
853
- const sourceIcon = getSourceTypeIcon(String(server.source || "unknown"));
854
- console.log(`${chalk.white(`${index + 1}.`)} ${sourceIcon} ${chalk.cyan(server.metadata.name)}`);
855
- console.log(` ${chalk.gray("Version:")} ${String(server.metadata.version || "unknown")}`);
856
- console.log(` ${chalk.gray("Source:")} ${server.source}`);
857
- console.log(` ${chalk.gray("Entry:")} ${server.entryPath}`);
858
- if (server.metadata.description) {
859
- console.log(` ${chalk.gray("Description:")} ${server.metadata.description}`);
860
- }
861
- // Add spacing between entries
862
- if (index < filteredServers.length - 1) {
863
- console.log();
864
- }
865
- });
866
- // Display statistics
867
- const stats = await unifiedRegistry.getDetailedStats();
868
- console.log(chalk.blue("๐Ÿ“Š Registry Statistics:"));
869
- console.log(` ${chalk.gray("Total plugins:")} ${stats.total}`);
870
- console.log(` ${chalk.gray("Manual servers:")} ${stats.manual?.servers || 0}`);
871
- console.log(` ${chalk.gray("Auto-discovered:")} ${stats.auto?.servers || 0}`);
872
- console.log(` ${chalk.gray("Total tools:")} ${stats.tools || 0}`);
873
- }
874
- catch (error) {
875
- spinner.fail(chalk.red("Registry initialization failed"));
876
- console.error(chalk.red(`Error: ${error instanceof Error ? error.message : String(error)}`));
877
- process.exit(1);
878
- }
879
- })
880
- // Enhanced tool execution with unified registry
881
- .command("run <tool>", "Execute a tool using unified registry (auto-fallback)", (y) => y
882
- .usage("Usage: $0 mcp run <tool> [options]")
883
- .positional("tool", {
884
- type: "string",
885
- description: "Tool name to execute",
886
- demandOption: true,
887
- })
888
- .option("params", {
889
- type: "string",
890
- description: "Tool parameters (JSON)",
891
- })
892
- .option("source", {
893
- type: "string",
894
- choices: ["manual", "auto", "default"],
895
- description: "Preferred source (with fallback)",
896
- })
897
- .option("no-fallback", {
898
- type: "boolean",
899
- description: "Disable fallback to other sources",
900
- })
901
- .example('$0 mcp run generate --params \'{"prompt": "Hello world"}\'', "Run tool with fallback")
902
- .example('$0 mcp run read_file --params \'{"path": "README.md"}\' --source manual', "Prefer manual config"), async (argv) => {
903
- console.log(chalk.blue(`๐Ÿš€ Executing tool: ${argv.tool}`));
904
- const spinner = ora("Initializing NeuroLink MCP...").start();
905
- try {
906
- // Initialize built-in NeuroLink servers first - register in unified registry
907
- await initializeNeuroLinkMCP(unifiedRegistry);
908
- // Initialize unified registry
909
- spinner.text = "Initializing unified registry...";
910
- await unifiedRegistry.initialize();
911
- let params = {};
912
- if (argv.params) {
913
- try {
914
- params = JSON.parse(argv.params);
915
- }
916
- catch (error) {
917
- spinner.fail(chalk.red("โŒ Invalid JSON for parameters"));
918
- process.exit(1);
919
- }
920
- }
921
- // Create execution context
922
- const contextManager = new ContextManager();
923
- const context = contextManager.createContext({
924
- sessionId: `cli-${Date.now()}`,
925
- userId: "cli-user",
926
- aiProvider: "unified-mcp",
927
- });
928
- const executionOptions = {
929
- preferredSource: argv.source,
930
- fallbackEnabled: !argv["no-fallback"],
931
- validateBeforeExecution: true,
932
- timeoutMs: 30000,
933
- };
934
- spinner.text = "Executing tool...";
935
- const orchestrator = new MCPOrchestrator(unifiedRegistry);
936
- const result = await orchestrator.executeTool(argv.tool, params, {
937
- sessionId: `cli-${Date.now()}`,
938
- userId: "cli-user",
939
- }, executionOptions);
940
- if (result.success) {
941
- spinner.succeed(chalk.green("โœ… Tool executed successfully!"));
942
- console.log(chalk.blue("\n๐Ÿ“‹ Result:"));
943
- if (result.data) {
944
- console.log(JSON.stringify(result.data, null, 2));
945
- }
946
- else {
947
- console.log("No data returned");
948
- }
949
- if (result.metadata) {
950
- console.log(chalk.gray("\n๐Ÿ”ง Execution Details:"));
951
- console.log(` Tool: ${result.metadata.toolName}`);
952
- console.log(` Server: ${result.metadata.serverId || "unknown"}`);
953
- console.log(` Execution time: ${result.metadata.executionTime}ms`);
954
- console.log(` Session: ${result.metadata.sessionId}`);
955
- }
956
- }
957
- else {
958
- spinner.fail(chalk.red("โŒ Tool execution failed"));
959
- console.error(chalk.red(`Error: ${result.error}`));
960
- process.exit(1);
961
- }
962
- }
963
- catch (error) {
964
- spinner.fail(chalk.red("โŒ Execution failed"));
965
- console.error(chalk.red(`Error: ${error instanceof Error ? error.message : String(error)}`));
966
- process.exit(1);
967
- }
968
- })
969
- // Configuration management commands
970
- .command("config <action>", "Manage unified registry configuration", (y) => y
971
- .usage("Usage: $0 mcp config <action> [options]")
972
- .command("show", "Show current configuration", {}, async () => {
973
- try {
974
- await unifiedRegistry.initialize();
975
- console.log(chalk.blue("๐Ÿ”ง Unified Registry Configuration"));
976
- console.log(chalk.gray("================================"));
977
- const stats = await unifiedRegistry.getDetailedStats();
978
- console.log(`Total servers: ${stats.total}`);
979
- console.log("\nBy Source:");
980
- Object.entries(stats.bySource).forEach(([source, count]) => {
981
- console.log(` ${source}: ${count}`);
982
- });
983
- console.log("\nBy Type:");
984
- Object.entries(stats.byType).forEach(([type, count]) => {
985
- console.log(` ${type}: ${count}`);
986
- });
987
- }
988
- catch (error) {
989
- console.error(chalk.red(`Error: ${error instanceof Error ? error.message : String(error)}`));
990
- process.exit(1);
991
- }
992
- })
993
- .command("enable-auto-discovery", "Enable auto-discovery", {}, async () => {
994
- try {
995
- await unifiedRegistry.initialize();
996
- unifiedRegistry.setAutoDiscovery(true);
997
- console.log(chalk.green("โœ… Auto-discovery enabled"));
998
- }
999
- catch (error) {
1000
- console.error(chalk.red(`Error: ${error instanceof Error ? error.message : String(error)}`));
1001
- process.exit(1);
1002
- }
1003
- })
1004
- .command("disable-auto-discovery", "Disable auto-discovery", {}, async () => {
1005
- try {
1006
- await unifiedRegistry.initialize();
1007
- unifiedRegistry.setAutoDiscovery(false);
1008
- console.log(chalk.green("โœ… Auto-discovery disabled"));
1009
- }
1010
- catch (error) {
1011
- console.error(chalk.red(`Error: ${error instanceof Error ? error.message : String(error)}`));
1012
- process.exit(1);
1013
- }
1014
- })
1015
- .command("set-sources <sources>", "Set preferred auto-discovery sources", (y) => y.positional("sources", {
1016
- type: "string",
1017
- description: "Comma-separated source list",
1018
- demandOption: true,
1019
- }), async (argv) => {
1020
- try {
1021
- await unifiedRegistry.initialize();
1022
- const sources = argv.sources
1023
- .split(",")
1024
- .map((s) => s.trim());
1025
- // Note: Source preference configuration not yet implemented
1026
- console.log(chalk.yellow(`โš ๏ธ Source preference configuration not yet implemented`));
1027
- console.log(chalk.blue(` Requested sources: ${sources.join(", ")}`));
1028
- }
1029
- catch (error) {
1030
- console.error(chalk.red(`Error: ${error instanceof Error ? error.message : String(error)}`));
1031
- process.exit(1);
1032
- }
1033
- })
1034
- .command("set-log-level <level>", "Set MCP logging verbosity", (y) => y.positional("level", {
1035
- type: "string",
1036
- choices: ["silent", "error", "warn", "info", "debug"],
1037
- description: "Log level to set",
1038
- demandOption: true,
1039
- }), async (argv) => {
1040
- try {
1041
- const level = argv.level;
1042
- // Note: LogLevel is a type, not an enum
1043
- // 'silent' is not a valid LogLevel, default to 'error' for minimal output
1044
- const logLevel = level === "silent"
1045
- ? "error" // Use 'error' for minimal output
1046
- : level === "error"
1047
- ? "error"
1048
- : level === "warn"
1049
- ? "warn"
1050
- : level === "info"
1051
- ? "info"
1052
- : "debug";
1053
- setGlobalMCPLogLevel(logLevel);
1054
- console.log(chalk.green(`โœ… MCP log level set to: ${level}`));
1055
- console.log(chalk.gray("This affects auto-discovery, registry operations, and tool execution logging"));
1056
- }
1057
- catch (error) {
1058
- console.error(chalk.red(`Error: ${error instanceof Error ? error.message : String(error)}`));
1059
- process.exit(1);
1060
- }
1061
- })
1062
- .example("$0 mcp config show", "Show current configuration")
1063
- .example("$0 mcp config enable-auto-discovery", "Enable auto-discovery")
1064
- .example('$0 mcp config set-sources "claude,vscode,cursor"', "Set preferred sources")
1065
- .example("$0 mcp config set-log-level debug", "Enable debug logging for troubleshooting"))
1066
- // Discover MCP servers from all AI tools
1067
- .command(["discover [options]", "d [options]"], "Discover MCP servers from all AI development tools", (y) => y
1068
- .usage("Usage: $0 mcp discover [options]")
1069
- .option("format", {
1070
- alias: "f",
1071
- type: "string",
1072
- choices: ["table", "json", "yaml", "summary"],
1073
- default: "table",
1074
- description: "Output format",
1075
- })
1076
- .option("include-inactive", {
1077
- type: "boolean",
1078
- default: true,
1079
- description: "Include servers that may not be currently active",
1080
- })
1081
- .option("preferred-tools", {
1082
- type: "string",
1083
- description: "Prioritize specific tools (comma-separated)",
1084
- })
1085
- .option("workspace-only", {
1086
- type: "boolean",
1087
- description: "Search only workspace/project configurations",
1088
- })
1089
- .option("global-only", {
1090
- type: "boolean",
1091
- description: "Search only global configurations",
1092
- })
1093
- .example("$0 mcp discover", "Discover all MCP servers")
1094
- .example("$0 mcp d --format json", "Export as JSON (using alias)")
1095
- .example('$0 mcp discover --preferred-tools "claude,cursor"', "Prioritize specific tools"), async (argv) => {
1096
- console.log(chalk.blue("๐Ÿ” NeuroLink MCP Server Discovery"));
1097
- console.log(chalk.gray("====================================="));
1098
- const options = {
1099
- includeDevPlugins: argv["include-inactive"],
1100
- // Additional search paths if needed
1101
- searchPaths: [
1102
- "./src/lib/mcp/plugins",
1103
- "./neurolink-mcp",
1104
- "./node_modules",
1105
- ],
1106
- };
1107
- const spinner = ora("Discovering MCP servers...").start();
1108
- try {
1109
- mcpLogger.debug("[MCP Discovery] Starting server discovery:", {
1110
- includeDevPlugins: options.includeDevPlugins,
1111
- searchPaths: options.searchPaths,
1112
- });
1113
- const discoveredPlugins = await discoverMCPServers(options);
1114
- mcpLogger.info("[MCP Discovery] Discovery completed:", {
1115
- pluginsFound: discoveredPlugins.length,
1116
- });
1117
- spinner.succeed(chalk.green("Discovery completed!"));
1118
- if (discoveredPlugins.length === 0) {
1119
- console.log(chalk.yellow("\n๐Ÿ“ญ No MCP servers found"));
1120
- console.log(chalk.gray("\n๐Ÿ’ก Tips for finding MCP servers:"));
1121
- console.log(chalk.gray(" โ€ข Make sure you have Claude Desktop, VS Code, or Cursor with MCP configurations"));
1122
- console.log(chalk.gray(" โ€ข Check that MCP configuration files exist in their expected locations"));
1123
- console.log(chalk.gray(" โ€ข Run with 'neurolink mcp discover' to search all locations"));
1124
- return;
1125
- }
1126
- // Display results based on format
1127
- if (argv.format === "json") {
1128
- console.log(JSON.stringify(discoveredPlugins, null, 2));
1129
- return;
1130
- }
1131
- if (argv.format === "yaml") {
1132
- // Simple YAML output
1133
- console.log("discovered:");
1134
- discoveredPlugins.forEach((plugin) => {
1135
- console.log(` - name: ${plugin.metadata.name}`);
1136
- console.log(` version: ${plugin.metadata.version}`);
1137
- console.log(` source: ${plugin.source}`);
1138
- console.log(` entryPath: ${plugin.entryPath}`);
1139
- if (plugin.metadata.description) {
1140
- console.log(` description: ${plugin.metadata.description}`);
1141
- }
1142
- });
1143
- return;
1144
- }
1145
- // Default format - show simple list
1146
- console.log(chalk.green(`\n๐Ÿ“‹ Found ${discoveredPlugins.length} MCP plugins:`));
1147
- console.log(chalk.gray("โ”€".repeat(80)));
1148
- discoveredPlugins.forEach((plugin, index) => {
1149
- console.log(`${chalk.white(`${index + 1}.`)} ${chalk.cyan(plugin.metadata.name)} v${plugin.metadata.version}`);
1150
- console.log(` ${chalk.gray("Source:")} ${plugin.source}`);
1151
- console.log(` ${chalk.gray("Entry:")} ${plugin.entryPath}`);
1152
- if (plugin.metadata.description) {
1153
- console.log(` ${chalk.gray("Description:")} ${plugin.metadata.description}`);
1154
- }
1155
- console.log();
1156
- });
1157
- }
1158
- catch (error) {
1159
- mcpLogger.error("[MCP Discovery] Discovery failed:", {
1160
- error: error instanceof Error ? error.message : String(error),
1161
- options,
1162
- });
1163
- spinner.fail(chalk.red("Discovery failed"));
1164
- console.error(chalk.red(`Error: ${error instanceof Error ? error.message : String(error)}`));
1165
- process.exit(1);
1166
- }
1167
- })
1168
- // Add debug command for tool registry diagnostics
1169
- .command("debug", "Debug MCP tool registry state and diagnose issues", (yargs) => {
1170
- return yargs.option("verbose", {
1171
- type: "boolean",
1172
- default: false,
1173
- description: "Show detailed debug information",
1174
- });
1175
- }, async (argv) => {
1176
- console.log(chalk.blue("๐Ÿ” MCP Tool Registry Debug"));
1177
- console.log(chalk.gray("=============================\n"));
1178
- try {
1179
- // Initialize built-in servers
1180
- console.log(chalk.cyan("๐Ÿ”ง Initializing Built-in Servers..."));
1181
- await initializeNeuroLinkMCP(unifiedRegistry);
1182
- // Initialize unified registry
1183
- console.log(chalk.cyan("๐ŸŒ Initializing Unified Registry..."));
1184
- await unifiedRegistry.initialize();
1185
- const registry = unifiedRegistry;
1186
- // Check built-in tools
1187
- console.log(chalk.green("\n๐Ÿ“ฆ Built-in Tools:"));
1188
- const builtInTools = await registry.listTools();
1189
- if (builtInTools.length === 0) {
1190
- console.log(chalk.red(" โŒ No built-in tools found"));
1191
- }
1192
- else {
1193
- builtInTools.forEach((tool) => {
1194
- console.log(` โœ… ${String(tool.name)} (${String(tool.serverId) || "unknown server"})`);
1195
- if (argv.verbose && tool.description) {
1196
- console.log(` โ””โ”€ ${String(tool.description)}`);
1197
- }
1198
- });
1199
- }
1200
- // Check external servers
1201
- console.log(chalk.green("\n๐ŸŒ External Servers:"));
1202
- const allTools = await registry.listAllTools();
1203
- const externalTools = allTools.filter((t) => Boolean(t.isExternal));
1204
- if (externalTools.length === 0) {
1205
- console.log(chalk.yellow(" โš ๏ธ No external servers connected"));
1206
- }
1207
- else {
1208
- const serverGroups = externalTools.reduce((acc, tool) => {
1209
- const server = String(tool.serverId) || "unknown";
1210
- if (!acc[server]) {
1211
- acc[server] = [];
1212
- }
1213
- acc[server].push(tool);
1214
- return acc;
1215
- }, {});
1216
- Object.entries(serverGroups).forEach(([server, tools]) => {
1217
- console.log(` ๐Ÿ”ง ${server} (${tools.length} tools)`);
1218
- if (argv.verbose) {
1219
- tools.forEach((tool) => {
1220
- console.log(` โ””โ”€ ${String(tool.name)}`);
1221
- });
1222
- }
1223
- });
1224
- }
1225
- // Test specific tool execution
1226
- console.log(chalk.green("\n๐Ÿงช Testing 'get-current-time' Tool:"));
1227
- try {
1228
- const result = await registry.executeTool("get-current-time");
1229
- console.log(chalk.green(" โœ… Success:"));
1230
- if (argv.verbose) {
1231
- console.log(JSON.stringify(result, null, 4));
1232
- }
1233
- else {
1234
- console.log(` โ””โ”€ Tool executed successfully`);
1235
- }
1236
- }
1237
- catch (error) {
1238
- const errorMessage = error instanceof Error ? error.message : String(error);
1239
- console.log(chalk.red(" โŒ Failed:"));
1240
- console.log(` โ””โ”€ ${errorMessage}`);
1241
- if (argv.verbose) {
1242
- console.log(chalk.gray("\n๐Ÿ“‹ Debug Details:"));
1243
- console.log(` Error Type: ${error instanceof Error ? error.constructor.name : typeof error}`);
1244
- console.log(` Stack: ${error instanceof Error && error.stack ? error.stack : "No stack trace available"}`);
1245
- }
1246
- }
1247
- // Summary
1248
- console.log(chalk.green(`\n๐Ÿ“Š Summary:`));
1249
- console.log(` Built-in tools: ${builtInTools.length}`);
1250
- console.log(` External tools: ${externalTools.length}`);
1251
- console.log(` Total tools: ${allTools.length}`);
1252
- }
1253
- catch (error) {
1254
- const errorMessage = error instanceof Error ? error.message : String(error);
1255
- console.error(chalk.red("โŒ Debug failed:"));
1256
- console.error(` ${errorMessage}`);
1257
- if (argv.verbose) {
1258
- console.error(error instanceof Error && error.stack
1259
- ? error.stack
1260
- : "No stack trace available");
1261
- }
1262
- process.exit(1);
1263
- }
1264
- })
1265
- .demandCommand(1, "Please specify an MCP subcommand")
1266
- .example("$0 mcp list", "List configured MCP servers")
1267
- .example("$0 mcp discover", "Discover MCP servers from all tools")
1268
- .example("$0 mcp debug", "Debug tool registry state")
1269
- .example("$0 mcp install filesystem", "Install filesystem MCP server")
1270
- .example("$0 mcp test filesystem", "Test filesystem server connection");
1271
- });
1272
- }