php-universal-mcp-server
Version:
Servidor MCP universal para desenvolvimento PHP e criação de sites em qualquer provedor de hospedagem
254 lines (219 loc) • 7.96 kB
JavaScript
/**
* PHP Universal MCP Server - Servidor HTTP
* Implementa um servidor HTTP para atender requisições do protocolo MCP
*/
const http = require('http');
const url = require('url');
const { createServer } = require('./index');
const MCPAdapter = require('./sdk-mcp');
const fs = require('fs');
const path = require('path');
// Configurações padrão
const DEFAULT_PORT = 7432;
const DEFAULT_HOST = '127.0.0.1';
/**
* Inicia o servidor HTTP para o protocolo MCP
* @param {Object} options - Opções de configuração
* @returns {http.Server} Instância do servidor HTTP
*/
function startServer(options = {}) {
const config = {
port: options.port || process.env.MCP_PORT || DEFAULT_PORT,
host: options.host || process.env.MCP_HOST || DEFAULT_HOST,
mcpConfig: options.mcpConfig || {}
};
// Cria o servidor MCP
const mcpServer = createServer(config.mcpConfig);
mcpServer.start();
// Cria o adaptador MCP
const mcpAdapter = new MCPAdapter(mcpServer);
mcpAdapter.initialize();
// Manipulador de requisições HTTP
const requestListener = (req, res) => {
// Habilita CORS para facilitar o desenvolvimento
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
// Responde imediatamente a requisições OPTIONS
if (req.method === 'OPTIONS') {
res.writeHead(200);
res.end();
return;
}
// Processa a URL e o path
const parsedUrl = url.parse(req.url, true);
const pathname = parsedUrl.pathname;
// Rota de status do servidor
if (pathname === '/status' && req.method === 'GET') {
const status = mcpServer.processCommand({ type: 'status' });
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify(status));
return;
}
// Rota principal MCP
if (pathname === '/mcp' && req.method === 'POST') {
let body = '';
req.on('data', chunk => {
body += chunk.toString();
});
req.on('end', () => {
try {
const message = JSON.parse(body);
const response = mcpAdapter.processMessage(message);
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify(response));
} catch (error) {
res.writeHead(400, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({
error: error.message,
status: 'error',
timestamp: new Date().toISOString()
}));
}
});
return;
}
// Rota de streaming via SSE (Server-Sent Events)
if (pathname === '/mcp/stream' && req.method === 'GET') {
const sessionId = parsedUrl.query.sessionId;
if (!sessionId) {
res.writeHead(400, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({
error: 'Missing sessionId parameter',
status: 'error',
timestamp: new Date().toISOString()
}));
return;
}
// Configura cabeçalhos para SSE
res.writeHead(200, {
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive'
});
// Função para enviar eventos para o cliente
const sendEvent = (event, data) => {
res.write(`event: ${event}\n`);
res.write(`data: ${JSON.stringify(data)}\n\n`);
};
// Envia evento inicial de conexão
sendEvent('connected', {
sessionId,
timestamp: new Date().toISOString()
});
// Configura handlers para eventos de stream
const onData = (data) => {
sendEvent('data', data);
};
const onEnd = (data) => {
sendEvent('end', data);
// Limpa os listeners e encerra a sessão
mcpAdapter.endSession(sessionId);
// Fecha a conexão
res.end();
};
const onError = (error) => {
sendEvent('error', {
error: error.message,
timestamp: new Date().toISOString()
});
// Limpa os listeners e encerra a sessão
mcpAdapter.endSession(sessionId);
// Fecha a conexão
res.end();
};
// Registra os listeners
mcpAdapter.eventEmitter.on('data', onData);
mcpAdapter.eventEmitter.on('end', onEnd);
mcpAdapter.eventEmitter.on('error', onError);
// Limpa os listeners quando o cliente desconecta
req.on('close', () => {
mcpAdapter.eventEmitter.off('data', onData);
mcpAdapter.eventEmitter.off('end', onEnd);
mcpAdapter.eventEmitter.off('error', onError);
mcpAdapter.endSession(sessionId);
});
return;
}
// Rota de documentação
if (pathname === '/' || pathname === '/index.html') {
try {
const docPath = path.join(__dirname, '../docs/index.html');
if (fs.existsSync(docPath)) {
const content = fs.readFileSync(docPath, 'utf8');
res.writeHead(200, { 'Content-Type': 'text/html' });
res.end(content);
} else {
// Página simples caso a documentação não exista
res.writeHead(200, { 'Content-Type': 'text/html' });
res.end(`
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>PHP Universal MCP Server</title>
<style>
body { font-family: Arial, sans-serif; max-width: 800px; margin: 0 auto; padding: 20px; }
h1 { color: #2c3e50; }
code { background: #f8f8f8; padding: 2px 4px; border-radius: 3px; }
</style>
</head>
<body>
<h1>PHP Universal MCP Server</h1>
<p>Um servidor MCP (Model Context Protocol) universal para desenvolvimento PHP, compatível com diversos provedores de hospedagem e nuvem.</p>
<p>Status do servidor: <code>Ativo</code></p>
<p>Endpoints disponíveis:</p>
<ul>
<li><code>GET /status</code> - Status do servidor</li>
<li><code>POST /mcp</code> - Endpoint principal MCP</li>
<li><code>GET /mcp/stream?sessionId=...</code> - Streaming via SSE</li>
</ul>
</body>
</html>
`);
}
return;
} catch (error) {
res.writeHead(500, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({
error: error.message,
status: 'error',
timestamp: new Date().toISOString()
}));
return;
}
}
// Rota não encontrada
res.writeHead(404, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({
error: 'Not Found',
status: 'error',
timestamp: new Date().toISOString()
}));
};
// Cria o servidor HTTP
const server = http.createServer(requestListener);
// Inicia o servidor
server.listen(config.port, config.host, () => {
console.log(`Servidor MCP rodando em http://${config.host}:${config.port}`);
console.log('Provedor ativo:', mcpServer.provider.getName());
console.log('Modo:', config.mcpConfig.mode || 'auto');
});
// Manipula erros do servidor
server.on('error', (error) => {
console.error('Erro no servidor MCP:', error.message);
if (error.code === 'EADDRINUSE') {
console.error(`A porta ${config.port} já está em uso. Tente usar outra porta.`);
}
});
return server;
}
// Exporta a função para iniciar o servidor
module.exports = {
startServer
};
// Se o arquivo for executado diretamente, inicia o servidor
if (require.main === module) {
startServer();
}