@juspay/neurolink 4.1.1 โ 4.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.
- package/CHANGELOG.md +8 -2
- package/README.md +1 -12
- package/dist/cli/commands/mcp.d.ts +11 -0
- package/dist/cli/commands/mcp.js +332 -223
- package/dist/cli/index.js +69 -8
- package/dist/core/factory.js +2 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/lib/core/factory.js +2 -2
- package/dist/lib/index.d.ts +1 -1
- package/dist/lib/index.js +1 -1
- package/dist/lib/mcp/context-manager.d.ts +6 -0
- package/dist/lib/mcp/context-manager.js +8 -0
- package/dist/lib/mcp/contracts/mcpContract.d.ts +1 -0
- package/dist/lib/mcp/external-client.js +6 -2
- package/dist/lib/mcp/initialize.d.ts +2 -1
- package/dist/lib/mcp/initialize.js +8 -7
- package/dist/lib/mcp/orchestrator.js +9 -0
- package/dist/lib/mcp/registry.d.ts +1 -1
- package/dist/lib/mcp/servers/ai-providers/ai-analysis-tools.js +1 -1
- package/dist/lib/mcp/servers/ai-providers/ai-core-server.js +3 -3
- package/dist/lib/mcp/servers/ai-providers/ai-workflow-tools.d.ts +2 -2
- package/dist/lib/mcp/servers/ai-providers/ai-workflow-tools.js +1 -1
- package/dist/lib/mcp/session-manager.js +1 -1
- package/dist/lib/mcp/session-persistence.js +1 -1
- package/dist/lib/mcp/tool-registry.d.ts +31 -11
- package/dist/lib/mcp/tool-registry.js +226 -38
- package/dist/lib/mcp/unified-mcp.d.ts +12 -2
- package/dist/lib/mcp/unified-registry.d.ts +21 -7
- package/dist/lib/mcp/unified-registry.js +179 -17
- package/dist/lib/neurolink.js +17 -25
- package/dist/lib/providers/googleVertexAI.js +19 -1
- package/dist/lib/providers/openAI.js +18 -1
- package/dist/lib/utils/provider-setup-messages.d.ts +8 -0
- package/dist/lib/utils/provider-setup-messages.js +120 -0
- package/dist/lib/utils/provider-validation.d.ts +35 -0
- package/dist/lib/utils/provider-validation.js +625 -0
- package/dist/lib/utils/providerUtils-fixed.js +20 -1
- package/dist/lib/utils/providerUtils.d.ts +2 -2
- package/dist/lib/utils/providerUtils.js +38 -7
- package/dist/lib/utils/timeout-manager.d.ts +75 -0
- package/dist/lib/utils/timeout-manager.js +244 -0
- package/dist/mcp/context-manager.d.ts +6 -0
- package/dist/mcp/context-manager.js +8 -0
- package/dist/mcp/contracts/mcpContract.d.ts +1 -0
- package/dist/mcp/external-client.js +6 -2
- package/dist/mcp/initialize.d.ts +2 -1
- package/dist/mcp/initialize.js +8 -7
- package/dist/mcp/orchestrator.js +9 -0
- package/dist/mcp/registry.d.ts +1 -1
- package/dist/mcp/servers/ai-providers/ai-analysis-tools.js +1 -1
- package/dist/mcp/servers/ai-providers/ai-core-server.js +3 -3
- package/dist/mcp/servers/ai-providers/ai-workflow-tools.d.ts +2 -2
- package/dist/mcp/servers/ai-providers/ai-workflow-tools.js +1 -1
- package/dist/mcp/session-manager.js +1 -1
- package/dist/mcp/session-persistence.js +1 -1
- package/dist/mcp/tool-registry.d.ts +31 -11
- package/dist/mcp/tool-registry.js +226 -38
- package/dist/mcp/unified-mcp.d.ts +12 -2
- package/dist/mcp/unified-registry.d.ts +21 -7
- package/dist/mcp/unified-registry.js +179 -17
- package/dist/neurolink.js +17 -25
- package/dist/providers/googleVertexAI.js +19 -1
- package/dist/providers/openAI.js +18 -1
- package/dist/utils/provider-setup-messages.d.ts +8 -0
- package/dist/utils/provider-setup-messages.js +120 -0
- package/dist/utils/provider-validation.d.ts +35 -0
- package/dist/utils/provider-validation.js +625 -0
- package/dist/utils/providerUtils-fixed.js +20 -1
- package/dist/utils/providerUtils.d.ts +2 -2
- package/dist/utils/providerUtils.js +38 -7
- package/dist/utils/timeout-manager.d.ts +75 -0
- package/dist/utils/timeout-manager.js +244 -0
- package/package.json +1 -1
package/dist/cli/commands/mcp.js
CHANGED
|
@@ -14,6 +14,7 @@ import { ContextManager } from "../../lib/mcp/context-manager.js";
|
|
|
14
14
|
import { MCPOrchestrator } from "../../lib/mcp/orchestrator.js";
|
|
15
15
|
import { initializeNeuroLinkMCP } from "../../lib/mcp/initialize.js";
|
|
16
16
|
import { mcpLogger, setGlobalMCPLogLevel } from "../../lib/mcp/logging.js";
|
|
17
|
+
import { defaultTimeoutManager } from "../../lib/utils/timeout-manager.js";
|
|
17
18
|
// Default MCP config file location
|
|
18
19
|
const MCP_CONFIG_FILE = path.join(process.cwd(), ".mcp-config.json");
|
|
19
20
|
// Load MCP configuration
|
|
@@ -37,37 +38,44 @@ function saveMCPConfig(config) {
|
|
|
37
38
|
async function checkMCPServerStatus(serverConfig) {
|
|
38
39
|
try {
|
|
39
40
|
if (serverConfig.transport === "stdio") {
|
|
40
|
-
// For stdio servers,
|
|
41
|
-
const
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
return new Promise((resolve) => {
|
|
47
|
-
const timeout = setTimeout(() => {
|
|
48
|
-
child.kill();
|
|
49
|
-
resolve(false);
|
|
50
|
-
}, 3000);
|
|
51
|
-
child.on("spawn", () => {
|
|
52
|
-
clearTimeout(timeout);
|
|
53
|
-
child.kill();
|
|
54
|
-
resolve(true);
|
|
41
|
+
// For stdio servers, use timeout manager for proper cleanup
|
|
42
|
+
const result = await defaultTimeoutManager.wrapMCPOperation(async () => {
|
|
43
|
+
const child = spawn(serverConfig.command, serverConfig.args || [], {
|
|
44
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
45
|
+
env: { ...process.env, ...serverConfig.env },
|
|
46
|
+
cwd: serverConfig.cwd,
|
|
55
47
|
});
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
48
|
+
return new Promise((resolve, reject) => {
|
|
49
|
+
child.on("spawn", () => {
|
|
50
|
+
child.kill();
|
|
51
|
+
resolve(true);
|
|
52
|
+
});
|
|
53
|
+
child.on("error", (error) => {
|
|
54
|
+
reject(error);
|
|
55
|
+
});
|
|
56
|
+
child.on("exit", (code) => {
|
|
57
|
+
if (code === null) {
|
|
58
|
+
// Process was terminated (expected for quick check)
|
|
59
|
+
resolve(true);
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
resolve(false);
|
|
63
|
+
}
|
|
64
|
+
});
|
|
59
65
|
});
|
|
60
|
-
});
|
|
66
|
+
}, "server-status-check", 10000);
|
|
67
|
+
return result.success && result.data === true;
|
|
61
68
|
}
|
|
62
69
|
else if (serverConfig.transport === "sse" && serverConfig.url) {
|
|
63
|
-
// For SSE servers, check if URL is accessible
|
|
64
|
-
|
|
70
|
+
// For SSE servers, check if URL is accessible with timeout
|
|
71
|
+
const result = await defaultTimeoutManager.wrapMCPOperation(async () => {
|
|
72
|
+
if (!serverConfig.url) {
|
|
73
|
+
throw new Error("SSE URL not configured");
|
|
74
|
+
}
|
|
65
75
|
const response = await fetch(serverConfig.url, { method: "HEAD" });
|
|
66
76
|
return response.ok;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
return false;
|
|
70
|
-
}
|
|
77
|
+
}, "sse-status-check", 10000);
|
|
78
|
+
return result.success && result.data === true;
|
|
71
79
|
}
|
|
72
80
|
return false;
|
|
73
81
|
}
|
|
@@ -78,226 +86,233 @@ async function checkMCPServerStatus(serverConfig) {
|
|
|
78
86
|
// Connect to MCP server and get capabilities
|
|
79
87
|
async function getMCPServerCapabilities(serverConfig) {
|
|
80
88
|
if (serverConfig.transport === "stdio") {
|
|
81
|
-
//
|
|
82
|
-
const
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
child.kill();
|
|
104
|
-
resolve(response.result);
|
|
105
|
-
return;
|
|
89
|
+
// Use timeout manager for proper cleanup and longer timeout
|
|
90
|
+
const result = await defaultTimeoutManager.wrapMCPOperation(async () => {
|
|
91
|
+
const child = spawn(serverConfig.command, serverConfig.args || [], {
|
|
92
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
93
|
+
env: { ...process.env, ...serverConfig.env },
|
|
94
|
+
cwd: serverConfig.cwd,
|
|
95
|
+
});
|
|
96
|
+
return new Promise((resolve, reject) => {
|
|
97
|
+
let responseData = "";
|
|
98
|
+
child.stdout?.on("data", (data) => {
|
|
99
|
+
responseData += data.toString();
|
|
100
|
+
// Look for JSON-RPC response
|
|
101
|
+
try {
|
|
102
|
+
const lines = responseData.split("\n");
|
|
103
|
+
for (const line of lines) {
|
|
104
|
+
if (line.trim() && line.includes('"result"')) {
|
|
105
|
+
const response = JSON.parse(line.trim());
|
|
106
|
+
if (response.result && response.result.capabilities) {
|
|
107
|
+
child.kill();
|
|
108
|
+
resolve(response.result);
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
106
111
|
}
|
|
107
112
|
}
|
|
108
113
|
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
114
|
+
catch {
|
|
115
|
+
// Continue parsing
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
child.on("spawn", () => {
|
|
119
|
+
// Send initialize request
|
|
120
|
+
const initRequest = {
|
|
121
|
+
jsonrpc: "2.0",
|
|
122
|
+
id: 1,
|
|
123
|
+
method: "initialize",
|
|
124
|
+
params: {
|
|
125
|
+
protocolVersion: "2024-11-05",
|
|
126
|
+
capabilities: {},
|
|
127
|
+
clientInfo: {
|
|
128
|
+
name: "neurolink-cli",
|
|
129
|
+
version: "1.0.0",
|
|
130
|
+
},
|
|
126
131
|
},
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
reject(error);
|
|
132
|
+
};
|
|
133
|
+
child.stdin?.write(JSON.stringify(initRequest) + "\n");
|
|
134
|
+
});
|
|
135
|
+
child.on("error", (error) => {
|
|
136
|
+
reject(error);
|
|
137
|
+
});
|
|
134
138
|
});
|
|
135
|
-
});
|
|
139
|
+
}, "server-capabilities-check", 15000);
|
|
140
|
+
if (result.success) {
|
|
141
|
+
return result.data;
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
throw result.error || new Error("Failed to get MCP server capabilities");
|
|
145
|
+
}
|
|
136
146
|
}
|
|
137
147
|
throw new Error("SSE transport not yet implemented for capabilities");
|
|
138
148
|
}
|
|
139
149
|
// List available tools from MCP server
|
|
140
150
|
async function listMCPServerTools(serverConfig) {
|
|
141
151
|
if (serverConfig.transport === "stdio") {
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
resolve(response.result.tools);
|
|
176
|
-
return;
|
|
152
|
+
// Use timeout manager for proper cleanup and longer timeout
|
|
153
|
+
const result = await defaultTimeoutManager.wrapMCPOperation(async () => {
|
|
154
|
+
const child = spawn(serverConfig.command, serverConfig.args || [], {
|
|
155
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
156
|
+
env: { ...process.env, ...serverConfig.env },
|
|
157
|
+
cwd: serverConfig.cwd,
|
|
158
|
+
});
|
|
159
|
+
return new Promise((resolve, reject) => {
|
|
160
|
+
let responseData = "";
|
|
161
|
+
let initialized = false;
|
|
162
|
+
child.stdout?.on("data", (data) => {
|
|
163
|
+
responseData += data.toString();
|
|
164
|
+
try {
|
|
165
|
+
const lines = responseData.split("\n");
|
|
166
|
+
for (const line of lines) {
|
|
167
|
+
if (line.trim() && line.includes('"result"')) {
|
|
168
|
+
const response = JSON.parse(line.trim());
|
|
169
|
+
if (response.id === 1 && response.result.capabilities) {
|
|
170
|
+
// Initialize successful, now list tools
|
|
171
|
+
initialized = true;
|
|
172
|
+
const listToolsRequest = {
|
|
173
|
+
jsonrpc: "2.0",
|
|
174
|
+
id: 2,
|
|
175
|
+
method: "tools/list",
|
|
176
|
+
params: {},
|
|
177
|
+
};
|
|
178
|
+
child.stdin?.write(JSON.stringify(listToolsRequest) + "\n");
|
|
179
|
+
}
|
|
180
|
+
else if (response.id === 2 && response.result.tools) {
|
|
181
|
+
child.kill();
|
|
182
|
+
resolve(response.result.tools);
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
177
185
|
}
|
|
178
186
|
}
|
|
179
187
|
}
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
188
|
+
catch {
|
|
189
|
+
// Continue parsing
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
child.on("spawn", () => {
|
|
193
|
+
// Send initialize request first
|
|
194
|
+
const initRequest = {
|
|
195
|
+
jsonrpc: "2.0",
|
|
196
|
+
id: 1,
|
|
197
|
+
method: "initialize",
|
|
198
|
+
params: {
|
|
199
|
+
protocolVersion: "2024-11-05",
|
|
200
|
+
capabilities: {},
|
|
201
|
+
clientInfo: {
|
|
202
|
+
name: "neurolink-cli",
|
|
203
|
+
version: "1.0.0",
|
|
204
|
+
},
|
|
197
205
|
},
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
reject(error);
|
|
206
|
+
};
|
|
207
|
+
child.stdin?.write(JSON.stringify(initRequest) + "\n");
|
|
208
|
+
});
|
|
209
|
+
child.on("error", (error) => {
|
|
210
|
+
reject(error);
|
|
211
|
+
});
|
|
205
212
|
});
|
|
206
|
-
});
|
|
213
|
+
}, "server-tools-list", 15000);
|
|
214
|
+
if (result.success) {
|
|
215
|
+
return result.data || [];
|
|
216
|
+
}
|
|
217
|
+
else {
|
|
218
|
+
throw result.error || new Error("Failed to list MCP server tools");
|
|
219
|
+
}
|
|
207
220
|
}
|
|
208
221
|
throw new Error("SSE transport not yet implemented for tool listing");
|
|
209
222
|
}
|
|
210
223
|
// Execute tool on MCP server
|
|
211
|
-
async function executeMCPTool(serverConfig, toolName, toolParams) {
|
|
224
|
+
export async function executeMCPTool(serverConfig, toolName, toolParams) {
|
|
212
225
|
if (serverConfig.transport === "stdio") {
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
};
|
|
244
|
-
child.stdin?.write(JSON.stringify(toolCallRequest) + "\n");
|
|
245
|
-
}
|
|
246
|
-
else if (response.id === 2) {
|
|
247
|
-
clearTimeout(timeout);
|
|
248
|
-
child.kill();
|
|
249
|
-
if (response.result) {
|
|
250
|
-
resolve(response.result);
|
|
251
|
-
}
|
|
252
|
-
else if (response.error) {
|
|
253
|
-
reject(new Error(`MCP Error: ${response.error.message || "Unknown error"}`));
|
|
226
|
+
// Use timeout manager for proper cleanup and configurable timeout
|
|
227
|
+
const result = await defaultTimeoutManager.wrapMCPOperation(async () => {
|
|
228
|
+
const child = spawn(serverConfig.command, serverConfig.args || [], {
|
|
229
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
230
|
+
env: { ...process.env, ...serverConfig.env },
|
|
231
|
+
cwd: serverConfig.cwd,
|
|
232
|
+
});
|
|
233
|
+
return new Promise((resolve, reject) => {
|
|
234
|
+
let responseData = "";
|
|
235
|
+
let initialized = false;
|
|
236
|
+
child.stdout?.on("data", (data) => {
|
|
237
|
+
responseData += data.toString();
|
|
238
|
+
try {
|
|
239
|
+
const lines = responseData.split("\n");
|
|
240
|
+
for (const line of lines) {
|
|
241
|
+
if (line.trim() && line.includes('"result"')) {
|
|
242
|
+
const response = JSON.parse(line.trim());
|
|
243
|
+
if (response.id === 1 && response.result.capabilities) {
|
|
244
|
+
// Initialize successful, now execute tool
|
|
245
|
+
initialized = true;
|
|
246
|
+
const toolCallRequest = {
|
|
247
|
+
jsonrpc: "2.0",
|
|
248
|
+
id: 2,
|
|
249
|
+
method: "tools/call",
|
|
250
|
+
params: {
|
|
251
|
+
name: toolName,
|
|
252
|
+
arguments: toolParams,
|
|
253
|
+
},
|
|
254
|
+
};
|
|
255
|
+
child.stdin?.write(JSON.stringify(toolCallRequest) + "\n");
|
|
254
256
|
}
|
|
255
|
-
else {
|
|
256
|
-
|
|
257
|
+
else if (response.id === 2) {
|
|
258
|
+
child.kill();
|
|
259
|
+
if (response.result) {
|
|
260
|
+
resolve(response.result);
|
|
261
|
+
}
|
|
262
|
+
else if (response.error) {
|
|
263
|
+
reject(new Error(`MCP Error: ${response.error.message || "Unknown error"}`));
|
|
264
|
+
}
|
|
265
|
+
else {
|
|
266
|
+
reject(new Error("Unknown MCP response format"));
|
|
267
|
+
}
|
|
268
|
+
return;
|
|
257
269
|
}
|
|
258
|
-
return;
|
|
259
270
|
}
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
return;
|
|
271
|
+
else if (line.trim() && line.includes('"error"')) {
|
|
272
|
+
const response = JSON.parse(line.trim());
|
|
273
|
+
if (response.error) {
|
|
274
|
+
child.kill();
|
|
275
|
+
reject(new Error(`MCP Error: ${response.error.message || "Unknown error"}`));
|
|
276
|
+
return;
|
|
277
|
+
}
|
|
268
278
|
}
|
|
269
279
|
}
|
|
270
280
|
}
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
281
|
+
catch {
|
|
282
|
+
// Continue parsing
|
|
283
|
+
}
|
|
284
|
+
});
|
|
285
|
+
child.stderr?.on("data", (data) => {
|
|
286
|
+
console.error(chalk.red(`MCP Server Error: ${data.toString()}`));
|
|
287
|
+
});
|
|
288
|
+
child.on("spawn", () => {
|
|
289
|
+
// Send initialize request first
|
|
290
|
+
const initRequest = {
|
|
291
|
+
jsonrpc: "2.0",
|
|
292
|
+
id: 1,
|
|
293
|
+
method: "initialize",
|
|
294
|
+
params: {
|
|
295
|
+
protocolVersion: "2024-11-05",
|
|
296
|
+
capabilities: {},
|
|
297
|
+
clientInfo: {
|
|
298
|
+
name: "neurolink-cli",
|
|
299
|
+
version: "1.0.0",
|
|
300
|
+
},
|
|
291
301
|
},
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
reject(error);
|
|
302
|
+
};
|
|
303
|
+
child.stdin?.write(JSON.stringify(initRequest) + "\n");
|
|
304
|
+
});
|
|
305
|
+
child.on("error", (error) => {
|
|
306
|
+
reject(error);
|
|
307
|
+
});
|
|
299
308
|
});
|
|
300
|
-
});
|
|
309
|
+
}, "tool-execution", 30000);
|
|
310
|
+
if (result.success) {
|
|
311
|
+
return result.data;
|
|
312
|
+
}
|
|
313
|
+
else {
|
|
314
|
+
throw result.error || new Error("Failed to execute MCP tool");
|
|
315
|
+
}
|
|
301
316
|
}
|
|
302
317
|
throw new Error("SSE transport not yet implemented for tool execution");
|
|
303
318
|
}
|
|
@@ -428,7 +443,7 @@ export async function mcpExecuteTool(serverName, toolName, toolParams) {
|
|
|
428
443
|
// First try unified registry (includes built-in NeuroLink servers)
|
|
429
444
|
try {
|
|
430
445
|
await unifiedRegistry.initialize();
|
|
431
|
-
const orchestrator = new MCPOrchestrator();
|
|
446
|
+
const orchestrator = new MCPOrchestrator(unifiedRegistry);
|
|
432
447
|
const result = await orchestrator.executeTool(toolName, toolParams, {
|
|
433
448
|
sessionId: `cli-${Date.now()}`,
|
|
434
449
|
userId: "cli-user",
|
|
@@ -800,8 +815,8 @@ export function addMCPCommands(yargs) {
|
|
|
800
815
|
console.log(chalk.gray("==================================="));
|
|
801
816
|
const spinner = ora("Initializing NeuroLink MCP...").start();
|
|
802
817
|
try {
|
|
803
|
-
// Initialize built-in NeuroLink servers first
|
|
804
|
-
await initializeNeuroLinkMCP();
|
|
818
|
+
// Initialize built-in NeuroLink servers first - register in unified registry
|
|
819
|
+
await initializeNeuroLinkMCP(unifiedRegistry);
|
|
805
820
|
// Initialize unified registry
|
|
806
821
|
spinner.text = "Initializing unified registry...";
|
|
807
822
|
await unifiedRegistry.initialize();
|
|
@@ -881,8 +896,8 @@ export function addMCPCommands(yargs) {
|
|
|
881
896
|
console.log(chalk.blue(`๐ Executing tool: ${argv.tool}`));
|
|
882
897
|
const spinner = ora("Initializing NeuroLink MCP...").start();
|
|
883
898
|
try {
|
|
884
|
-
// Initialize built-in NeuroLink servers first
|
|
885
|
-
await initializeNeuroLinkMCP();
|
|
899
|
+
// Initialize built-in NeuroLink servers first - register in unified registry
|
|
900
|
+
await initializeNeuroLinkMCP(unifiedRegistry);
|
|
886
901
|
// Initialize unified registry
|
|
887
902
|
spinner.text = "Initializing unified registry...";
|
|
888
903
|
await unifiedRegistry.initialize();
|
|
@@ -910,7 +925,7 @@ export function addMCPCommands(yargs) {
|
|
|
910
925
|
timeoutMs: 30000,
|
|
911
926
|
};
|
|
912
927
|
spinner.text = "Executing tool...";
|
|
913
|
-
const orchestrator = new MCPOrchestrator();
|
|
928
|
+
const orchestrator = new MCPOrchestrator(unifiedRegistry);
|
|
914
929
|
const result = await orchestrator.executeTool(argv.tool, params, {
|
|
915
930
|
sessionId: `cli-${Date.now()}`,
|
|
916
931
|
userId: "cli-user",
|
|
@@ -952,7 +967,7 @@ export function addMCPCommands(yargs) {
|
|
|
952
967
|
await unifiedRegistry.initialize();
|
|
953
968
|
console.log(chalk.blue("๐ง Unified Registry Configuration"));
|
|
954
969
|
console.log(chalk.gray("================================"));
|
|
955
|
-
const stats = await unifiedRegistry.
|
|
970
|
+
const stats = await unifiedRegistry.getDetailedStats();
|
|
956
971
|
console.log(`Total servers: ${stats.total}`);
|
|
957
972
|
console.log("\nBy Source:");
|
|
958
973
|
Object.entries(stats.bySource).forEach(([source, count]) => {
|
|
@@ -1142,10 +1157,104 @@ export function addMCPCommands(yargs) {
|
|
|
1142
1157
|
console.error(chalk.red(`Error: ${error instanceof Error ? error.message : String(error)}`));
|
|
1143
1158
|
process.exit(1);
|
|
1144
1159
|
}
|
|
1160
|
+
})
|
|
1161
|
+
// Add debug command for tool registry diagnostics
|
|
1162
|
+
.command("debug", "Debug MCP tool registry state and diagnose issues", (yargs) => {
|
|
1163
|
+
return yargs.option("verbose", {
|
|
1164
|
+
type: "boolean",
|
|
1165
|
+
default: false,
|
|
1166
|
+
description: "Show detailed debug information",
|
|
1167
|
+
});
|
|
1168
|
+
}, async (argv) => {
|
|
1169
|
+
console.log(chalk.blue("๐ MCP Tool Registry Debug"));
|
|
1170
|
+
console.log(chalk.gray("=============================\n"));
|
|
1171
|
+
try {
|
|
1172
|
+
// Initialize built-in servers
|
|
1173
|
+
console.log(chalk.cyan("๐ง Initializing Built-in Servers..."));
|
|
1174
|
+
await initializeNeuroLinkMCP(unifiedRegistry);
|
|
1175
|
+
// Initialize unified registry
|
|
1176
|
+
console.log(chalk.cyan("๐ Initializing Unified Registry..."));
|
|
1177
|
+
await unifiedRegistry.initialize();
|
|
1178
|
+
const registry = unifiedRegistry;
|
|
1179
|
+
// Check built-in tools
|
|
1180
|
+
console.log(chalk.green("\n๐ฆ Built-in Tools:"));
|
|
1181
|
+
const builtInTools = await registry.listTools();
|
|
1182
|
+
if (builtInTools.length === 0) {
|
|
1183
|
+
console.log(chalk.red(" โ No built-in tools found"));
|
|
1184
|
+
}
|
|
1185
|
+
else {
|
|
1186
|
+
builtInTools.forEach((tool) => {
|
|
1187
|
+
console.log(` โ
${tool.name} (${tool.serverId || "unknown server"})`);
|
|
1188
|
+
if (argv.verbose && tool.description) {
|
|
1189
|
+
console.log(` โโ ${tool.description}`);
|
|
1190
|
+
}
|
|
1191
|
+
});
|
|
1192
|
+
}
|
|
1193
|
+
// Check external servers
|
|
1194
|
+
console.log(chalk.green("\n๐ External Servers:"));
|
|
1195
|
+
const allTools = await registry.listAllTools();
|
|
1196
|
+
const externalTools = allTools.filter((t) => t.isExternal);
|
|
1197
|
+
if (externalTools.length === 0) {
|
|
1198
|
+
console.log(chalk.yellow(" โ ๏ธ No external servers connected"));
|
|
1199
|
+
}
|
|
1200
|
+
else {
|
|
1201
|
+
const serverGroups = externalTools.reduce((acc, tool) => {
|
|
1202
|
+
const server = tool.serverId || "unknown";
|
|
1203
|
+
if (!acc[server]) {
|
|
1204
|
+
acc[server] = [];
|
|
1205
|
+
}
|
|
1206
|
+
acc[server].push(tool);
|
|
1207
|
+
return acc;
|
|
1208
|
+
}, {});
|
|
1209
|
+
Object.entries(serverGroups).forEach(([server, tools]) => {
|
|
1210
|
+
console.log(` ๐ง ${server} (${tools.length} tools)`);
|
|
1211
|
+
if (argv.verbose) {
|
|
1212
|
+
tools.forEach((tool) => {
|
|
1213
|
+
console.log(` โโ ${tool.name}`);
|
|
1214
|
+
});
|
|
1215
|
+
}
|
|
1216
|
+
});
|
|
1217
|
+
}
|
|
1218
|
+
// Test specific tool execution
|
|
1219
|
+
console.log(chalk.green("\n๐งช Testing 'get-current-time' Tool:"));
|
|
1220
|
+
try {
|
|
1221
|
+
const result = await registry.executeTool("get-current-time");
|
|
1222
|
+
console.log(chalk.green(" โ
Success:"));
|
|
1223
|
+
if (argv.verbose) {
|
|
1224
|
+
console.log(JSON.stringify(result, null, 4));
|
|
1225
|
+
}
|
|
1226
|
+
else {
|
|
1227
|
+
console.log(` โโ Tool executed successfully`);
|
|
1228
|
+
}
|
|
1229
|
+
}
|
|
1230
|
+
catch (error) {
|
|
1231
|
+
console.log(chalk.red(" โ Failed:"));
|
|
1232
|
+
console.log(` โโ ${error.message}`);
|
|
1233
|
+
if (argv.verbose) {
|
|
1234
|
+
console.log(chalk.gray("\n๐ Debug Details:"));
|
|
1235
|
+
console.log(` Error Type: ${error.constructor.name}`);
|
|
1236
|
+
console.log(` Stack: ${error.stack}`);
|
|
1237
|
+
}
|
|
1238
|
+
}
|
|
1239
|
+
// Summary
|
|
1240
|
+
console.log(chalk.green(`\n๐ Summary:`));
|
|
1241
|
+
console.log(` Built-in tools: ${builtInTools.length}`);
|
|
1242
|
+
console.log(` External tools: ${externalTools.length}`);
|
|
1243
|
+
console.log(` Total tools: ${allTools.length}`);
|
|
1244
|
+
}
|
|
1245
|
+
catch (error) {
|
|
1246
|
+
console.error(chalk.red("โ Debug failed:"));
|
|
1247
|
+
console.error(` ${error.message}`);
|
|
1248
|
+
if (argv.verbose) {
|
|
1249
|
+
console.error(error.stack);
|
|
1250
|
+
}
|
|
1251
|
+
process.exit(1);
|
|
1252
|
+
}
|
|
1145
1253
|
})
|
|
1146
1254
|
.demandCommand(1, "Please specify an MCP subcommand")
|
|
1147
1255
|
.example("$0 mcp list", "List configured MCP servers")
|
|
1148
1256
|
.example("$0 mcp discover", "Discover MCP servers from all tools")
|
|
1257
|
+
.example("$0 mcp debug", "Debug tool registry state")
|
|
1149
1258
|
.example("$0 mcp install filesystem", "Install filesystem MCP server")
|
|
1150
1259
|
.example("$0 mcp test filesystem", "Test filesystem server connection");
|
|
1151
1260
|
});
|