snow-flow 2.8.6 โ†’ 2.8.7

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.
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
- * Start all ServiceNow MCP servers
3
+ * Start all ServiceNow MCP servers (WITH SINGLETON PROTECTION)
4
4
  */
5
5
  export {};
6
6
  //# sourceMappingURL=start-all-mcp-servers.d.ts.map
@@ -1,14 +1,21 @@
1
1
  #!/usr/bin/env node
2
2
  "use strict";
3
3
  /**
4
- * Start all ServiceNow MCP servers
4
+ * Start all ServiceNow MCP servers (WITH SINGLETON PROTECTION)
5
5
  */
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
7
  const child_process_1 = require("child_process");
8
8
  const logger_js_1 = require("../utils/logger.js");
9
+ const mcp_singleton_lock_js_1 = require("../utils/mcp-singleton-lock.js");
9
10
  const logger = new logger_js_1.Logger('MCPServerLauncher');
10
11
  async function startAllServers() {
11
- logger.info('Starting all ServiceNow MCP servers...');
12
+ // ๐Ÿ”’ SINGLETON CHECK - Prevent duplicate instances
13
+ const singletonLock = (0, mcp_singleton_lock_js_1.getMCPSingletonLock)();
14
+ if (!singletonLock.acquire()) {
15
+ logger.error('โŒ MCP servers already running. Exiting.');
16
+ process.exit(1);
17
+ }
18
+ logger.info('โœ… Starting all ServiceNow MCP servers (singleton protected)...');
12
19
  const servers = [
13
20
  {
14
21
  name: 'ServiceNow MCP Server',
@@ -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
@@ -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;
@@ -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.6",
3
+ "version": "2.8.7",
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",