snow-flow 2.9.0 โ†’ 2.9.4

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.
@@ -0,0 +1,69 @@
1
+ /**
2
+ * MCP On-Demand Manager
3
+ * Starts MCP servers only when needed and stops them after inactivity
4
+ */
5
+ import { ChildProcess } from 'child_process';
6
+ export declare class MCPOnDemandManager {
7
+ private static instance;
8
+ private servers;
9
+ private inactivityTimeout;
10
+ private cleanupInterval?;
11
+ private constructor();
12
+ static getInstance(): MCPOnDemandManager;
13
+ /**
14
+ * Get or start an MCP server on demand
15
+ */
16
+ getServer(serverName: string): Promise<ChildProcess>;
17
+ /**
18
+ * Start an MCP server
19
+ */
20
+ private startServer;
21
+ /**
22
+ * Wait for a server to finish starting
23
+ */
24
+ private waitForServer;
25
+ /**
26
+ * Stop a specific server
27
+ */
28
+ stopServer(serverName: string): Promise<void>;
29
+ /**
30
+ * Stop least recently used servers to free resources
31
+ */
32
+ private stopLeastRecentlyUsed;
33
+ /**
34
+ * Stop all inactive servers
35
+ */
36
+ private stopInactiveServers;
37
+ /**
38
+ * Start monitoring for inactive servers
39
+ */
40
+ private startInactivityMonitor;
41
+ /**
42
+ * Stop the inactivity monitor
43
+ */
44
+ stopInactivityMonitor(): void;
45
+ /**
46
+ * Get the script path for a server
47
+ */
48
+ private getScriptPath;
49
+ /**
50
+ * Get status of all servers
51
+ */
52
+ getStatus(): {
53
+ total: number;
54
+ running: number;
55
+ stopped: number;
56
+ servers: Array<{
57
+ name: string;
58
+ status: string;
59
+ lastUsed: string;
60
+ useCount: number;
61
+ uptime?: string;
62
+ }>;
63
+ };
64
+ /**
65
+ * Stop all servers
66
+ */
67
+ stopAll(): Promise<void>;
68
+ }
69
+ //# sourceMappingURL=mcp-on-demand-manager.d.ts.map
@@ -0,0 +1,309 @@
1
+ "use strict";
2
+ /**
3
+ * MCP On-Demand Manager
4
+ * Starts MCP servers only when needed and stops them after inactivity
5
+ */
6
+ var __importDefault = (this && this.__importDefault) || function (mod) {
7
+ return (mod && mod.__esModule) ? mod : { "default": mod };
8
+ };
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.MCPOnDemandManager = void 0;
11
+ const child_process_1 = require("child_process");
12
+ const logger_js_1 = require("./logger.js");
13
+ const mcp_process_manager_js_1 = require("./mcp-process-manager.js");
14
+ const unified_auth_store_js_1 = require("./unified-auth-store.js");
15
+ const path_1 = __importDefault(require("path"));
16
+ const fs_1 = __importDefault(require("fs"));
17
+ const logger = new logger_js_1.Logger('MCPOnDemand');
18
+ class MCPOnDemandManager {
19
+ constructor() {
20
+ this.servers = new Map();
21
+ this.inactivityTimeout = parseInt(process.env.SNOW_MCP_INACTIVITY_TIMEOUT || '300000'); // 5 minutes default
22
+ this.startInactivityMonitor();
23
+ }
24
+ static getInstance() {
25
+ if (!MCPOnDemandManager.instance) {
26
+ MCPOnDemandManager.instance = new MCPOnDemandManager();
27
+ }
28
+ return MCPOnDemandManager.instance;
29
+ }
30
+ /**
31
+ * Get or start an MCP server on demand
32
+ */
33
+ async getServer(serverName) {
34
+ let server = this.servers.get(serverName);
35
+ if (!server) {
36
+ server = {
37
+ name: serverName,
38
+ lastUsed: Date.now(),
39
+ useCount: 0,
40
+ status: 'stopped'
41
+ };
42
+ this.servers.set(serverName, server);
43
+ }
44
+ // Update last used time
45
+ server.lastUsed = Date.now();
46
+ server.useCount++;
47
+ // If server is running, return it
48
+ if (server.status === 'running' && server.process) {
49
+ logger.debug(`โœ… Reusing existing ${serverName} (used ${server.useCount} times)`);
50
+ return server.process;
51
+ }
52
+ // If server is starting, wait for it
53
+ if (server.status === 'starting') {
54
+ logger.debug(`โณ Waiting for ${serverName} to start...`);
55
+ return this.waitForServer(serverName);
56
+ }
57
+ // Start the server
58
+ return this.startServer(serverName);
59
+ }
60
+ /**
61
+ * Start an MCP server
62
+ */
63
+ async startServer(serverName) {
64
+ const server = this.servers.get(serverName);
65
+ if (!server) {
66
+ throw new Error(`Server ${serverName} not found`);
67
+ }
68
+ // Check resource limits
69
+ const processManager = mcp_process_manager_js_1.MCPProcessManager.getInstance();
70
+ if (!processManager.canSpawnServer()) {
71
+ // Try to free up resources by stopping least recently used servers
72
+ await this.stopLeastRecentlyUsed();
73
+ if (!processManager.canSpawnServer()) {
74
+ throw new Error('Cannot start server: resource limits exceeded');
75
+ }
76
+ }
77
+ server.status = 'starting';
78
+ logger.info(`๐Ÿš€ Starting ${serverName} on demand...`);
79
+ try {
80
+ // Get the script path
81
+ const scriptPath = this.getScriptPath(serverName);
82
+ // Get auth tokens
83
+ await unified_auth_store_js_1.unifiedAuthStore.bridgeToMCP();
84
+ const tokens = await unified_auth_store_js_1.unifiedAuthStore.getTokens();
85
+ const authEnv = {};
86
+ if (tokens) {
87
+ authEnv.SNOW_OAUTH_TOKENS = JSON.stringify(tokens);
88
+ authEnv.SNOW_INSTANCE = tokens.instance;
89
+ authEnv.SNOW_CLIENT_ID = tokens.clientId;
90
+ authEnv.SNOW_CLIENT_SECRET = tokens.clientSecret;
91
+ if (tokens.accessToken) {
92
+ authEnv.SNOW_ACCESS_TOKEN = tokens.accessToken;
93
+ }
94
+ if (tokens.refreshToken) {
95
+ authEnv.SNOW_REFRESH_TOKEN = tokens.refreshToken;
96
+ }
97
+ }
98
+ // Start the process
99
+ const childProcess = (0, child_process_1.spawn)('node', [scriptPath], {
100
+ stdio: ['pipe', 'pipe', 'pipe'],
101
+ env: {
102
+ ...process.env,
103
+ ...authEnv,
104
+ SNOW_MCP_ON_DEMAND: 'true' // Flag to indicate on-demand mode
105
+ }
106
+ });
107
+ // Handle process events
108
+ childProcess.on('error', (error) => {
109
+ logger.error(`${serverName} error:`, error);
110
+ server.status = 'stopped';
111
+ });
112
+ childProcess.on('exit', (code) => {
113
+ logger.info(`${serverName} exited with code ${code}`);
114
+ server.status = 'stopped';
115
+ server.process = undefined;
116
+ });
117
+ // Log output for debugging
118
+ childProcess.stdout?.on('data', (data) => {
119
+ logger.debug(`${serverName} stdout:`, data.toString());
120
+ });
121
+ childProcess.stderr?.on('data', (data) => {
122
+ logger.debug(`${serverName} stderr:`, data.toString());
123
+ });
124
+ server.process = childProcess;
125
+ server.status = 'running';
126
+ server.startTime = Date.now();
127
+ logger.info(`โœ… ${serverName} started (PID: ${childProcess.pid})`);
128
+ return childProcess;
129
+ }
130
+ catch (error) {
131
+ server.status = 'stopped';
132
+ throw error;
133
+ }
134
+ }
135
+ /**
136
+ * Wait for a server to finish starting
137
+ */
138
+ async waitForServer(serverName, timeout = 30000) {
139
+ const startTime = Date.now();
140
+ while (Date.now() - startTime < timeout) {
141
+ const server = this.servers.get(serverName);
142
+ if (server?.status === 'running' && server.process) {
143
+ return server.process;
144
+ }
145
+ if (server?.status === 'stopped') {
146
+ throw new Error(`Server ${serverName} failed to start`);
147
+ }
148
+ await new Promise(resolve => setTimeout(resolve, 100));
149
+ }
150
+ throw new Error(`Timeout waiting for ${serverName} to start`);
151
+ }
152
+ /**
153
+ * Stop a specific server
154
+ */
155
+ async stopServer(serverName) {
156
+ const server = this.servers.get(serverName);
157
+ if (!server || !server.process) {
158
+ return;
159
+ }
160
+ server.status = 'stopping';
161
+ logger.info(`๐Ÿ›‘ Stopping ${serverName} (was used ${server.useCount} times)`);
162
+ try {
163
+ server.process.kill('SIGTERM');
164
+ // Wait for graceful shutdown
165
+ await new Promise((resolve) => {
166
+ const timeout = setTimeout(() => {
167
+ if (server.process) {
168
+ server.process.kill('SIGKILL');
169
+ }
170
+ resolve(undefined);
171
+ }, 5000);
172
+ server.process?.once('exit', () => {
173
+ clearTimeout(timeout);
174
+ resolve(undefined);
175
+ });
176
+ });
177
+ }
178
+ catch (error) {
179
+ logger.error(`Error stopping ${serverName}:`, error);
180
+ }
181
+ server.status = 'stopped';
182
+ server.process = undefined;
183
+ server.startTime = undefined;
184
+ }
185
+ /**
186
+ * Stop least recently used servers to free resources
187
+ */
188
+ async stopLeastRecentlyUsed() {
189
+ const runningServers = Array.from(this.servers.values())
190
+ .filter(s => s.status === 'running')
191
+ .sort((a, b) => a.lastUsed - b.lastUsed);
192
+ if (runningServers.length > 0) {
193
+ const oldest = runningServers[0];
194
+ logger.info(`๐Ÿ“ฆ Stopping least recently used server: ${oldest.name}`);
195
+ await this.stopServer(oldest.name);
196
+ }
197
+ }
198
+ /**
199
+ * Stop all inactive servers
200
+ */
201
+ async stopInactiveServers() {
202
+ const now = Date.now();
203
+ const promises = [];
204
+ for (const [name, server] of this.servers) {
205
+ if (server.status === 'running' &&
206
+ now - server.lastUsed > this.inactivityTimeout) {
207
+ const inactiveMinutes = Math.round((now - server.lastUsed) / 60000);
208
+ logger.info(`โฐ Stopping ${name} due to inactivity (${inactiveMinutes} minutes)`);
209
+ promises.push(this.stopServer(name));
210
+ }
211
+ }
212
+ await Promise.all(promises);
213
+ }
214
+ /**
215
+ * Start monitoring for inactive servers
216
+ */
217
+ startInactivityMonitor() {
218
+ // Check every minute
219
+ this.cleanupInterval = setInterval(() => {
220
+ this.stopInactiveServers().catch(error => {
221
+ logger.error('Error during inactivity cleanup:', error);
222
+ });
223
+ }, 60000);
224
+ // Don't block process exit
225
+ this.cleanupInterval.unref();
226
+ }
227
+ /**
228
+ * Stop the inactivity monitor
229
+ */
230
+ stopInactivityMonitor() {
231
+ if (this.cleanupInterval) {
232
+ clearInterval(this.cleanupInterval);
233
+ this.cleanupInterval = undefined;
234
+ }
235
+ }
236
+ /**
237
+ * Get the script path for a server
238
+ */
239
+ getScriptPath(serverName) {
240
+ // Map server names to script files
241
+ const serverMap = {
242
+ 'servicenow-operations': 'servicenow-operations-mcp.js',
243
+ 'servicenow-deployment': 'servicenow-deployment-mcp.js',
244
+ 'servicenow-machine-learning': 'servicenow-machine-learning-mcp.js',
245
+ 'servicenow-update-set': 'servicenow-update-set-mcp.js',
246
+ 'servicenow-platform-development': 'servicenow-platform-development-mcp.js',
247
+ 'servicenow-integration': 'servicenow-integration-mcp.js',
248
+ 'servicenow-automation': 'servicenow-automation-mcp.js',
249
+ 'servicenow-security-compliance': 'servicenow-security-compliance-mcp.js',
250
+ 'servicenow-reporting-analytics': 'servicenow-reporting-analytics-mcp.js',
251
+ 'servicenow-flow-composer': 'servicenow-flow-composer-mcp.js',
252
+ 'servicenow-intelligent': 'servicenow-intelligent-mcp.js',
253
+ 'servicenow-development-assistant': 'servicenow-development-assistant-mcp.js',
254
+ 'servicenow-graph-memory': 'servicenow-graph-memory-mcp.js',
255
+ 'snow-flow': 'snow-flow-mcp.js'
256
+ };
257
+ const scriptFile = serverMap[serverName];
258
+ if (!scriptFile) {
259
+ throw new Error(`Unknown server: ${serverName}`);
260
+ }
261
+ // Check different possible locations
262
+ const possiblePaths = [
263
+ path_1.default.join(__dirname, '..', 'mcp', scriptFile),
264
+ path_1.default.join(process.cwd(), 'dist', 'mcp', scriptFile),
265
+ path_1.default.join('/Users/nielsvanderwerf/.nvm/versions/node/v20.15.0/lib/node_modules/snow-flow/dist/mcp', scriptFile)
266
+ ];
267
+ for (const scriptPath of possiblePaths) {
268
+ if (fs_1.default.existsSync(scriptPath)) {
269
+ return scriptPath;
270
+ }
271
+ }
272
+ throw new Error(`Script not found for ${serverName}: ${scriptFile}`);
273
+ }
274
+ /**
275
+ * Get status of all servers
276
+ */
277
+ getStatus() {
278
+ const servers = Array.from(this.servers.values()).map(server => {
279
+ const lastUsedMinutes = Math.round((Date.now() - server.lastUsed) / 60000);
280
+ const uptime = server.startTime ?
281
+ Math.round((Date.now() - server.startTime) / 60000) + ' minutes' :
282
+ undefined;
283
+ return {
284
+ name: server.name,
285
+ status: server.status,
286
+ lastUsed: `${lastUsedMinutes} minutes ago`,
287
+ useCount: server.useCount,
288
+ uptime
289
+ };
290
+ });
291
+ return {
292
+ total: servers.length,
293
+ running: servers.filter(s => s.status === 'running').length,
294
+ stopped: servers.filter(s => s.status === 'stopped').length,
295
+ servers
296
+ };
297
+ }
298
+ /**
299
+ * Stop all servers
300
+ */
301
+ async stopAll() {
302
+ logger.info('๐Ÿ›‘ Stopping all MCP servers...');
303
+ const promises = Array.from(this.servers.keys()).map(name => this.stopServer(name));
304
+ await Promise.all(promises);
305
+ this.stopInactivityMonitor();
306
+ }
307
+ }
308
+ exports.MCPOnDemandManager = MCPOnDemandManager;
309
+ //# sourceMappingURL=mcp-on-demand-manager.js.map
@@ -0,0 +1,58 @@
1
+ /**
2
+ * MCP Process Manager
3
+ * Prevents excessive MCP server spawning and manages resource limits
4
+ */
5
+ export declare class MCPProcessManager {
6
+ private static instance;
7
+ private readonly MAX_MCP_SERVERS;
8
+ private readonly MAX_MEMORY_MB;
9
+ private readonly CLEANUP_INTERVAL;
10
+ private cleanupTimer?;
11
+ private constructor();
12
+ static getInstance(): MCPProcessManager;
13
+ /**
14
+ * Check if we can spawn a new MCP server
15
+ */
16
+ canSpawnServer(): boolean;
17
+ /**
18
+ * Get current MCP system status
19
+ */
20
+ getSystemStatus(): {
21
+ processCount: number;
22
+ memoryUsageMB: number;
23
+ processes: Array<{
24
+ pid: number;
25
+ memory: number;
26
+ name: string;
27
+ }>;
28
+ };
29
+ /**
30
+ * Kill duplicate MCP servers (keep only the newest)
31
+ */
32
+ killDuplicates(): void;
33
+ /**
34
+ * Kill all MCP servers
35
+ */
36
+ killAll(): void;
37
+ /**
38
+ * Clean up excessive resources
39
+ */
40
+ cleanup(): void;
41
+ /**
42
+ * Start periodic cleanup
43
+ */
44
+ private startPeriodicCleanup;
45
+ /**
46
+ * Stop periodic cleanup
47
+ */
48
+ stopPeriodicCleanup(): void;
49
+ /**
50
+ * Get resource usage summary
51
+ */
52
+ getResourceSummary(): string;
53
+ /**
54
+ * Get health status
55
+ */
56
+ getHealthStatus(): 'healthy' | 'warning' | 'critical';
57
+ }
58
+ //# sourceMappingURL=mcp-process-manager.d.ts.map
@@ -0,0 +1,220 @@
1
+ "use strict";
2
+ /**
3
+ * MCP Process Manager
4
+ * Prevents excessive MCP server spawning and manages resource limits
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.MCPProcessManager = void 0;
8
+ const child_process_1 = require("child_process");
9
+ const logger_js_1 = require("./logger.js");
10
+ const logger = new logger_js_1.Logger('MCPProcessManager');
11
+ class MCPProcessManager {
12
+ constructor() {
13
+ this.MAX_MCP_SERVERS = parseInt(process.env.SNOW_MAX_MCP_SERVERS || '10');
14
+ this.MAX_MEMORY_MB = parseInt(process.env.SNOW_MCP_MEMORY_LIMIT || '1500');
15
+ this.CLEANUP_INTERVAL = 60000; // 1 minute
16
+ // Start periodic cleanup
17
+ this.startPeriodicCleanup();
18
+ }
19
+ static getInstance() {
20
+ if (!MCPProcessManager.instance) {
21
+ MCPProcessManager.instance = new MCPProcessManager();
22
+ }
23
+ return MCPProcessManager.instance;
24
+ }
25
+ /**
26
+ * Check if we can spawn a new MCP server
27
+ */
28
+ canSpawnServer() {
29
+ const status = this.getSystemStatus();
30
+ if (status.processCount >= this.MAX_MCP_SERVERS) {
31
+ logger.warn(`โŒ Cannot spawn: Already at max servers (${status.processCount}/${this.MAX_MCP_SERVERS})`);
32
+ return false;
33
+ }
34
+ if (status.memoryUsageMB > this.MAX_MEMORY_MB) {
35
+ logger.warn(`โŒ Cannot spawn: Memory limit exceeded (${status.memoryUsageMB}MB > ${this.MAX_MEMORY_MB}MB)`);
36
+ return false;
37
+ }
38
+ return true;
39
+ }
40
+ /**
41
+ * Get current MCP system status
42
+ */
43
+ getSystemStatus() {
44
+ try {
45
+ // Count MCP processes
46
+ const psOutput = (0, child_process_1.execSync)('ps aux | grep -E "mcp|servicenow.*mcp" | grep -v grep', {
47
+ encoding: 'utf8'
48
+ }).trim();
49
+ if (!psOutput) {
50
+ return {
51
+ processCount: 0,
52
+ memoryUsageMB: 0,
53
+ processes: []
54
+ };
55
+ }
56
+ const lines = psOutput.split('\n');
57
+ const processes = [];
58
+ let totalMemory = 0;
59
+ for (const line of lines) {
60
+ const parts = line.split(/\s+/);
61
+ if (parts.length > 10) {
62
+ const pid = parseInt(parts[1]);
63
+ const memory = Math.round(parseInt(parts[5]) / 1024); // Convert KB to MB
64
+ const name = parts.slice(10).join(' ');
65
+ processes.push({ pid, memory, name });
66
+ totalMemory += memory;
67
+ }
68
+ }
69
+ return {
70
+ processCount: processes.length,
71
+ memoryUsageMB: totalMemory,
72
+ processes
73
+ };
74
+ }
75
+ catch (error) {
76
+ // No MCP processes found
77
+ return {
78
+ processCount: 0,
79
+ memoryUsageMB: 0,
80
+ processes: []
81
+ };
82
+ }
83
+ }
84
+ /**
85
+ * Kill duplicate MCP servers (keep only the newest)
86
+ */
87
+ killDuplicates() {
88
+ const status = this.getSystemStatus();
89
+ // Group processes by server type
90
+ const serverGroups = new Map();
91
+ for (const proc of status.processes) {
92
+ // Extract server type from process name
93
+ const match = proc.name.match(/servicenow-([^-]+)-mcp\.js/);
94
+ if (match) {
95
+ const serverType = match[1];
96
+ if (!serverGroups.has(serverType)) {
97
+ serverGroups.set(serverType, []);
98
+ }
99
+ serverGroups.get(serverType).push({
100
+ pid: proc.pid,
101
+ memory: proc.memory
102
+ });
103
+ }
104
+ }
105
+ // Kill duplicates (keep the first one)
106
+ for (const [serverType, procs] of serverGroups) {
107
+ if (procs.length > 1) {
108
+ logger.warn(`Found ${procs.length} instances of ${serverType}-mcp, killing duplicates...`);
109
+ // Sort by PID (older PIDs first) and keep the first one
110
+ procs.sort((a, b) => a.pid - b.pid);
111
+ for (let i = 1; i < procs.length; i++) {
112
+ try {
113
+ process.kill(procs[i].pid, 'SIGTERM');
114
+ logger.info(`Killed duplicate ${serverType}-mcp (PID: ${procs[i].pid})`);
115
+ }
116
+ catch (error) {
117
+ // Process might already be dead
118
+ }
119
+ }
120
+ }
121
+ }
122
+ }
123
+ /**
124
+ * Kill all MCP servers
125
+ */
126
+ killAll() {
127
+ try {
128
+ (0, child_process_1.execSync)('pkill -f mcp', { encoding: 'utf8' });
129
+ logger.info('โœ… Killed all MCP processes');
130
+ }
131
+ catch (error) {
132
+ // pkill returns non-zero if no processes found
133
+ }
134
+ }
135
+ /**
136
+ * Clean up excessive resources
137
+ */
138
+ cleanup() {
139
+ const status = this.getSystemStatus();
140
+ if (status.processCount > this.MAX_MCP_SERVERS) {
141
+ logger.warn(`๐Ÿงน Cleaning up excessive MCP servers (${status.processCount} > ${this.MAX_MCP_SERVERS})`);
142
+ this.killDuplicates();
143
+ }
144
+ if (status.memoryUsageMB > this.MAX_MEMORY_MB) {
145
+ logger.warn(`๐Ÿงน Memory usage too high (${status.memoryUsageMB}MB), killing oldest processes...`);
146
+ // Sort by memory usage and kill the highest consumers
147
+ const sorted = status.processes.sort((a, b) => b.memory - a.memory);
148
+ let memoryFreed = 0;
149
+ for (const proc of sorted) {
150
+ if (status.memoryUsageMB - memoryFreed <= this.MAX_MEMORY_MB * 0.8) {
151
+ break; // Stop when we're at 80% of limit
152
+ }
153
+ try {
154
+ process.kill(proc.pid, 'SIGTERM');
155
+ memoryFreed += proc.memory;
156
+ logger.info(`Killed high-memory process (PID: ${proc.pid}, ${proc.memory}MB)`);
157
+ }
158
+ catch (error) {
159
+ // Process might already be dead
160
+ }
161
+ }
162
+ }
163
+ }
164
+ /**
165
+ * Start periodic cleanup
166
+ */
167
+ startPeriodicCleanup() {
168
+ // Clear existing timer
169
+ if (this.cleanupTimer) {
170
+ clearInterval(this.cleanupTimer);
171
+ }
172
+ // Run cleanup periodically
173
+ this.cleanupTimer = setInterval(() => {
174
+ const status = this.getSystemStatus();
175
+ if (status.processCount > this.MAX_MCP_SERVERS * 0.8 ||
176
+ status.memoryUsageMB > this.MAX_MEMORY_MB * 0.8) {
177
+ logger.info('๐Ÿ”„ Running periodic MCP cleanup...');
178
+ this.cleanup();
179
+ }
180
+ }, this.CLEANUP_INTERVAL);
181
+ // Don't block process exit
182
+ this.cleanupTimer.unref();
183
+ }
184
+ /**
185
+ * Stop periodic cleanup
186
+ */
187
+ stopPeriodicCleanup() {
188
+ if (this.cleanupTimer) {
189
+ clearInterval(this.cleanupTimer);
190
+ this.cleanupTimer = undefined;
191
+ }
192
+ }
193
+ /**
194
+ * Get resource usage summary
195
+ */
196
+ getResourceSummary() {
197
+ const status = this.getSystemStatus();
198
+ return `MCP Resources:
199
+ Processes: ${status.processCount}/${this.MAX_MCP_SERVERS} (${Math.round(status.processCount / this.MAX_MCP_SERVERS * 100)}%)
200
+ Memory: ${status.memoryUsageMB}MB/${this.MAX_MEMORY_MB}MB (${Math.round(status.memoryUsageMB / this.MAX_MEMORY_MB * 100)}%)
201
+ Status: ${this.getHealthStatus()}`;
202
+ }
203
+ /**
204
+ * Get health status
205
+ */
206
+ getHealthStatus() {
207
+ const status = this.getSystemStatus();
208
+ const processPercent = status.processCount / this.MAX_MCP_SERVERS;
209
+ const memoryPercent = status.memoryUsageMB / this.MAX_MEMORY_MB;
210
+ if (processPercent > 0.9 || memoryPercent > 0.9) {
211
+ return 'critical';
212
+ }
213
+ if (processPercent > 0.7 || memoryPercent > 0.7) {
214
+ return 'warning';
215
+ }
216
+ return 'healthy';
217
+ }
218
+ }
219
+ exports.MCPProcessManager = MCPProcessManager;
220
+ //# sourceMappingURL=mcp-process-manager.js.map