snow-flow 2.9.0 → 2.9.5

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,43 @@
1
+ /**
2
+ * Deployment Authentication Fix
3
+ * Ensures OAuth tokens are properly refreshed and validated before deployment operations
4
+ */
5
+ export interface AuthValidationResult {
6
+ isValid: boolean;
7
+ hasWriteScope: boolean;
8
+ tokenAge?: number;
9
+ expiresIn?: number;
10
+ error?: string;
11
+ recommendations?: string[];
12
+ }
13
+ export declare class DeploymentAuthManager {
14
+ private oauth;
15
+ private lastTokenRefresh;
16
+ constructor();
17
+ /**
18
+ * Ensure we have valid tokens for deployment operations
19
+ * This is MORE strict than regular authentication
20
+ */
21
+ ensureDeploymentAuth(): Promise<AuthValidationResult>;
22
+ /**
23
+ * Validate token by making a simple API call
24
+ */
25
+ private validateTokenWithAPI;
26
+ /**
27
+ * Check if token has write permissions by attempting to read widget table
28
+ */
29
+ private checkWritePermissions;
30
+ /**
31
+ * Force a fresh token for deployment operations
32
+ */
33
+ forceTokenRefresh(): Promise<{
34
+ success: boolean;
35
+ accessToken?: string;
36
+ error?: string;
37
+ }>;
38
+ /**
39
+ * Get fresh access token for deployment
40
+ */
41
+ getDeploymentToken(): Promise<string | null>;
42
+ }
43
+ //# sourceMappingURL=deployment-auth-fix.d.ts.map
@@ -0,0 +1,272 @@
1
+ "use strict";
2
+ /**
3
+ * Deployment Authentication Fix
4
+ * Ensures OAuth tokens are properly refreshed and validated before deployment operations
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.DeploymentAuthManager = void 0;
8
+ const snow_oauth_js_1 = require("./snow-oauth.js");
9
+ const unified_auth_store_js_1 = require("./unified-auth-store.js");
10
+ const logger_js_1 = require("./logger.js");
11
+ const logger = new logger_js_1.Logger('DeploymentAuthFix');
12
+ class DeploymentAuthManager {
13
+ constructor() {
14
+ this.lastTokenRefresh = 0;
15
+ this.oauth = new snow_oauth_js_1.ServiceNowOAuth();
16
+ }
17
+ /**
18
+ * Ensure we have valid tokens for deployment operations
19
+ * This is MORE strict than regular authentication
20
+ */
21
+ async ensureDeploymentAuth() {
22
+ try {
23
+ logger.info('🔐 Validating deployment authentication...');
24
+ // Step 1: Check if we have any auth at all
25
+ const isAuth = await this.oauth.isAuthenticated();
26
+ if (!isAuth) {
27
+ return {
28
+ isValid: false,
29
+ hasWriteScope: false,
30
+ error: 'Not authenticated',
31
+ recommendations: [
32
+ 'Run: snow-flow auth login',
33
+ 'Ensure OAuth app has write/admin scopes'
34
+ ]
35
+ };
36
+ }
37
+ // Step 2: Get current tokens
38
+ let tokens = await this.oauth.loadTokens();
39
+ if (!tokens || !tokens.accessToken) {
40
+ // Try unified auth store as fallback
41
+ tokens = await unified_auth_store_js_1.unifiedAuthStore.getTokens();
42
+ if (!tokens || !tokens.accessToken) {
43
+ return {
44
+ isValid: false,
45
+ hasWriteScope: false,
46
+ error: 'No access token found',
47
+ recommendations: [
48
+ 'Run: snow-flow auth login',
49
+ 'Check .env configuration'
50
+ ]
51
+ };
52
+ }
53
+ }
54
+ // Step 3: Check token age and expiry
55
+ const now = Date.now();
56
+ const tokenAge = tokens.issuedAt ? now - tokens.issuedAt : null;
57
+ const expiresIn = tokens.expiresAt ? tokens.expiresAt - now : null;
58
+ // If token expires in less than 5 minutes, refresh it
59
+ if (expiresIn && expiresIn < 300000) { // 5 minutes
60
+ logger.info('⚠️ Token expires soon, refreshing...');
61
+ try {
62
+ const refreshResult = await this.oauth.refreshAccessToken();
63
+ if (refreshResult.success && refreshResult.accessToken) {
64
+ logger.info('✅ Token refreshed successfully');
65
+ tokens = {
66
+ ...tokens,
67
+ accessToken: refreshResult.accessToken,
68
+ expiresAt: refreshResult.expiresIn ? now + refreshResult.expiresIn * 1000 : undefined,
69
+ issuedAt: now
70
+ };
71
+ // Update unified auth store
72
+ await unified_auth_store_js_1.unifiedAuthStore.saveTokens(tokens);
73
+ }
74
+ else {
75
+ logger.warn('Failed to refresh token:', refreshResult.error);
76
+ }
77
+ }
78
+ catch (error) {
79
+ logger.error('Token refresh error:', error);
80
+ }
81
+ }
82
+ // Step 4: Validate token by making a test API call
83
+ try {
84
+ const testResponse = await this.validateTokenWithAPI(tokens.accessToken);
85
+ if (!testResponse.success) {
86
+ // Token is invalid, try to refresh
87
+ logger.warn('Token validation failed, attempting refresh...');
88
+ const refreshResult = await this.oauth.refreshAccessToken();
89
+ if (refreshResult.success && refreshResult.accessToken) {
90
+ tokens.accessToken = refreshResult.accessToken;
91
+ await unified_auth_store_js_1.unifiedAuthStore.saveTokens(tokens);
92
+ // Validate again
93
+ const retryResponse = await this.validateTokenWithAPI(tokens.accessToken);
94
+ if (!retryResponse.success) {
95
+ return {
96
+ isValid: false,
97
+ hasWriteScope: false,
98
+ error: 'Token validation failed after refresh',
99
+ recommendations: [
100
+ 'Run: snow-flow auth login',
101
+ 'Check ServiceNow OAuth app configuration',
102
+ 'Verify API access is enabled for your user'
103
+ ]
104
+ };
105
+ }
106
+ }
107
+ else {
108
+ return {
109
+ isValid: false,
110
+ hasWriteScope: false,
111
+ error: 'Failed to refresh invalid token',
112
+ recommendations: [
113
+ 'Run: snow-flow auth login',
114
+ 'Your session may have expired'
115
+ ]
116
+ };
117
+ }
118
+ }
119
+ }
120
+ catch (error) {
121
+ logger.error('Token validation error:', error);
122
+ return {
123
+ isValid: false,
124
+ hasWriteScope: false,
125
+ error: `Token validation failed: ${error.message}`,
126
+ recommendations: [
127
+ 'Check network connectivity',
128
+ 'Verify ServiceNow instance is accessible',
129
+ 'Run: snow-flow auth login'
130
+ ]
131
+ };
132
+ }
133
+ // Step 5: Check for write permissions
134
+ const hasWriteScope = await this.checkWritePermissions(tokens.accessToken);
135
+ return {
136
+ isValid: true,
137
+ hasWriteScope,
138
+ tokenAge: tokenAge ? Math.round(tokenAge / 1000) : undefined,
139
+ expiresIn: expiresIn ? Math.round(expiresIn / 1000) : undefined,
140
+ recommendations: hasWriteScope ? [] : [
141
+ 'OAuth token is valid but may lack write permissions',
142
+ 'Check OAuth app scopes in ServiceNow',
143
+ 'Ensure user has sp_admin or admin role'
144
+ ]
145
+ };
146
+ }
147
+ catch (error) {
148
+ logger.error('Deployment auth validation error:', error);
149
+ return {
150
+ isValid: false,
151
+ hasWriteScope: false,
152
+ error: error.message,
153
+ recommendations: [
154
+ 'Unexpected error during authentication',
155
+ 'Run: snow-flow auth login',
156
+ 'Check error logs for details'
157
+ ]
158
+ };
159
+ }
160
+ }
161
+ /**
162
+ * Validate token by making a simple API call
163
+ */
164
+ async validateTokenWithAPI(accessToken) {
165
+ try {
166
+ const axios = require('axios');
167
+ const credentials = await this.oauth.loadCredentials();
168
+ if (!credentials?.instance) {
169
+ return { success: false, error: 'No instance configured' };
170
+ }
171
+ const response = await axios.get(`https://${credentials.instance}/api/now/table/sys_user?sysparm_limit=1`, {
172
+ headers: {
173
+ 'Authorization': `Bearer ${accessToken}`,
174
+ 'Accept': 'application/json'
175
+ },
176
+ timeout: 10000
177
+ });
178
+ return { success: response.status === 200 };
179
+ }
180
+ catch (error) {
181
+ if (error.response?.status === 401) {
182
+ return { success: false, error: 'Token is invalid or expired' };
183
+ }
184
+ return { success: false, error: error.message };
185
+ }
186
+ }
187
+ /**
188
+ * Check if token has write permissions by attempting to read widget table
189
+ */
190
+ async checkWritePermissions(accessToken) {
191
+ try {
192
+ const axios = require('axios');
193
+ const credentials = await this.oauth.loadCredentials();
194
+ if (!credentials?.instance) {
195
+ return false;
196
+ }
197
+ // Try to read from sp_widget table (requires portal access)
198
+ const response = await axios.get(`https://${credentials.instance}/api/now/table/sp_widget?sysparm_limit=1`, {
199
+ headers: {
200
+ 'Authorization': `Bearer ${accessToken}`,
201
+ 'Accept': 'application/json'
202
+ },
203
+ timeout: 10000
204
+ });
205
+ // If we can read widgets, we likely have portal access
206
+ return response.status === 200;
207
+ }
208
+ catch (error) {
209
+ // 403 means we don't have permission
210
+ if (error.response?.status === 403) {
211
+ logger.warn('No write permissions for Service Portal');
212
+ return false;
213
+ }
214
+ // Other errors we'll assume no permission
215
+ return false;
216
+ }
217
+ }
218
+ /**
219
+ * Force a fresh token for deployment operations
220
+ */
221
+ async forceTokenRefresh() {
222
+ try {
223
+ logger.info('🔄 Forcing token refresh for deployment...');
224
+ const refreshResult = await this.oauth.refreshAccessToken();
225
+ if (refreshResult.success && refreshResult.accessToken) {
226
+ // Store in unified auth store
227
+ const tokens = await this.oauth.loadTokens();
228
+ if (tokens) {
229
+ tokens.accessToken = refreshResult.accessToken;
230
+ tokens.expiresAt = refreshResult.expiresIn ? Date.now() + refreshResult.expiresIn * 1000 : undefined;
231
+ tokens.issuedAt = Date.now();
232
+ await unified_auth_store_js_1.unifiedAuthStore.saveTokens(tokens);
233
+ }
234
+ logger.info('✅ Token refreshed successfully');
235
+ return {
236
+ success: true,
237
+ accessToken: refreshResult.accessToken
238
+ };
239
+ }
240
+ return {
241
+ success: false,
242
+ error: refreshResult.error || 'Failed to refresh token'
243
+ };
244
+ }
245
+ catch (error) {
246
+ logger.error('Force refresh error:', error);
247
+ return {
248
+ success: false,
249
+ error: error.message
250
+ };
251
+ }
252
+ }
253
+ /**
254
+ * Get fresh access token for deployment
255
+ */
256
+ async getDeploymentToken() {
257
+ // First ensure we have valid auth
258
+ const authResult = await this.ensureDeploymentAuth();
259
+ if (!authResult.isValid) {
260
+ logger.error('Invalid authentication for deployment:', authResult.error);
261
+ throw new Error(authResult.error || 'Authentication failed');
262
+ }
263
+ if (!authResult.hasWriteScope) {
264
+ logger.warn('⚠️ Token may lack write permissions, deployment might fail');
265
+ }
266
+ // Get the token
267
+ const tokens = await this.oauth.loadTokens();
268
+ return tokens?.accessToken || null;
269
+ }
270
+ }
271
+ exports.DeploymentAuthManager = DeploymentAuthManager;
272
+ //# sourceMappingURL=deployment-auth-fix.js.map
@@ -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