UNPKG

php-universal-mcp-server

Version:

Servidor MCP universal para desenvolvimento PHP e criação de sites em qualquer provedor de hospedagem

367 lines (330 loc) 10.4 kB
/** * MCP Server - Implementação universal do Model Context Protocol * Compatível com qualquer provedor de hospedagem e funcional sem API */ const crypto = require('crypto'); class MCPServer { /** * Inicializa o servidor MCP com configurações * @param {Object} config - Configuração do servidor */ constructor(config = {}) { this.config = { mode: 'auto', // 'online', 'offline', 'auto' apiKey: '', fallbackEnabled: true, simulateResponses: true, providerType: 'auto', // 'hostinger', 'cpanel', 'plesk', 'aws', 'azure', 'gcp', 'mock' ...config }; // Inicializa o provider this.provider = this._initProvider(); // Handlers para comandos MCP this.handlers = { // Comandos padrão do protocolo MCP 'status': this._handleStatus.bind(this), 'execute': this._handleExecute.bind(this), 'stream': this._handleStream.bind(this), 'cancel': this._handleCancel.bind(this), 'terminate': this._handleTerminate.bind(this) }; // Estado interno do servidor this.state = { isRunning: false, activeSessions: new Map(), lastError: null }; } /** * Inicializa o provider adequado com base na configuração * @private */ _initProvider() { const { providerType, apiKey, mode } = this.config; // Se modo for offline ou não tiver API key, força mock if (mode === 'offline' || !apiKey) { const MockProvider = require('./providers/MockProvider'); return new MockProvider(this.config); } // Detecta automaticamente o provider se for auto if (providerType === 'auto') { return this._detectProvider(); } // Escolhe o provider específico switch (providerType) { case 'hostinger': const HostingerProvider = require('./providers/HostingerProvider'); return new HostingerProvider(this.config); case 'cpanel': const CPanelProvider = require('./providers/CPanelProvider'); return new CPanelProvider(this.config); case 'plesk': const PleskProvider = require('./providers/PleskProvider'); return new PleskProvider(this.config); case 'aws': const AWSProvider = require('./providers/AWSProvider'); return new AWSProvider(this.config); case 'azure': const AzureProvider = require('./providers/AzureProvider'); return new AzureProvider(this.config); case 'gcp': const GCPProvider = require('./providers/GCPProvider'); return new GCPProvider(this.config); default: const MockProvider = require('./providers/MockProvider'); return new MockProvider(this.config); } } /** * Detecta automaticamente o provider com base no ambiente * @private */ _detectProvider() { // Implementação da detecção baseada em características do ambiente if (this._isHostinger()) { const HostingerProvider = require('./providers/HostingerProvider'); return new HostingerProvider(this.config); } else if (this._isCPanel()) { const CPanelProvider = require('./providers/CPanelProvider'); return new CPanelProvider(this.config); } else if (this._isPlesk()) { const PleskProvider = require('./providers/PleskProvider'); return new PleskProvider(this.config); } else if (this._isAWS()) { const AWSProvider = require('./providers/AWSProvider'); return new AWSProvider(this.config); } else if (this._isAzure()) { const AzureProvider = require('./providers/AzureProvider'); return new AzureProvider(this.config); } else if (this._isGCP()) { const GCPProvider = require('./providers/GCPProvider'); return new GCPProvider(this.config); } // Fallback para mock provider const MockProvider = require('./providers/MockProvider'); return new MockProvider(this.config); } // Métodos de detecção de ambiente _isHostinger() { // Implementar detecção para Hostinger // Verifica características específicas do ambiente Hostinger try { // Por exemplo, verificar variáveis de ambiente ou arquivos específicos return process.env.HOSTINGER_ENV === 'true' || process.env.API_KEY; } catch (e) { return false; } } _isCPanel() { // Implementar detecção para cPanel try { // Verificar arquivos ou variáveis de ambiente cPanel return process.env.CPANEL_USER || (process.env.SERVER_SOFTWARE || '').includes('cPanel'); } catch (e) { return false; } } _isPlesk() { // Implementar detecção para Plesk try { // Verificar arquivos ou variáveis de ambiente Plesk return process.env.PLESK_ENV === 'true' || (process.env.SERVER_SOFTWARE || '').includes('Plesk'); } catch (e) { return false; } } _isAWS() { // Implementar detecção para AWS try { // Verificar metadados ou variáveis de ambiente AWS return process.env.AWS_REGION || process.env.AWS_LAMBDA_FUNCTION_NAME || process.env.AWS_EXECUTION_ENV || process.env.AWS_ACCESS_KEY_ID; } catch (e) { return false; } } _isAzure() { // Implementar detecção para Azure try { // Verificar variáveis de ambiente Azure return process.env.AZURE_SUBSCRIPTION_ID || process.env.WEBSITE_SITE_NAME || process.env.WEBSITE_INSTANCE_ID || process.env.AZURE_TENANT_ID; } catch (e) { return false; } } _isGCP() { // Implementar detecção para GCP try { // Verificar variáveis de ambiente GCP return process.env.GOOGLE_CLOUD_PROJECT || process.env.GCP_PROJECT || process.env.FUNCTION_NAME || process.env.K_SERVICE; } catch (e) { return false; } } /** * Inicia o servidor MCP */ start() { this.state.isRunning = true; return { status: 'running', provider: this.provider.getName(), mode: this.config.mode, timestamp: new Date().toISOString() }; } /** * Para o servidor MCP */ stop() { this.state.isRunning = false; // Finaliza todas as sessões ativas this.state.activeSessions.forEach((session, id) => { this._terminateSession(id); }); return { status: 'stopped', timestamp: new Date().toISOString() }; } /** * Processa um comando do protocolo MCP * @param {Object} mcpCommand - Comando MCP a ser processado */ processCommand(mcpCommand) { // Verifica se o servidor está rodando if (!this.state.isRunning) { return { error: 'Server not running', status: 'error', timestamp: new Date().toISOString() }; } // Valida o comando if (!mcpCommand || !mcpCommand.type) { return { error: 'Invalid MCP command', status: 'error', timestamp: new Date().toISOString() }; } // Busca o handler apropriado const handler = this.handlers[mcpCommand.type]; if (!handler) { return { error: `Unsupported MCP command: ${mcpCommand.type}`, status: 'error', timestamp: new Date().toISOString() }; } // Executa o handler try { return handler(mcpCommand); } catch (error) { this.state.lastError = error; return { error: error.message, status: 'error', timestamp: new Date().toISOString() }; } } /** * Registra um handler personalizado para um comando MCP * @param {string} commandType - Tipo do comando MCP * @param {Function} handler - Função que processa o comando */ registerHandler(commandType, handler) { if (typeof handler !== 'function') { throw new Error('Handler must be a function'); } this.handlers[commandType] = handler; } // Implementação dos handlers padrão _handleStatus(command) { return { status: 'success', serverStatus: this.state.isRunning ? 'running' : 'stopped', provider: this.provider.getName(), mode: this.config.mode, activeSessions: this.state.activeSessions.size, timestamp: new Date().toISOString() }; } _handleExecute(command) { const sessionId = crypto.randomUUID(); // Executa o comando através do provider const result = this.provider.execute(command.payload); // Registra a sessão this.state.activeSessions.set(sessionId, { id: sessionId, command: command, startTime: new Date(), result: result }); return { status: 'success', sessionId: sessionId, result: result, timestamp: new Date().toISOString() }; } _handleStream(command) { const sessionId = crypto.randomUUID(); // Cria um stream através do provider const stream = this.provider.createStream(command.payload); // Registra a sessão this.state.activeSessions.set(sessionId, { id: sessionId, command: command, startTime: new Date(), stream: stream }); return { status: 'success', sessionId: sessionId, stream: stream, timestamp: new Date().toISOString() }; } _handleCancel(command) { const { sessionId } = command.payload; if (!sessionId || !this.state.activeSessions.has(sessionId)) { return { error: `Session not found: ${sessionId}`, status: 'error', timestamp: new Date().toISOString() }; } // Cancela o comando no provider this.provider.cancel(sessionId); // Remove a sessão this.state.activeSessions.delete(sessionId); return { status: 'success', message: `Session ${sessionId} canceled`, timestamp: new Date().toISOString() }; } _handleTerminate(command) { return this.stop(); } /** * Termina uma sessão específica * @param {string} sessionId - ID da sessão a ser terminada * @private */ _terminateSession(sessionId) { if (this.state.activeSessions.has(sessionId)) { const session = this.state.activeSessions.get(sessionId); if (session.stream) { this.provider.closeStream(session.stream); } this.state.activeSessions.delete(sessionId); } } } // Exporta o MCPServer module.exports = MCPServer;