UNPKG

@genxis/whmrockstar

Version:

🎸 GenXis WHMRockStar - AI-powered multi-server WHM/cPanel management via Model Context Protocol (MCP). Enhanced with proper MCP stdio protocol support and multi-server management.

249 lines (212 loc) • 7.53 kB
const fs = require('fs'); const path = require('path'); const WHMService = require('./whm-service'); const logger = require('./logger'); class MultiServerManager { constructor() { this.servers = new Map(); this.configDir = path.join(process.env.HOME || process.env.USERPROFILE, '.genxis-whmrockstar'); this.serversConfigPath = path.join(this.configDir, 'servers.json'); this.loadServers(); } loadServers() { // Ensure config directory exists if (!fs.existsSync(this.configDir)) { fs.mkdirSync(this.configDir, { recursive: true }); } // Load from servers.json if (fs.existsSync(this.serversConfigPath)) { try { const config = JSON.parse(fs.readFileSync(this.serversConfigPath, 'utf8')); for (const [serverId, serverConfig] of Object.entries(config.servers || {})) { this.addServer(serverId, serverConfig, false); } logger.info(`Loaded ${this.servers.size} server(s) from configuration`); } catch (error) { logger.error(`Failed to load servers configuration: ${error.message}`); } } // Load legacy single server config const legacyConfigPath = path.join(this.configDir, 'config.json'); if (fs.existsSync(legacyConfigPath) && this.servers.size === 0) { try { const config = JSON.parse(fs.readFileSync(legacyConfigPath, 'utf8')); if (config.server && config.apiToken) { this.addServer('default', { ...config, name: config.name || `WHM Server (${config.server})` }, false); logger.info('Loaded legacy server configuration'); } } catch (error) { logger.error(`Failed to load legacy configuration: ${error.message}`); } } // Load from environment variables if (process.env.WHM_SERVER && process.env.WHM_API_TOKEN && this.servers.size === 0) { const serverId = process.env.WHM_SERVER_ID || 'env'; this.addServer(serverId, { server: process.env.WHM_SERVER, apiToken: process.env.WHM_API_TOKEN, port: process.env.WHM_PORT || '2087', name: process.env.WHM_SERVER_NAME || `WHM Server (${process.env.WHM_SERVER})` }, false); logger.info('Loaded server configuration from environment variables'); } } saveServers() { try { const config = { version: "2.0", servers: {} }; for (const [serverId, serverData] of this.servers) { config.servers[serverId] = { server: serverData.config.server, apiToken: serverData.config.apiToken, port: serverData.config.port || '2087', name: serverData.config.name, username: serverData.config.username || 'root', timeout: serverData.config.timeout || 30000, enabled: serverData.config.enabled !== false }; } fs.writeFileSync(this.serversConfigPath, JSON.stringify(config, null, 2)); logger.info('Server configuration saved'); } catch (error) { logger.error(`Failed to save server configuration: ${error.message}`); throw error; } } addServer(serverId, config, save = true) { try { // Validate configuration if (!config.server || !config.apiToken) { throw new Error('Server IP and API token are required'); } // Create WHM service instance const whmService = new WHMService(config); // Store server configuration this.servers.set(serverId, { service: whmService, config: { ...config, id: serverId, enabled: config.enabled !== false } }); logger.info(`Added server: ${serverId} (${config.server})`); if (save) { this.saveServers(); } return true; } catch (error) { logger.error(`Failed to add server ${serverId}: ${error.message}`); throw error; } } removeServer(serverId) { if (!this.servers.has(serverId)) { throw new Error(`Server '${serverId}' not found`); } this.servers.delete(serverId); logger.info(`Removed server: ${serverId}`); this.saveServers(); } updateServer(serverId, updates) { const serverData = this.servers.get(serverId); if (!serverData) { throw new Error(`Server '${serverId}' not found`); } // Update configuration const newConfig = { ...serverData.config, ...updates }; // Create new service instance with updated config const newService = new WHMService(newConfig); // Update stored data this.servers.set(serverId, { service: newService, config: newConfig }); logger.info(`Updated server: ${serverId}`); this.saveServers(); } getServer(serverId) { // If no serverId specified and only one server, return it if (!serverId && this.servers.size === 1) { return Array.from(this.servers.values())[0]; } // If no serverId specified and multiple servers, throw error if (!serverId && this.servers.size > 1) { const availableServers = Array.from(this.servers.keys()).join(', '); throw new Error(`Multiple servers configured. Please specify serverId. Available: ${availableServers}`); } // If no serverId specified and no servers, throw error if (!serverId && this.servers.size === 0) { throw new Error('No servers configured. Please add a server first.'); } const serverData = this.servers.get(serverId); if (!serverData) { const availableServers = Array.from(this.servers.keys()).join(', '); throw new Error(`Server '${serverId}' not found. Available servers: ${availableServers}`); } if (serverData.config.enabled === false) { throw new Error(`Server '${serverId}' is disabled`); } return serverData; } listServers() { return Array.from(this.servers.entries()).map(([id, { config }]) => ({ id, name: config.name || `WHM Server (${config.server})`, server: config.server, port: config.port || '2087', enabled: config.enabled !== false, username: config.username || 'root' })); } async testServer(serverId) { const { service, config } = this.getServer(serverId); try { await service.get('version'); return { success: true, server: config.server, message: 'Connection successful' }; } catch (error) { return { success: false, server: config.server, error: error.message }; } } async testAllServers() { const results = []; for (const [serverId] of this.servers) { try { const result = await this.testServer(serverId); results.push({ serverId, ...result }); } catch (error) { results.push({ serverId, success: false, error: error.message }); } } return results; } getServerCount() { return this.servers.size; } hasServers() { return this.servers.size > 0; } getEnabledServers() { return Array.from(this.servers.entries()) .filter(([, { config }]) => config.enabled !== false) .map(([id, data]) => ({ id, ...data })); } } module.exports = MultiServerManager;