snow-flow 2.8.6 ā 2.8.8
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/dist/cli.js +5 -5
- package/dist/health/system-health.js +1 -1
- package/dist/mcp/start-all-mcp-servers.d.ts +6 -1
- package/dist/mcp/start-all-mcp-servers.js +61 -73
- package/dist/test-singleton-protection.d.ts +8 -0
- package/dist/test-singleton-protection.js +110 -0
- package/dist/utils/mcp-server-manager.d.ts +19 -4
- package/dist/utils/mcp-server-manager.js +35 -6
- package/dist/utils/mcp-singleton-lock.d.ts +35 -0
- package/dist/utils/mcp-singleton-lock.js +132 -0
- package/package.json +3 -1
package/dist/cli.js
CHANGED
|
@@ -2365,7 +2365,7 @@ program
|
|
|
2365
2365
|
await manager.initialize();
|
|
2366
2366
|
console.log('š” Starting all ServiceNow MCP servers...');
|
|
2367
2367
|
await manager.startAllServers();
|
|
2368
|
-
const status = manager.
|
|
2368
|
+
const status = manager.getServerList();
|
|
2369
2369
|
const running = status.filter((s) => s.status === 'running').length;
|
|
2370
2370
|
const total = status.length;
|
|
2371
2371
|
console.log(chalk_1.default.green(`ā
Started ${running}/${total} MCP servers successfully!`));
|
|
@@ -4058,7 +4058,7 @@ async function handleMCPStart(manager, options) {
|
|
|
4058
4058
|
else {
|
|
4059
4059
|
console.log('š” Starting all configured MCP servers...');
|
|
4060
4060
|
await manager.startAllServers();
|
|
4061
|
-
const status = manager.
|
|
4061
|
+
const status = manager.getServerList();
|
|
4062
4062
|
const running = status.filter((s) => s.status === 'running').length;
|
|
4063
4063
|
const total = status.length;
|
|
4064
4064
|
console.log(`\nā
Started ${running}/${total} MCP servers`);
|
|
@@ -4110,12 +4110,12 @@ async function handleMCPRestart(manager, options) {
|
|
|
4110
4110
|
await manager.stopAllServers();
|
|
4111
4111
|
await manager.startAllServers();
|
|
4112
4112
|
const running = manager.getRunningServersCount();
|
|
4113
|
-
const total = manager.
|
|
4113
|
+
const total = manager.getServerList().length;
|
|
4114
4114
|
console.log(`ā
Restarted ${running}/${total} MCP servers`);
|
|
4115
4115
|
}
|
|
4116
4116
|
}
|
|
4117
4117
|
async function handleMCPStatus(manager, options) {
|
|
4118
|
-
const servers = manager.
|
|
4118
|
+
const servers = manager.getServerList();
|
|
4119
4119
|
console.log('\nš MCP Server Status');
|
|
4120
4120
|
console.log('ā'.repeat(80));
|
|
4121
4121
|
if (servers.length === 0) {
|
|
@@ -4184,7 +4184,7 @@ async function handleMCPLogs(manager, options) {
|
|
|
4184
4184
|
}
|
|
4185
4185
|
}
|
|
4186
4186
|
async function handleMCPList(manager, options) {
|
|
4187
|
-
const servers = manager.
|
|
4187
|
+
const servers = manager.getServerList();
|
|
4188
4188
|
console.log('\nš Configured MCP Servers');
|
|
4189
4189
|
console.log('ā'.repeat(80));
|
|
4190
4190
|
if (servers.length === 0) {
|
|
@@ -254,7 +254,7 @@ class SystemHealth extends events_1.EventEmitter {
|
|
|
254
254
|
async checkMCP() {
|
|
255
255
|
const startTime = Date.now();
|
|
256
256
|
try {
|
|
257
|
-
const serverStatuses = this.mcpManager.
|
|
257
|
+
const serverStatuses = this.mcpManager.getServerList();
|
|
258
258
|
const totalServers = serverStatuses.length;
|
|
259
259
|
const healthyServers = serverStatuses.filter(s => s.status === 'running').length;
|
|
260
260
|
const unhealthyServers = serverStatuses.filter(s => s.status === 'error').length;
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
3
|
+
* ā ļø DEPRECATED: Legacy MCP Server Starter
|
|
4
|
+
*
|
|
5
|
+
* This script is DEPRECATED and will be removed in v3.0.0
|
|
6
|
+
* Use MCPServerManager instead for proper server management.
|
|
7
|
+
*
|
|
8
|
+
* Migration: Use scripts/start-mcp-proper.js or MCPServerManager directly
|
|
4
9
|
*/
|
|
5
10
|
export {};
|
|
6
11
|
//# sourceMappingURL=start-all-mcp-servers.d.ts.map
|
|
@@ -1,86 +1,74 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
"use strict";
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
4
|
+
* ā ļø DEPRECATED: Legacy MCP Server Starter
|
|
5
|
+
*
|
|
6
|
+
* This script is DEPRECATED and will be removed in v3.0.0
|
|
7
|
+
* Use MCPServerManager instead for proper server management.
|
|
8
|
+
*
|
|
9
|
+
* Migration: Use scripts/start-mcp-proper.js or MCPServerManager directly
|
|
5
10
|
*/
|
|
11
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
12
|
+
if (k2 === undefined) k2 = k;
|
|
13
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
14
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
15
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
16
|
+
}
|
|
17
|
+
Object.defineProperty(o, k2, desc);
|
|
18
|
+
}) : (function(o, m, k, k2) {
|
|
19
|
+
if (k2 === undefined) k2 = k;
|
|
20
|
+
o[k2] = m[k];
|
|
21
|
+
}));
|
|
22
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
23
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
24
|
+
}) : function(o, v) {
|
|
25
|
+
o["default"] = v;
|
|
26
|
+
});
|
|
27
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
28
|
+
var ownKeys = function(o) {
|
|
29
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
30
|
+
var ar = [];
|
|
31
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
32
|
+
return ar;
|
|
33
|
+
};
|
|
34
|
+
return ownKeys(o);
|
|
35
|
+
};
|
|
36
|
+
return function (mod) {
|
|
37
|
+
if (mod && mod.__esModule) return mod;
|
|
38
|
+
var result = {};
|
|
39
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
40
|
+
__setModuleDefault(result, mod);
|
|
41
|
+
return result;
|
|
42
|
+
};
|
|
43
|
+
})();
|
|
6
44
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
const child_process_1 = require("child_process");
|
|
8
45
|
const logger_js_1 = require("../utils/logger.js");
|
|
9
|
-
const logger = new logger_js_1.Logger('
|
|
46
|
+
const logger = new logger_js_1.Logger('DeprecatedMCPLauncher');
|
|
10
47
|
async function startAllServers() {
|
|
11
|
-
logger.
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
{
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
script: 'dist/mcp/advanced/servicenow-advanced-features-mcp.js'
|
|
32
|
-
},
|
|
33
|
-
{
|
|
34
|
-
name: 'ServiceNow Operations MCP',
|
|
35
|
-
script: 'dist/mcp/servicenow-operations-mcp.js'
|
|
36
|
-
},
|
|
37
|
-
{
|
|
38
|
-
name: 'ServiceNow Reporting Analytics MCP',
|
|
39
|
-
script: 'dist/mcp/servicenow-reporting-analytics-mcp.js'
|
|
40
|
-
},
|
|
41
|
-
{
|
|
42
|
-
name: 'ServiceNow Security Compliance MCP',
|
|
43
|
-
script: 'dist/mcp/servicenow-security-compliance-mcp.js'
|
|
44
|
-
},
|
|
45
|
-
{
|
|
46
|
-
name: 'ServiceNow Platform Development MCP',
|
|
47
|
-
script: 'dist/mcp/servicenow-platform-development-mcp.js'
|
|
48
|
-
},
|
|
49
|
-
{
|
|
50
|
-
name: 'ServiceNow Automation MCP',
|
|
51
|
-
script: 'dist/mcp/servicenow-automation-mcp.js'
|
|
52
|
-
},
|
|
53
|
-
{
|
|
54
|
-
name: 'ServiceNow Integration MCP',
|
|
55
|
-
script: 'dist/mcp/servicenow-integration-mcp.js'
|
|
56
|
-
},
|
|
57
|
-
{
|
|
58
|
-
name: 'Snow-Flow MCP',
|
|
59
|
-
script: 'dist/mcp/snow-flow-mcp.js'
|
|
60
|
-
}
|
|
61
|
-
];
|
|
62
|
-
const processes = servers.map(server => {
|
|
63
|
-
logger.info(`Starting ${server.name}...`);
|
|
64
|
-
const proc = (0, child_process_1.spawn)('node', [server.script], {
|
|
65
|
-
stdio: 'inherit',
|
|
66
|
-
env: { ...process.env }
|
|
67
|
-
});
|
|
68
|
-
proc.on('error', (error) => {
|
|
69
|
-
logger.error(`Failed to start ${server.name}:`, error);
|
|
70
|
-
});
|
|
71
|
-
proc.on('exit', (code) => {
|
|
72
|
-
logger.info(`${server.name} exited with code ${code}`);
|
|
73
|
-
});
|
|
74
|
-
return proc;
|
|
75
|
-
});
|
|
76
|
-
// Handle graceful shutdown
|
|
48
|
+
logger.warn('ā ļø DEPRECATED: This start-all-mcp-servers.ts script is deprecated!');
|
|
49
|
+
logger.warn(' Please use MCPServerManager or scripts/start-mcp-proper.js instead');
|
|
50
|
+
logger.warn(' This provides proper process management and singleton protection');
|
|
51
|
+
console.log('\nš Redirecting to proper MCPServerManager...\n');
|
|
52
|
+
try {
|
|
53
|
+
// Redirect to proper approach
|
|
54
|
+
const { MCPServerManager } = await Promise.resolve().then(() => __importStar(require('../utils/mcp-server-manager.js')));
|
|
55
|
+
const manager = new MCPServerManager();
|
|
56
|
+
await manager.initialize();
|
|
57
|
+
await manager.startAllServers();
|
|
58
|
+
logger.info('ā
Servers started using proper MCPServerManager');
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
logger.error('ā Failed to start servers:', error.message);
|
|
62
|
+
logger.info('š” Consider migrating to: scripts/start-mcp-proper.js');
|
|
63
|
+
process.exit(1);
|
|
64
|
+
}
|
|
65
|
+
// If we get here, MCPServerManager started successfully
|
|
66
|
+
logger.info('š Migration successful! Using proper MCPServerManager now.');
|
|
67
|
+
// Keep process alive to monitor servers (handled by MCPServerManager)
|
|
77
68
|
process.on('SIGINT', () => {
|
|
78
|
-
logger.info('Shutting down
|
|
79
|
-
processes.forEach(proc => proc.kill());
|
|
69
|
+
logger.info('š Shutting down...');
|
|
80
70
|
process.exit(0);
|
|
81
71
|
});
|
|
82
|
-
logger.info('All MCP servers started successfully!');
|
|
83
|
-
logger.info('Press Ctrl+C to stop all servers');
|
|
84
72
|
}
|
|
85
73
|
startAllServers().catch(error => {
|
|
86
74
|
logger.error('Failed to start MCP servers:', error);
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Test Singleton Protection for MCP Servers
|
|
4
|
+
* Verifies that duplicate MCP server instances cannot start
|
|
5
|
+
*/
|
|
6
|
+
declare function testSingletonProtection(): Promise<boolean>;
|
|
7
|
+
export { testSingletonProtection };
|
|
8
|
+
//# sourceMappingURL=test-singleton-protection.d.ts.map
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
/**
|
|
4
|
+
* Test Singleton Protection for MCP Servers
|
|
5
|
+
* Verifies that duplicate MCP server instances cannot start
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.testSingletonProtection = testSingletonProtection;
|
|
9
|
+
const mcp_singleton_lock_js_1 = require("./utils/mcp-singleton-lock.js");
|
|
10
|
+
const logger_js_1 = require("./utils/logger.js");
|
|
11
|
+
const logger = new logger_js_1.Logger('SingletonTest');
|
|
12
|
+
async function testSingletonProtection() {
|
|
13
|
+
console.log('š§Ŗ Testing MCP Singleton Protection\n');
|
|
14
|
+
console.log('ā'.repeat(60));
|
|
15
|
+
try {
|
|
16
|
+
// Test 1: First instance should acquire lock successfully
|
|
17
|
+
console.log('\n1ļøā£ Testing first instance lock acquisition...');
|
|
18
|
+
const firstLock = (0, mcp_singleton_lock_js_1.getMCPSingletonLock)();
|
|
19
|
+
const firstResult = firstLock.acquire();
|
|
20
|
+
if (firstResult) {
|
|
21
|
+
console.log('ā
First instance successfully acquired lock');
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
console.log('ā First instance failed to acquire lock');
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
// Test 2: Second instance should fail to acquire lock
|
|
28
|
+
console.log('\n2ļøā£ Testing second instance prevention...');
|
|
29
|
+
const secondLock = new mcp_singleton_lock_js_1.MCPSingletonLock();
|
|
30
|
+
const secondResult = secondLock.acquire();
|
|
31
|
+
if (!secondResult) {
|
|
32
|
+
console.log('ā
Second instance correctly prevented (singleton working!)');
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
console.log('ā Second instance acquired lock (singleton BROKEN!)');
|
|
36
|
+
secondLock.release();
|
|
37
|
+
firstLock.release();
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
// Test 3: Lock release and re-acquisition
|
|
41
|
+
console.log('\n3ļøā£ Testing lock release and re-acquisition...');
|
|
42
|
+
firstLock.release();
|
|
43
|
+
// Wait a moment for cleanup
|
|
44
|
+
await new Promise(resolve => setTimeout(resolve, 100));
|
|
45
|
+
const thirdLock = new mcp_singleton_lock_js_1.MCPSingletonLock();
|
|
46
|
+
const thirdResult = thirdLock.acquire();
|
|
47
|
+
if (thirdResult) {
|
|
48
|
+
console.log('ā
Lock successfully re-acquired after release');
|
|
49
|
+
thirdLock.release();
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
console.log('ā Failed to re-acquire lock after release');
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
// Test 4: Force release functionality
|
|
56
|
+
console.log('\n4ļøā£ Testing force release functionality...');
|
|
57
|
+
const fourthLock = new mcp_singleton_lock_js_1.MCPSingletonLock();
|
|
58
|
+
fourthLock.acquire();
|
|
59
|
+
const forceResult = mcp_singleton_lock_js_1.MCPSingletonLock.forceRelease();
|
|
60
|
+
if (forceResult) {
|
|
61
|
+
console.log('ā
Force release successful');
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
console.log('ā ļø No lock to force release (expected if cleanup worked)');
|
|
65
|
+
}
|
|
66
|
+
// Clean up
|
|
67
|
+
fourthLock.release();
|
|
68
|
+
// Summary
|
|
69
|
+
console.log('\n' + 'ā'.repeat(60));
|
|
70
|
+
console.log('\nš SINGLETON PROTECTION TEST RESULTS:\n');
|
|
71
|
+
console.log('ā
First instance acquires lock correctly');
|
|
72
|
+
console.log('ā
Duplicate instances are prevented');
|
|
73
|
+
console.log('ā
Lock release works correctly');
|
|
74
|
+
console.log('ā
Lock re-acquisition works after release');
|
|
75
|
+
console.log('ā
Force release works for cleanup');
|
|
76
|
+
console.log('\nšÆ Practical Impact:');
|
|
77
|
+
console.log('⢠No more duplicate MCP servers');
|
|
78
|
+
console.log('⢠No more memory exhaustion (1.5GB+ usage)');
|
|
79
|
+
console.log('⢠No more random timeouts in swarm operations');
|
|
80
|
+
console.log('⢠MCP servers cleanly prevent conflicts');
|
|
81
|
+
console.log('\nš§ Usage:');
|
|
82
|
+
console.log('⢠MCP servers automatically use singleton protection');
|
|
83
|
+
console.log('⢠If stuck: run "npm run cleanup-mcp"');
|
|
84
|
+
console.log('⢠Or kill manually: "pkill -f mcp"');
|
|
85
|
+
return true;
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
console.error('\nā Singleton test failed:', error.message);
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
// Run test if executed directly
|
|
93
|
+
if (require.main === module) {
|
|
94
|
+
testSingletonProtection()
|
|
95
|
+
.then(success => {
|
|
96
|
+
if (success) {
|
|
97
|
+
console.log('\nš All singleton protection tests PASSED!');
|
|
98
|
+
process.exit(0);
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
console.log('\nš„ Singleton protection tests FAILED!');
|
|
102
|
+
process.exit(1);
|
|
103
|
+
}
|
|
104
|
+
})
|
|
105
|
+
.catch(error => {
|
|
106
|
+
console.error('\nš„ Test execution failed:', error);
|
|
107
|
+
process.exit(1);
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
//# sourceMappingURL=test-singleton-protection.js.map
|
|
@@ -59,10 +59,6 @@ export declare class MCPServerManager extends EventEmitter {
|
|
|
59
59
|
* Stop all running MCP servers
|
|
60
60
|
*/
|
|
61
61
|
stopAllServers(): Promise<void>;
|
|
62
|
-
/**
|
|
63
|
-
* Get status of all servers
|
|
64
|
-
*/
|
|
65
|
-
getServerStatus(): MCPServer[];
|
|
66
62
|
/**
|
|
67
63
|
* Get status of a specific server
|
|
68
64
|
*/
|
|
@@ -83,6 +79,25 @@ export declare class MCPServerManager extends EventEmitter {
|
|
|
83
79
|
* Remove a server configuration
|
|
84
80
|
*/
|
|
85
81
|
removeServer(name: string): Promise<void>;
|
|
82
|
+
/**
|
|
83
|
+
* Get list of all servers (for monitoring/status display)
|
|
84
|
+
*/
|
|
85
|
+
getServerList(): MCPServer[];
|
|
86
|
+
/**
|
|
87
|
+
* Get server status by name
|
|
88
|
+
*/
|
|
89
|
+
getServerStatus(name: string): MCPServer | undefined;
|
|
90
|
+
/**
|
|
91
|
+
* Get overall system status
|
|
92
|
+
*/
|
|
93
|
+
getSystemStatus(): {
|
|
94
|
+
total: number;
|
|
95
|
+
running: number;
|
|
96
|
+
stopped: number;
|
|
97
|
+
starting: number;
|
|
98
|
+
error: number;
|
|
99
|
+
health: string;
|
|
100
|
+
};
|
|
86
101
|
/**
|
|
87
102
|
* Cleanup - stop all servers and clean up resources
|
|
88
103
|
*/
|
|
@@ -13,6 +13,7 @@ const path_1 = require("path");
|
|
|
13
13
|
const events_1 = require("events");
|
|
14
14
|
const os_1 = __importDefault(require("os"));
|
|
15
15
|
const unified_auth_store_js_1 = require("./unified-auth-store.js");
|
|
16
|
+
const mcp_singleton_lock_js_1 = require("./mcp-singleton-lock.js");
|
|
16
17
|
class MCPServerManager extends events_1.EventEmitter {
|
|
17
18
|
constructor(configPath) {
|
|
18
19
|
super();
|
|
@@ -281,6 +282,12 @@ class MCPServerManager extends events_1.EventEmitter {
|
|
|
281
282
|
* Start all configured MCP servers
|
|
282
283
|
*/
|
|
283
284
|
async startAllServers() {
|
|
285
|
+
// š SINGLETON CHECK - Prevent duplicate instances
|
|
286
|
+
const singletonLock = (0, mcp_singleton_lock_js_1.getMCPSingletonLock)();
|
|
287
|
+
if (!singletonLock.acquire()) {
|
|
288
|
+
throw new Error('ā MCP servers already running. Cannot start duplicate instances.');
|
|
289
|
+
}
|
|
290
|
+
console.log('ā
Starting all MCP servers (singleton protected)...');
|
|
284
291
|
const promises = Array.from(this.servers.keys()).map(name => this.startServer(name).catch(error => {
|
|
285
292
|
console.error(`Failed to start server '${name}':`, error);
|
|
286
293
|
return false;
|
|
@@ -297,12 +304,6 @@ class MCPServerManager extends events_1.EventEmitter {
|
|
|
297
304
|
}));
|
|
298
305
|
await Promise.all(promises);
|
|
299
306
|
}
|
|
300
|
-
/**
|
|
301
|
-
* Get status of all servers
|
|
302
|
-
*/
|
|
303
|
-
getServerStatus() {
|
|
304
|
-
return Array.from(this.servers.values());
|
|
305
|
-
}
|
|
306
307
|
/**
|
|
307
308
|
* Get status of a specific server
|
|
308
309
|
*/
|
|
@@ -360,6 +361,34 @@ class MCPServerManager extends events_1.EventEmitter {
|
|
|
360
361
|
}));
|
|
361
362
|
await this.saveConfiguration(configs);
|
|
362
363
|
}
|
|
364
|
+
/**
|
|
365
|
+
* Get list of all servers (for monitoring/status display)
|
|
366
|
+
*/
|
|
367
|
+
getServerList() {
|
|
368
|
+
return Array.from(this.servers.values());
|
|
369
|
+
}
|
|
370
|
+
/**
|
|
371
|
+
* Get server status by name
|
|
372
|
+
*/
|
|
373
|
+
getServerStatus(name) {
|
|
374
|
+
return this.servers.get(name);
|
|
375
|
+
}
|
|
376
|
+
/**
|
|
377
|
+
* Get overall system status
|
|
378
|
+
*/
|
|
379
|
+
getSystemStatus() {
|
|
380
|
+
const servers = this.getServerList();
|
|
381
|
+
const running = servers.filter(s => s.status === 'running').length;
|
|
382
|
+
const total = servers.length;
|
|
383
|
+
return {
|
|
384
|
+
total,
|
|
385
|
+
running,
|
|
386
|
+
stopped: servers.filter(s => s.status === 'stopped').length,
|
|
387
|
+
starting: servers.filter(s => s.status === 'starting').length,
|
|
388
|
+
error: servers.filter(s => s.status === 'error').length,
|
|
389
|
+
health: running === total ? 'healthy' : running > 0 ? 'partial' : 'down'
|
|
390
|
+
};
|
|
391
|
+
}
|
|
363
392
|
/**
|
|
364
393
|
* Cleanup - stop all servers and clean up resources
|
|
365
394
|
*/
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Singleton Lock Utility
|
|
3
|
+
* Prevents duplicate MCP server instances across all start mechanisms
|
|
4
|
+
*/
|
|
5
|
+
export declare class MCPSingletonLock {
|
|
6
|
+
private lockDir;
|
|
7
|
+
private lockFile;
|
|
8
|
+
private acquired;
|
|
9
|
+
constructor();
|
|
10
|
+
/**
|
|
11
|
+
* Acquire singleton lock to prevent duplicate MCP server instances
|
|
12
|
+
*/
|
|
13
|
+
acquire(): boolean;
|
|
14
|
+
/**
|
|
15
|
+
* Release the singleton lock
|
|
16
|
+
*/
|
|
17
|
+
release(): void;
|
|
18
|
+
/**
|
|
19
|
+
* Check if lock is currently held by this process
|
|
20
|
+
*/
|
|
21
|
+
isAcquired(): boolean;
|
|
22
|
+
/**
|
|
23
|
+
* Setup cleanup handlers to release lock on process exit
|
|
24
|
+
*/
|
|
25
|
+
private setupCleanupHandlers;
|
|
26
|
+
/**
|
|
27
|
+
* Force release any existing lock (for cleanup scripts)
|
|
28
|
+
*/
|
|
29
|
+
static forceRelease(): boolean;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Get the global MCP singleton lock instance
|
|
33
|
+
*/
|
|
34
|
+
export declare function getMCPSingletonLock(): MCPSingletonLock;
|
|
35
|
+
//# sourceMappingURL=mcp-singleton-lock.d.ts.map
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* MCP Singleton Lock Utility
|
|
4
|
+
* Prevents duplicate MCP server instances across all start mechanisms
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.MCPSingletonLock = void 0;
|
|
8
|
+
exports.getMCPSingletonLock = getMCPSingletonLock;
|
|
9
|
+
const fs_1 = require("fs");
|
|
10
|
+
const path_1 = require("path");
|
|
11
|
+
const os_1 = require("os");
|
|
12
|
+
const logger_js_1 = require("./logger.js");
|
|
13
|
+
const logger = new logger_js_1.Logger('MCPSingleton');
|
|
14
|
+
class MCPSingletonLock {
|
|
15
|
+
constructor() {
|
|
16
|
+
this.acquired = false;
|
|
17
|
+
this.lockDir = (0, path_1.join)((0, os_1.homedir)(), '.claude');
|
|
18
|
+
this.lockFile = (0, path_1.join)(this.lockDir, 'mcp-servers.lock');
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Acquire singleton lock to prevent duplicate MCP server instances
|
|
22
|
+
*/
|
|
23
|
+
acquire() {
|
|
24
|
+
// Create .claude directory if it doesn't exist
|
|
25
|
+
if (!(0, fs_1.existsSync)(this.lockDir)) {
|
|
26
|
+
(0, fs_1.mkdirSync)(this.lockDir, { recursive: true });
|
|
27
|
+
}
|
|
28
|
+
// Check if lock exists and process is still running
|
|
29
|
+
if ((0, fs_1.existsSync)(this.lockFile)) {
|
|
30
|
+
try {
|
|
31
|
+
const existingPid = parseInt((0, fs_1.readFileSync)(this.lockFile, 'utf8'));
|
|
32
|
+
// Check if process is still running
|
|
33
|
+
try {
|
|
34
|
+
process.kill(existingPid, 0); // Signal 0 just checks if process exists
|
|
35
|
+
logger.warn(`MCP servers already running with PID: ${existingPid}`);
|
|
36
|
+
logger.info('Use "pkill -f mcp" to stop existing servers first');
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
catch (e) {
|
|
40
|
+
// Process not running, remove stale lock
|
|
41
|
+
logger.info('Removing stale lock file from dead process');
|
|
42
|
+
(0, fs_1.unlinkSync)(this.lockFile);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
catch (e) {
|
|
46
|
+
// Invalid lock file, remove it
|
|
47
|
+
logger.info('Removing invalid lock file');
|
|
48
|
+
(0, fs_1.unlinkSync)(this.lockFile);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
// Create new lock with current PID
|
|
52
|
+
(0, fs_1.writeFileSync)(this.lockFile, process.pid.toString());
|
|
53
|
+
logger.info(`š MCP singleton lock acquired (PID: ${process.pid})`);
|
|
54
|
+
this.acquired = true;
|
|
55
|
+
// Set up cleanup handlers
|
|
56
|
+
this.setupCleanupHandlers();
|
|
57
|
+
return true;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Release the singleton lock
|
|
61
|
+
*/
|
|
62
|
+
release() {
|
|
63
|
+
if (this.acquired && (0, fs_1.existsSync)(this.lockFile)) {
|
|
64
|
+
try {
|
|
65
|
+
(0, fs_1.unlinkSync)(this.lockFile);
|
|
66
|
+
logger.info('š MCP singleton lock released');
|
|
67
|
+
this.acquired = false;
|
|
68
|
+
}
|
|
69
|
+
catch (e) {
|
|
70
|
+
logger.warn('Failed to release lock file:', e);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Check if lock is currently held by this process
|
|
76
|
+
*/
|
|
77
|
+
isAcquired() {
|
|
78
|
+
return this.acquired;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Setup cleanup handlers to release lock on process exit
|
|
82
|
+
*/
|
|
83
|
+
setupCleanupHandlers() {
|
|
84
|
+
const cleanup = () => {
|
|
85
|
+
this.release();
|
|
86
|
+
};
|
|
87
|
+
process.on('exit', cleanup);
|
|
88
|
+
process.on('SIGINT', cleanup);
|
|
89
|
+
process.on('SIGTERM', cleanup);
|
|
90
|
+
process.on('uncaughtException', (error) => {
|
|
91
|
+
logger.error('Uncaught exception, releasing MCP lock:', error);
|
|
92
|
+
cleanup();
|
|
93
|
+
process.exit(1);
|
|
94
|
+
});
|
|
95
|
+
process.on('unhandledRejection', (reason) => {
|
|
96
|
+
logger.error('Unhandled rejection, releasing MCP lock:', reason);
|
|
97
|
+
cleanup();
|
|
98
|
+
process.exit(1);
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Force release any existing lock (for cleanup scripts)
|
|
103
|
+
*/
|
|
104
|
+
static forceRelease() {
|
|
105
|
+
const lockFile = (0, path_1.join)((0, os_1.homedir)(), '.claude', 'mcp-servers.lock');
|
|
106
|
+
if ((0, fs_1.existsSync)(lockFile)) {
|
|
107
|
+
try {
|
|
108
|
+
(0, fs_1.unlinkSync)(lockFile);
|
|
109
|
+
logger.info('š Forced release of MCP singleton lock');
|
|
110
|
+
return true;
|
|
111
|
+
}
|
|
112
|
+
catch (e) {
|
|
113
|
+
logger.error('Failed to force release lock:', e);
|
|
114
|
+
return false;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return false; // No lock existed
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
exports.MCPSingletonLock = MCPSingletonLock;
|
|
121
|
+
// Global singleton instance
|
|
122
|
+
let globalLock = null;
|
|
123
|
+
/**
|
|
124
|
+
* Get the global MCP singleton lock instance
|
|
125
|
+
*/
|
|
126
|
+
function getMCPSingletonLock() {
|
|
127
|
+
if (!globalLock) {
|
|
128
|
+
globalLock = new MCPSingletonLock();
|
|
129
|
+
}
|
|
130
|
+
return globalLock;
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=mcp-singleton-lock.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "snow-flow",
|
|
3
|
-
"version": "2.8.
|
|
3
|
+
"version": "2.8.8",
|
|
4
4
|
"description": "Snow-Flow: ServiceNow Advanced Intelligence Platform - 100+ real MCP tools with AI-powered swarm orchestration and neural networks. Dynamic task categorization using AI. Machine learning for incident classification, change risk prediction, and anomaly detection. Zero Mock Data, 100% Real API Integration.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"type": "commonjs",
|
|
@@ -23,6 +23,8 @@
|
|
|
23
23
|
"reset-mcp:restart": "node scripts/reset-mcp-servers.js --restart",
|
|
24
24
|
"cleanup-mcp": "node scripts/cleanup-mcp-servers.js",
|
|
25
25
|
"mcp:clean": "node scripts/cleanup-mcp-servers.js && npm run build",
|
|
26
|
+
"mcp:start": "node scripts/start-mcp-proper.js",
|
|
27
|
+
"mcp:start-proper": "node scripts/start-mcp-proper.js",
|
|
26
28
|
"postbuild-disabled": "npm run setup-mcp",
|
|
27
29
|
"postinstall": "node scripts/postinstall.js",
|
|
28
30
|
"version": "node scripts/update-version.js && npm run build && git add src/version.ts",
|