@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.
- package/CHANGELOG.md +10 -6
- package/dist/cli/commands/config.d.ts +13 -13
- package/dist/cli/index.js +3 -9
- package/dist/core/analytics.d.ts +11 -1
- package/dist/core/analytics.js +2 -2
- package/dist/core/base-provider.js +4 -18
- package/dist/core/dynamic-models.d.ts +8 -8
- package/dist/core/factory.js +3 -11
- package/dist/index.d.ts +2 -4
- package/dist/index.js +2 -11
- package/dist/lib/core/analytics.d.ts +11 -1
- package/dist/lib/core/analytics.js +2 -2
- package/dist/lib/core/base-provider.js +4 -18
- package/dist/lib/core/dynamic-models.d.ts +8 -8
- package/dist/lib/core/factory.js +3 -11
- package/dist/lib/index.d.ts +2 -4
- package/dist/lib/index.js +2 -11
- package/dist/lib/mcp/factory.d.ts +1 -1
- package/dist/lib/mcp/index.d.ts +7 -19
- package/dist/lib/mcp/index.js +15 -56
- package/dist/lib/neurolink.d.ts +1 -9
- package/dist/lib/neurolink.js +21 -70
- package/dist/lib/providers/amazon-bedrock.js +5 -16
- package/dist/lib/providers/anthropic-baseprovider.js +3 -21
- package/dist/lib/providers/anthropic.js +4 -7
- package/dist/lib/providers/azure-openai.js +4 -2
- package/dist/lib/providers/google-vertex.js +5 -9
- package/dist/lib/providers/huggingFace.js +5 -10
- package/dist/lib/providers/mistral.js +5 -8
- package/dist/lib/providers/openAI.js +4 -7
- package/dist/lib/utils/providerConfig.d.ts +117 -0
- package/dist/lib/utils/providerConfig.js +353 -0
- package/dist/lib/utils/providerUtils.d.ts +2 -1
- package/dist/lib/utils/providerUtils.js +53 -36
- package/dist/lib/utils/timeout.d.ts +72 -1
- package/dist/lib/utils/timeout.js +203 -2
- package/dist/mcp/factory.d.ts +1 -1
- package/dist/mcp/index.d.ts +7 -19
- package/dist/mcp/index.js +15 -56
- package/dist/neurolink.d.ts +1 -9
- package/dist/neurolink.js +21 -70
- package/dist/providers/amazon-bedrock.js +5 -16
- package/dist/providers/anthropic-baseprovider.js +3 -21
- package/dist/providers/anthropic.js +4 -7
- package/dist/providers/azure-openai.js +4 -2
- package/dist/providers/google-vertex.js +5 -9
- package/dist/providers/huggingFace.js +5 -10
- package/dist/providers/mistral.js +5 -8
- package/dist/providers/openAI.js +4 -7
- package/dist/utils/providerConfig.d.ts +117 -0
- package/dist/utils/providerConfig.js +353 -0
- package/dist/utils/providerUtils.d.ts +2 -1
- package/dist/utils/providerUtils.js +53 -36
- package/dist/utils/timeout.d.ts +72 -1
- package/dist/utils/timeout.js +203 -2
- package/package.json +1 -1
- package/dist/chat/client-utils.d.ts +0 -95
- package/dist/chat/client-utils.js +0 -315
- package/dist/chat/index.d.ts +0 -24
- package/dist/chat/index.js +0 -33
- package/dist/chat/session-storage.d.ts +0 -77
- package/dist/chat/session-storage.js +0 -233
- package/dist/chat/session.d.ts +0 -96
- package/dist/chat/session.js +0 -257
- package/dist/chat/sse-handler.d.ts +0 -49
- package/dist/chat/sse-handler.js +0 -259
- package/dist/chat/types.d.ts +0 -74
- package/dist/chat/types.js +0 -5
- package/dist/chat/websocket-chat-handler.d.ts +0 -37
- package/dist/chat/websocket-chat-handler.js +0 -262
- package/dist/cli/commands/mcp.d.ts +0 -20
- package/dist/cli/commands/mcp.js +0 -1272
- package/dist/core/defaults.d.ts +0 -19
- package/dist/core/defaults.js +0 -29
- package/dist/core/evaluation-config.d.ts +0 -29
- package/dist/core/evaluation-config.js +0 -144
- package/dist/factories/compatibility-factory.d.ts +0 -35
- package/dist/factories/compatibility-factory.js +0 -71
- package/dist/factories/provider-generate-factory.d.ts +0 -20
- package/dist/factories/provider-generate-factory.js +0 -93
- package/dist/lib/chat/client-utils.d.ts +0 -95
- package/dist/lib/chat/client-utils.js +0 -315
- package/dist/lib/chat/index.d.ts +0 -24
- package/dist/lib/chat/index.js +0 -33
- package/dist/lib/chat/session-storage.d.ts +0 -77
- package/dist/lib/chat/session-storage.js +0 -233
- package/dist/lib/chat/session.d.ts +0 -96
- package/dist/lib/chat/session.js +0 -257
- package/dist/lib/chat/sse-handler.d.ts +0 -49
- package/dist/lib/chat/sse-handler.js +0 -259
- package/dist/lib/chat/types.d.ts +0 -74
- package/dist/lib/chat/types.js +0 -5
- package/dist/lib/chat/websocket-chat-handler.d.ts +0 -37
- package/dist/lib/chat/websocket-chat-handler.js +0 -262
- package/dist/lib/core/defaults.d.ts +0 -19
- package/dist/lib/core/defaults.js +0 -29
- package/dist/lib/core/evaluation-config.d.ts +0 -29
- package/dist/lib/core/evaluation-config.js +0 -144
- package/dist/lib/factories/compatibility-factory.d.ts +0 -35
- package/dist/lib/factories/compatibility-factory.js +0 -71
- package/dist/lib/factories/provider-generate-factory.d.ts +0 -20
- package/dist/lib/factories/provider-generate-factory.js +0 -93
- package/dist/lib/mcp/adapters/plugin-bridge.d.ts +0 -40
- package/dist/lib/mcp/adapters/plugin-bridge.js +0 -89
- package/dist/lib/mcp/auto-discovery.d.ts +0 -62
- package/dist/lib/mcp/auto-discovery.js +0 -149
- package/dist/lib/mcp/client.d.ts +0 -68
- package/dist/lib/mcp/client.js +0 -248
- package/dist/lib/mcp/config.d.ts +0 -31
- package/dist/lib/mcp/config.js +0 -99
- package/dist/lib/mcp/context-manager.d.ts +0 -171
- package/dist/lib/mcp/context-manager.js +0 -362
- package/dist/lib/mcp/contracts/mcp-contract.d.ts +0 -169
- package/dist/lib/mcp/contracts/mcp-contract.js +0 -58
- package/dist/lib/mcp/core/plugin-manager.d.ts +0 -46
- package/dist/lib/mcp/core/plugin-manager.js +0 -110
- package/dist/lib/mcp/demo/plugin-demo.d.ts +0 -20
- package/dist/lib/mcp/demo/plugin-demo.js +0 -118
- package/dist/lib/mcp/dynamic-chain-executor.d.ts +0 -225
- package/dist/lib/mcp/dynamic-chain-executor.js +0 -489
- package/dist/lib/mcp/dynamic-orchestrator.d.ts +0 -115
- package/dist/lib/mcp/dynamic-orchestrator.js +0 -351
- package/dist/lib/mcp/ecosystem.d.ts +0 -75
- package/dist/lib/mcp/ecosystem.js +0 -161
- package/dist/lib/mcp/error-manager.d.ts +0 -254
- package/dist/lib/mcp/error-manager.js +0 -501
- package/dist/lib/mcp/error-recovery.d.ts +0 -159
- package/dist/lib/mcp/error-recovery.js +0 -405
- package/dist/lib/mcp/external-client.d.ts +0 -88
- package/dist/lib/mcp/external-client.js +0 -331
- package/dist/lib/mcp/external-manager.d.ts +0 -112
- package/dist/lib/mcp/external-manager.js +0 -308
- package/dist/lib/mcp/function-calling.d.ts +0 -65
- package/dist/lib/mcp/function-calling.js +0 -642
- package/dist/lib/mcp/health-monitor.d.ts +0 -257
- package/dist/lib/mcp/health-monitor.js +0 -630
- package/dist/lib/mcp/initialize-tools.d.ts +0 -29
- package/dist/lib/mcp/initialize-tools.js +0 -261
- package/dist/lib/mcp/initialize.d.ts +0 -18
- package/dist/lib/mcp/initialize.js +0 -62
- package/dist/lib/mcp/manager.d.ts +0 -68
- package/dist/lib/mcp/manager.js +0 -176
- package/dist/lib/mcp/neurolink-mcp-client.d.ts +0 -97
- package/dist/lib/mcp/neurolink-mcp-client.js +0 -462
- package/dist/lib/mcp/orchestrator.d.ts +0 -302
- package/dist/lib/mcp/orchestrator.js +0 -703
- package/dist/lib/mcp/plugin-manager.d.ts +0 -98
- package/dist/lib/mcp/plugin-manager.js +0 -296
- package/dist/lib/mcp/plugins/core/filesystem-mcp.d.ts +0 -36
- package/dist/lib/mcp/plugins/core/filesystem-mcp.js +0 -142
- package/dist/lib/mcp/plugins/filesystem-mcp.d.ts +0 -37
- package/dist/lib/mcp/plugins/filesystem-mcp.js +0 -54
- package/dist/lib/mcp/security-manager.d.ts +0 -87
- package/dist/lib/mcp/security-manager.js +0 -344
- package/dist/lib/mcp/semaphore-manager.d.ts +0 -137
- package/dist/lib/mcp/semaphore-manager.js +0 -329
- package/dist/lib/mcp/session-manager.d.ts +0 -187
- package/dist/lib/mcp/session-manager.js +0 -400
- package/dist/lib/mcp/session-persistence.d.ts +0 -93
- package/dist/lib/mcp/session-persistence.js +0 -301
- package/dist/lib/mcp/tool-integration.d.ts +0 -58
- package/dist/lib/mcp/tool-integration.js +0 -203
- package/dist/lib/mcp/transport-manager.d.ts +0 -154
- package/dist/lib/mcp/transport-manager.js +0 -334
- package/dist/lib/mcp/unified-mcp.d.ts +0 -133
- package/dist/lib/mcp/unified-mcp.js +0 -251
- package/dist/lib/mcp/unified-registry.d.ts +0 -165
- package/dist/lib/mcp/unified-registry.js +0 -538
- package/dist/lib/providers/analytics-helper.d.ts +0 -38
- package/dist/lib/providers/analytics-helper.js +0 -216
- package/dist/lib/providers/function-calling-provider.d.ts +0 -142
- package/dist/lib/providers/function-calling-provider.js +0 -630
- package/dist/lib/providers/mcp-provider.d.ts +0 -75
- package/dist/lib/providers/mcp-provider.js +0 -283
- package/dist/lib/providers/timeout-wrapper.d.ts +0 -40
- package/dist/lib/providers/timeout-wrapper.js +0 -100
- package/dist/lib/sdk/tool-extension.d.ts +0 -181
- package/dist/lib/sdk/tool-extension.js +0 -284
- package/dist/lib/services/streaming/streaming-manager.d.ts +0 -29
- package/dist/lib/services/streaming/streaming-manager.js +0 -245
- package/dist/lib/services/types.d.ts +0 -156
- package/dist/lib/services/types.js +0 -2
- package/dist/lib/services/websocket/websocket-server.d.ts +0 -34
- package/dist/lib/services/websocket/websocket-server.js +0 -305
- package/dist/lib/utils/provider-validation.d.ts +0 -36
- package/dist/lib/utils/provider-validation.js +0 -625
- package/dist/lib/utils/providerUtils-fixed.d.ts +0 -8
- package/dist/lib/utils/providerUtils-fixed.js +0 -94
- package/dist/lib/utils/streaming-utils.d.ts +0 -79
- package/dist/lib/utils/streaming-utils.js +0 -198
- package/dist/lib/utils/timeout-manager.d.ts +0 -75
- package/dist/lib/utils/timeout-manager.js +0 -244
- package/dist/mcp/adapters/plugin-bridge.d.ts +0 -40
- package/dist/mcp/adapters/plugin-bridge.js +0 -89
- package/dist/mcp/auto-discovery.d.ts +0 -62
- package/dist/mcp/auto-discovery.js +0 -149
- package/dist/mcp/client.d.ts +0 -68
- package/dist/mcp/client.js +0 -248
- package/dist/mcp/config.d.ts +0 -31
- package/dist/mcp/config.js +0 -99
- package/dist/mcp/context-manager.d.ts +0 -171
- package/dist/mcp/context-manager.js +0 -362
- package/dist/mcp/contracts/mcp-contract.d.ts +0 -169
- package/dist/mcp/contracts/mcp-contract.js +0 -58
- package/dist/mcp/core/plugin-manager.d.ts +0 -46
- package/dist/mcp/core/plugin-manager.js +0 -110
- package/dist/mcp/demo/plugin-demo.d.ts +0 -20
- package/dist/mcp/demo/plugin-demo.js +0 -118
- package/dist/mcp/dynamic-chain-executor.d.ts +0 -225
- package/dist/mcp/dynamic-chain-executor.js +0 -489
- package/dist/mcp/dynamic-orchestrator.d.ts +0 -115
- package/dist/mcp/dynamic-orchestrator.js +0 -351
- package/dist/mcp/ecosystem.d.ts +0 -75
- package/dist/mcp/ecosystem.js +0 -162
- package/dist/mcp/error-manager.d.ts +0 -254
- package/dist/mcp/error-manager.js +0 -501
- package/dist/mcp/error-recovery.d.ts +0 -159
- package/dist/mcp/error-recovery.js +0 -405
- package/dist/mcp/external-client.d.ts +0 -88
- package/dist/mcp/external-client.js +0 -331
- package/dist/mcp/external-manager.d.ts +0 -112
- package/dist/mcp/external-manager.js +0 -308
- package/dist/mcp/function-calling.d.ts +0 -65
- package/dist/mcp/function-calling.js +0 -642
- package/dist/mcp/health-monitor.d.ts +0 -257
- package/dist/mcp/health-monitor.js +0 -630
- package/dist/mcp/initialize-tools.d.ts +0 -29
- package/dist/mcp/initialize-tools.js +0 -262
- package/dist/mcp/initialize.d.ts +0 -18
- package/dist/mcp/initialize.js +0 -62
- package/dist/mcp/manager.d.ts +0 -68
- package/dist/mcp/manager.js +0 -176
- package/dist/mcp/neurolink-mcp-client.d.ts +0 -97
- package/dist/mcp/neurolink-mcp-client.js +0 -462
- package/dist/mcp/orchestrator.d.ts +0 -302
- package/dist/mcp/orchestrator.js +0 -703
- package/dist/mcp/plugin-manager.d.ts +0 -98
- package/dist/mcp/plugin-manager.js +0 -297
- package/dist/mcp/plugins/core/filesystem-mcp.d.ts +0 -36
- package/dist/mcp/plugins/core/filesystem-mcp.js +0 -142
- package/dist/mcp/plugins/core/neurolink-mcp.json +0 -17
- package/dist/mcp/plugins/filesystem-mcp.d.ts +0 -37
- package/dist/mcp/plugins/filesystem-mcp.js +0 -54
- package/dist/mcp/security-manager.d.ts +0 -87
- package/dist/mcp/security-manager.js +0 -344
- package/dist/mcp/semaphore-manager.d.ts +0 -137
- package/dist/mcp/semaphore-manager.js +0 -329
- package/dist/mcp/session-manager.d.ts +0 -187
- package/dist/mcp/session-manager.js +0 -400
- package/dist/mcp/session-persistence.d.ts +0 -93
- package/dist/mcp/session-persistence.js +0 -302
- package/dist/mcp/tool-integration.d.ts +0 -58
- package/dist/mcp/tool-integration.js +0 -203
- package/dist/mcp/transport-manager.d.ts +0 -154
- package/dist/mcp/transport-manager.js +0 -335
- package/dist/mcp/unified-mcp.d.ts +0 -133
- package/dist/mcp/unified-mcp.js +0 -251
- package/dist/mcp/unified-registry.d.ts +0 -165
- package/dist/mcp/unified-registry.js +0 -539
- package/dist/providers/analytics-helper.d.ts +0 -38
- package/dist/providers/analytics-helper.js +0 -216
- package/dist/providers/function-calling-provider.d.ts +0 -142
- package/dist/providers/function-calling-provider.js +0 -630
- package/dist/providers/mcp-provider.d.ts +0 -75
- package/dist/providers/mcp-provider.js +0 -283
- package/dist/providers/timeout-wrapper.d.ts +0 -40
- package/dist/providers/timeout-wrapper.js +0 -100
- package/dist/sdk/tool-extension.d.ts +0 -181
- package/dist/sdk/tool-extension.js +0 -284
- package/dist/services/streaming/streaming-manager.d.ts +0 -29
- package/dist/services/streaming/streaming-manager.js +0 -245
- package/dist/services/types.d.ts +0 -156
- package/dist/services/types.js +0 -2
- package/dist/services/websocket/websocket-server.d.ts +0 -34
- package/dist/services/websocket/websocket-server.js +0 -306
- package/dist/utils/provider-validation.d.ts +0 -36
- package/dist/utils/provider-validation.js +0 -625
- package/dist/utils/providerUtils-fixed.d.ts +0 -8
- package/dist/utils/providerUtils-fixed.js +0 -94
- package/dist/utils/streaming-utils.d.ts +0 -79
- package/dist/utils/streaming-utils.js +0 -198
- package/dist/utils/timeout-manager.d.ts +0 -75
- package/dist/utils/timeout-manager.js +0 -244
package/dist/cli/commands/mcp.js
DELETED
|
@@ -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
|
-
}
|