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
JavaScript
/**
* 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;