snow-flow 2.9.9 → 2.10.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.
@@ -14,6 +14,7 @@ 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
16
  const mcp_singleton_lock_js_1 = require("./mcp-singleton-lock.js");
17
+ const mcp_singleton_enforcer_js_1 = require("./mcp-singleton-enforcer.js");
17
18
  const mcp_process_manager_js_1 = require("./mcp-process-manager.js");
18
19
  class MCPServerManager extends events_1.EventEmitter {
19
20
  constructor(configPath) {
@@ -298,10 +299,12 @@ class MCPServerManager extends events_1.EventEmitter {
298
299
  * Start all configured MCP servers
299
300
  */
300
301
  async startAllServers() {
301
- // 🔒 SINGLETON CHECK - Prevent duplicate instances
302
- const singletonLock = (0, mcp_singleton_lock_js_1.getMCPSingletonLock)();
303
- if (!singletonLock.acquire()) {
304
- throw new Error('❌ MCP servers already running. Cannot start duplicate instances.');
302
+ // 🔒 ENFORCE SINGLETON - Kill any existing and acquire lock
303
+ mcp_singleton_enforcer_js_1.MCPSingletonEnforcer.enforce();
304
+ // Health check before starting
305
+ const health = await mcp_singleton_enforcer_js_1.MCPSingletonEnforcer.checkHealth();
306
+ if (!health.healthy) {
307
+ console.warn('⚠️ MCP health issues detected:', health.issues);
305
308
  }
306
309
  // Clean up any existing duplicates first
307
310
  const processManager = mcp_process_manager_js_1.MCPProcessManager.getInstance();
@@ -0,0 +1,30 @@
1
+ /**
2
+ * MCP Singleton Enforcer
3
+ * Ensures only ONE set of MCP servers can run at a time
4
+ * v2.10.0 - Critical fix for duplicate MCP servers causing timeouts
5
+ */
6
+ export declare class MCPSingletonEnforcer {
7
+ private static enforced;
8
+ /**
9
+ * Kill ALL existing MCP processes before starting new ones
10
+ * This is a nuclear option but necessary to prevent timeouts
11
+ */
12
+ static killAllMCPProcesses(): number;
13
+ /**
14
+ * Enforce singleton before any MCP operation
15
+ * This should be called before starting ANY MCP server
16
+ */
17
+ static enforce(): boolean;
18
+ /**
19
+ * Setup cleanup handlers
20
+ */
21
+ private static setupCleanup;
22
+ /**
23
+ * Check if MCP servers are healthy
24
+ */
25
+ static checkHealth(): Promise<{
26
+ healthy: boolean;
27
+ issues: string[];
28
+ }>;
29
+ }
30
+ //# sourceMappingURL=mcp-singleton-enforcer.d.ts.map
@@ -0,0 +1,177 @@
1
+ "use strict";
2
+ /**
3
+ * MCP Singleton Enforcer
4
+ * Ensures only ONE set of MCP servers can run at a time
5
+ * v2.10.0 - Critical fix for duplicate MCP servers causing timeouts
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.MCPSingletonEnforcer = void 0;
9
+ const logger_js_1 = require("./logger.js");
10
+ const child_process_1 = require("child_process");
11
+ const mcp_singleton_lock_js_1 = require("./mcp-singleton-lock.js");
12
+ const logger = new logger_js_1.Logger('MCPSingletonEnforcer');
13
+ class MCPSingletonEnforcer {
14
+ /**
15
+ * Kill ALL existing MCP processes before starting new ones
16
+ * This is a nuclear option but necessary to prevent timeouts
17
+ */
18
+ static killAllMCPProcesses() {
19
+ try {
20
+ // Count existing processes
21
+ const countCmd = "ps aux | grep -E 'mcp.*\\.js' | grep -v grep | wc -l";
22
+ const count = parseInt((0, child_process_1.execSync)(countCmd, { encoding: 'utf8' }).trim());
23
+ if (count > 0) {
24
+ logger.warn(`🔪 Found ${count} existing MCP processes, killing them all...`);
25
+ // Kill all MCP processes
26
+ try {
27
+ (0, child_process_1.execSync)("pkill -f 'mcp.*\\.js'", { encoding: 'utf8' });
28
+ logger.info('✅ Killed all existing MCP processes');
29
+ }
30
+ catch (e) {
31
+ // pkill returns non-zero if no processes found, which is fine
32
+ }
33
+ // Also kill by specific patterns
34
+ const patterns = [
35
+ 'snow-flow-mcp',
36
+ 'servicenow-.*-mcp',
37
+ 'mcp/.*\\.js'
38
+ ];
39
+ for (const pattern of patterns) {
40
+ try {
41
+ (0, child_process_1.execSync)(`pkill -f '${pattern}'`, { encoding: 'utf8' });
42
+ }
43
+ catch (e) {
44
+ // Ignore errors, process might not exist
45
+ }
46
+ }
47
+ // Wait a moment for processes to die
48
+ (0, child_process_1.execSync)('sleep 1', { encoding: 'utf8' });
49
+ // Verify they're gone
50
+ const remaining = parseInt((0, child_process_1.execSync)(countCmd, { encoding: 'utf8' }).trim());
51
+ if (remaining > 0) {
52
+ logger.warn(`⚠️ ${remaining} MCP processes still running after kill`);
53
+ // Force kill with -9
54
+ try {
55
+ (0, child_process_1.execSync)("pkill -9 -f 'mcp.*\\.js'", { encoding: 'utf8' });
56
+ logger.info('✅ Force killed remaining MCP processes');
57
+ }
58
+ catch (e) {
59
+ // Ignore
60
+ }
61
+ }
62
+ return count;
63
+ }
64
+ return 0;
65
+ }
66
+ catch (error) {
67
+ logger.error('Error checking/killing MCP processes:', error.message);
68
+ return 0;
69
+ }
70
+ }
71
+ /**
72
+ * Enforce singleton before any MCP operation
73
+ * This should be called before starting ANY MCP server
74
+ */
75
+ static enforce() {
76
+ if (this.enforced) {
77
+ logger.debug('Singleton already enforced in this session');
78
+ return true;
79
+ }
80
+ // Check if strict mode is enabled
81
+ const strictMode = process.env.SNOW_MCP_SINGLETON_STRICT === 'true';
82
+ if (strictMode) {
83
+ logger.info('🔒 Strict singleton mode enabled');
84
+ // Kill any existing processes first
85
+ const killed = this.killAllMCPProcesses();
86
+ if (killed > 0) {
87
+ logger.info(`🧹 Cleaned up ${killed} stale MCP processes`);
88
+ }
89
+ }
90
+ // Try to acquire singleton lock
91
+ const lock = (0, mcp_singleton_lock_js_1.getMCPSingletonLock)();
92
+ if (!lock.acquire()) {
93
+ if (strictMode) {
94
+ // In strict mode, force release and try again
95
+ logger.warn('⚠️ Lock exists, forcing release in strict mode...');
96
+ mcp_singleton_lock_js_2.MCPSingletonLock.forceRelease();
97
+ // Try once more
98
+ if (!lock.acquire()) {
99
+ throw new Error('Cannot acquire MCP singleton lock even after force release');
100
+ }
101
+ logger.info('✅ Acquired lock after force release');
102
+ }
103
+ else {
104
+ throw new Error('MCP servers already running. Use SNOW_MCP_SINGLETON_STRICT=true to force');
105
+ }
106
+ }
107
+ this.enforced = true;
108
+ logger.info('✅ MCP singleton enforced successfully');
109
+ // Set up cleanup on exit
110
+ this.setupCleanup(lock);
111
+ return true;
112
+ }
113
+ /**
114
+ * Setup cleanup handlers
115
+ */
116
+ static setupCleanup(lock) {
117
+ const cleanup = () => {
118
+ if (this.enforced) {
119
+ logger.info('🧹 Cleaning up MCP singleton...');
120
+ lock.release();
121
+ this.enforced = false;
122
+ // Kill all MCP processes on exit
123
+ this.killAllMCPProcesses();
124
+ }
125
+ };
126
+ process.once('exit', cleanup);
127
+ process.once('SIGINT', () => {
128
+ cleanup();
129
+ process.exit(0);
130
+ });
131
+ process.once('SIGTERM', () => {
132
+ cleanup();
133
+ process.exit(0);
134
+ });
135
+ }
136
+ /**
137
+ * Check if MCP servers are healthy
138
+ */
139
+ static async checkHealth() {
140
+ const issues = [];
141
+ try {
142
+ // Check process count
143
+ const countCmd = "ps aux | grep -E 'mcp.*\\.js' | grep -v grep | wc -l";
144
+ const count = parseInt((0, child_process_1.execSync)(countCmd, { encoding: 'utf8' }).trim());
145
+ if (count === 0) {
146
+ issues.push('No MCP servers running');
147
+ }
148
+ else if (count > 15) {
149
+ issues.push(`Too many MCP servers running: ${count}`);
150
+ }
151
+ // Check memory usage
152
+ const memCmd = "ps aux | grep -E 'mcp.*\\.js' | grep -v grep | awk '{sum+=$6} END {print sum/1024}'";
153
+ const memMB = parseFloat((0, child_process_1.execSync)(memCmd, { encoding: 'utf8' }).trim() || '0');
154
+ if (memMB > 3000) {
155
+ issues.push(`High memory usage: ${memMB.toFixed(0)}MB`);
156
+ }
157
+ // Check for zombie processes
158
+ const zombieCmd = "ps aux | grep -E 'mcp.*\\.js.*<defunct>' | grep -v grep | wc -l";
159
+ const zombies = parseInt((0, child_process_1.execSync)(zombieCmd, { encoding: 'utf8' }).trim());
160
+ if (zombies > 0) {
161
+ issues.push(`Found ${zombies} zombie MCP processes`);
162
+ }
163
+ }
164
+ catch (error) {
165
+ issues.push(`Health check error: ${error.message}`);
166
+ }
167
+ return {
168
+ healthy: issues.length === 0,
169
+ issues
170
+ };
171
+ }
172
+ }
173
+ exports.MCPSingletonEnforcer = MCPSingletonEnforcer;
174
+ MCPSingletonEnforcer.enforced = false;
175
+ // Import the singleton lock class
176
+ const mcp_singleton_lock_js_2 = require("./mcp-singleton-lock.js");
177
+ //# sourceMappingURL=mcp-singleton-enforcer.js.map
@@ -0,0 +1,44 @@
1
+ /**
2
+ * MCP Timeout Fix
3
+ * Addresses timeout issues with MCP operations, especially memory_usage
4
+ * v2.10.0 - Critical fix for hanging MCP operations
5
+ */
6
+ export interface TimeoutConfig {
7
+ startup: number;
8
+ operation: number;
9
+ deployment: number;
10
+ memory: number;
11
+ global: number;
12
+ }
13
+ export declare class MCPTimeoutManager {
14
+ private static instance;
15
+ private config;
16
+ private constructor();
17
+ static getInstance(): MCPTimeoutManager;
18
+ /**
19
+ * Get timeout for specific operation type
20
+ */
21
+ getTimeout(operationType: 'startup' | 'operation' | 'deployment' | 'memory' | 'global'): number;
22
+ /**
23
+ * Execute an operation with timeout protection
24
+ */
25
+ executeWithTimeout<T>(operation: Promise<T>, timeoutMs: number, operationName: string): Promise<T>;
26
+ /**
27
+ * Create a timeout-protected wrapper for MCP operations
28
+ */
29
+ wrapMCPOperation<T>(operation: () => Promise<T>, operationType?: 'startup' | 'operation' | 'deployment' | 'memory' | 'global', customTimeout?: number): Promise<T>;
30
+ /**
31
+ * Special handling for memory operations which tend to hang
32
+ */
33
+ executeMemoryOperation<T>(operation: () => Promise<T>): Promise<T>;
34
+ /**
35
+ * Get recommended timeout settings for slow instances
36
+ */
37
+ getSlowInstanceRecommendations(): Record<string, string>;
38
+ /**
39
+ * Apply timeout override if configured
40
+ */
41
+ applyOverride(): void;
42
+ }
43
+ export declare const mcpTimeoutManager: MCPTimeoutManager;
44
+ //# sourceMappingURL=mcp-timeout-fix.d.ts.map
@@ -0,0 +1,147 @@
1
+ "use strict";
2
+ /**
3
+ * MCP Timeout Fix
4
+ * Addresses timeout issues with MCP operations, especially memory_usage
5
+ * v2.10.0 - Critical fix for hanging MCP operations
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.mcpTimeoutManager = exports.MCPTimeoutManager = void 0;
9
+ const logger_js_1 = require("./logger.js");
10
+ const logger = new logger_js_1.Logger('MCPTimeoutFix');
11
+ class MCPTimeoutManager {
12
+ constructor() {
13
+ // Load timeout values from environment with increased defaults
14
+ this.config = {
15
+ startup: parseInt(process.env.SNOW_MCP_STARTUP_TIMEOUT || '120000'), // 2 minutes
16
+ operation: parseInt(process.env.SNOW_MCP_OPERATION_TIMEOUT || '300000'), // 5 minutes
17
+ deployment: parseInt(process.env.MCP_DEPLOYMENT_TIMEOUT || '720000'), // 12 minutes
18
+ memory: parseInt(process.env.SNOW_MCP_MEMORY_TIMEOUT || '60000'), // 1 minute for memory ops
19
+ global: parseInt(process.env.SNOW_API_TIMEOUT || '180000') // 3 minutes global
20
+ };
21
+ logger.info('🕐 MCP Timeout Configuration:', {
22
+ startup: `${this.config.startup / 1000}s`,
23
+ operation: `${this.config.operation / 1000}s`,
24
+ deployment: `${this.config.deployment / 1000}s`,
25
+ memory: `${this.config.memory / 1000}s`,
26
+ global: `${this.config.global / 1000}s`
27
+ });
28
+ }
29
+ static getInstance() {
30
+ if (!this.instance) {
31
+ this.instance = new MCPTimeoutManager();
32
+ }
33
+ return this.instance;
34
+ }
35
+ /**
36
+ * Get timeout for specific operation type
37
+ */
38
+ getTimeout(operationType) {
39
+ return this.config[operationType];
40
+ }
41
+ /**
42
+ * Execute an operation with timeout protection
43
+ */
44
+ async executeWithTimeout(operation, timeoutMs, operationName) {
45
+ return new Promise((resolve, reject) => {
46
+ let timeoutHandle;
47
+ let completed = false;
48
+ // Set up timeout
49
+ timeoutHandle = setTimeout(() => {
50
+ if (!completed) {
51
+ completed = true;
52
+ logger.error(`⏱️ Operation '${operationName}' timed out after ${timeoutMs / 1000}s`);
53
+ reject(new Error(`Operation '${operationName}' timed out after ${timeoutMs / 1000} seconds`));
54
+ }
55
+ }, timeoutMs);
56
+ // Execute operation
57
+ operation
58
+ .then(result => {
59
+ if (!completed) {
60
+ completed = true;
61
+ clearTimeout(timeoutHandle);
62
+ resolve(result);
63
+ }
64
+ })
65
+ .catch(error => {
66
+ if (!completed) {
67
+ completed = true;
68
+ clearTimeout(timeoutHandle);
69
+ reject(error);
70
+ }
71
+ });
72
+ });
73
+ }
74
+ /**
75
+ * Create a timeout-protected wrapper for MCP operations
76
+ */
77
+ wrapMCPOperation(operation, operationType = 'operation', customTimeout) {
78
+ const timeout = customTimeout || this.getTimeout(operationType);
79
+ const operationName = `MCP ${operationType}`;
80
+ logger.debug(`⏱️ Starting ${operationName} with ${timeout / 1000}s timeout`);
81
+ return this.executeWithTimeout(operation(), timeout, operationName);
82
+ }
83
+ /**
84
+ * Special handling for memory operations which tend to hang
85
+ */
86
+ async executeMemoryOperation(operation) {
87
+ const maxRetries = 3;
88
+ let lastError = null;
89
+ for (let attempt = 1; attempt <= maxRetries; attempt++) {
90
+ try {
91
+ logger.debug(`🧠 Memory operation attempt ${attempt}/${maxRetries}`);
92
+ // Use shorter timeout for memory operations
93
+ const result = await this.wrapMCPOperation(operation, 'memory', this.config.memory);
94
+ logger.debug(`✅ Memory operation succeeded on attempt ${attempt}`);
95
+ return result;
96
+ }
97
+ catch (error) {
98
+ lastError = error;
99
+ logger.warn(`⚠️ Memory operation attempt ${attempt} failed:`, error.message);
100
+ if (attempt < maxRetries) {
101
+ // Wait before retrying
102
+ const delay = attempt * 1000; // Progressive delay
103
+ logger.debug(`⏳ Waiting ${delay}ms before retry...`);
104
+ await new Promise(resolve => setTimeout(resolve, delay));
105
+ }
106
+ }
107
+ }
108
+ throw new Error(`Memory operation failed after ${maxRetries} attempts: ${lastError?.message}`);
109
+ }
110
+ /**
111
+ * Get recommended timeout settings for slow instances
112
+ */
113
+ getSlowInstanceRecommendations() {
114
+ return {
115
+ SNOW_API_TIMEOUT: '300000', // 5 minutes
116
+ SNOW_MCP_STARTUP_TIMEOUT: '180000', // 3 minutes
117
+ SNOW_MCP_OPERATION_TIMEOUT: '600000', // 10 minutes
118
+ MCP_DEPLOYMENT_TIMEOUT: '900000', // 15 minutes
119
+ SNOW_MCP_MEMORY_TIMEOUT: '120000', // 2 minutes
120
+ SNOW_MAX_CONCURRENT_REQUESTS: '5',
121
+ SNOW_BATCH_DELAY: '500'
122
+ };
123
+ }
124
+ /**
125
+ * Apply timeout override if configured
126
+ */
127
+ applyOverride() {
128
+ const override = process.env.SNOW_TIMEOUT_OVERRIDE;
129
+ if (override) {
130
+ const overrideMs = parseInt(override);
131
+ if (!isNaN(overrideMs)) {
132
+ logger.warn(`⚠️ Applying global timeout override: ${overrideMs / 1000}s`);
133
+ this.config = {
134
+ startup: overrideMs,
135
+ operation: overrideMs,
136
+ deployment: overrideMs,
137
+ memory: Math.min(overrideMs, 120000), // Cap memory ops at 2 minutes
138
+ global: overrideMs
139
+ };
140
+ }
141
+ }
142
+ }
143
+ }
144
+ exports.MCPTimeoutManager = MCPTimeoutManager;
145
+ // Export singleton instance
146
+ exports.mcpTimeoutManager = MCPTimeoutManager.getInstance();
147
+ //# sourceMappingURL=mcp-timeout-fix.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "snow-flow",
3
- "version": "2.9.9",
3
+ "version": "2.10.0",
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",