Skip to main content
Glama

MCP Firebird

// sse-proxy.js // Un proxy simple para manejar las conexiones SSE entre el cliente y el servidor MCP Firebird import express from 'express'; import cors from 'cors'; import { createServer } from 'http'; import fetch from 'node-fetch'; import { spawn } from 'child_process'; import * as path from 'path'; import { fileURLToPath } from 'url'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); // Configuración const PROXY_PORT = 3004; const MCP_SERVER_PORT = 3003; const MCP_SERVER_URL = `http://localhost:${MCP_SERVER_PORT}`; // Crear la aplicación Express const app = express(); // Habilitar CORS app.use(cors({ origin: '*', methods: ['GET', 'POST', 'OPTIONS'], allowedHeaders: ['Content-Type', 'X-Session-ID', 'Authorization'] })); // Parsear cuerpos JSON app.use(express.json()); // Mapa para almacenar las conexiones SSE activas const sessions = new Map(); // Función para iniciar el servidor MCP async function startMcpServer() { console.log('Iniciando servidor MCP...'); // Configurar variables de entorno process.env.TRANSPORT_TYPE = 'sse'; process.env.SSE_PORT = MCP_SERVER_PORT.toString(); // Iniciar el servidor MCP const child = spawn('node', ['dist/index.js'], { env: process.env, stdio: 'inherit', shell: true }); // Manejar salida del proceso child.on('exit', (code) => { console.log(`Servidor MCP finalizado con código ${code}`); process.exit(code); }); // Esperar a que el servidor esté listo await new Promise(resolve => setTimeout(resolve, 2000)); return child; } // Endpoint SSE app.get('/', async (req, res) => { try { console.log('Nueva conexión SSE recibida'); // Configurar la respuesta para SSE res.setHeader('Content-Type', 'text/event-stream'); res.setHeader('Cache-Control', 'no-cache'); res.setHeader('Connection', 'keep-alive'); res.flushHeaders(); // Crear una conexión SSE con el servidor MCP const sseResponse = await fetch(`${MCP_SERVER_URL}`, { method: 'GET', headers: { 'Accept': 'text/event-stream' } }); if (!sseResponse.ok) { throw new Error(`Error al conectar con el servidor MCP: ${sseResponse.status} ${sseResponse.statusText}`); } console.log('Conexión SSE establecida con el servidor MCP'); // Generar un ID de sesión para el cliente const clientId = `client-${Math.random().toString(36).substring(2, 14)}`; console.log(`ID de cliente generado: ${clientId}`); // Almacenar la sesión sessions.set(clientId, { res, createdAt: new Date(), lastActivity: new Date() }); // Enviar el evento endpoint al cliente const endpointUrl = `${req.protocol}://${req.get('host')}/message?sessionId=${clientId}`; console.log(`Enviando endpoint: ${endpointUrl}`); res.write(`event: endpoint\ndata: ${endpointUrl}\n\n`); // Enviar un mensaje inicial res.write(`data: ${JSON.stringify({ type: 'connection', message: 'Conexión establecida' })}\n\n`); // Manejar la desconexión del cliente req.on('close', () => { console.log(`Cliente desconectado`); if (clientId) { console.log(`Eliminando sesión ${clientId}`); sessions.delete(clientId); } }); // Mantener la conexión viva enviando un comentario cada 30 segundos const keepAliveInterval = setInterval(() => { if (res.writableEnded) { clearInterval(keepAliveInterval); return; } res.write(': keepalive\n\n'); }, 30000); } catch (error) { console.error(`Error al establecer la conexión SSE: ${error.message}`); if (!res.headersSent) { res.status(500).send({ error: 'Error al establecer la conexión SSE', message: error.message }); } } }); // Ya no necesitamos esta función porque el servidor MCP maneja las sesiones correctamente // Endpoint para mensajes app.post('/message', async (req, res) => { try { // Obtener el ID de sesión del parámetro de consulta const sessionId = req.query.sessionId?.toString(); if (!sessionId) { throw new Error('Se requiere un ID de sesión'); } console.log(`Mensaje recibido del cliente para la sesión ${sessionId}`); // Obtener la sesión const session = sessions.get(sessionId); if (!session) { throw new Error(`No se encontró una sesión activa para el ID: ${sessionId}`); } // Actualizar la última actividad session.lastActivity = new Date(); // Obtener el ID de sesión del servidor MCP const mcpSessionId = `session-${Date.now()}-${Math.random().toString(36).substring(2, 10)}`; // Crear una sesión en el servidor MCP try { const sseResponse = await fetch(`${MCP_SERVER_URL}?sessionId=${mcpSessionId}`, { method: 'GET', headers: { 'Accept': 'text/event-stream' } }); if (!sseResponse.ok) { throw new Error(`Error al conectar con el servidor MCP: ${sseResponse.status} ${sseResponse.statusText}`); } console.log(`Sesión creada en el servidor MCP: ${mcpSessionId}`); } catch (error) { console.error(`Error al crear la sesión en el servidor MCP: ${error.message}`); throw error; } // Reenviar la solicitud al servidor MCP const mcpResponse = await fetch(`${MCP_SERVER_URL}/message?sessionId=${mcpSessionId}`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-Session-ID': mcpSessionId }, body: JSON.stringify(req.body) }); // Verificar si la respuesta es exitosa if (!mcpResponse.ok) { const errorText = await mcpResponse.text(); console.error(`Error del servidor MCP: ${errorText}`); // Intentar parsear el error como JSON try { const errorJson = JSON.parse(errorText); res.status(mcpResponse.status).json(errorJson); } catch (e) { // No es JSON, enviar como texto res.status(mcpResponse.status).send(errorText); } return; } // Obtener la respuesta del servidor MCP const responseData = await mcpResponse.json(); // Enviar la respuesta al cliente res.json(responseData); // También enviar la respuesta a través de SSE if (session.res && !session.res.writableEnded) { session.res.write(`data: ${JSON.stringify(responseData)}\n\n`); } } catch (error) { console.error(`Error al manejar el mensaje: ${error.message}`); // Solo enviar una respuesta si los encabezados no se han enviado aún if (!res.headersSent) { res.status(400).json({ jsonrpc: '2.0', id: req.body?.id, error: { code: -32603, message: error.message || 'Error interno del servidor', data: { type: 'TRANSPORT_ERROR' } } }); } } }); // Iniciar el servidor proxy async function startProxy() { try { // Iniciar el servidor MCP const mcpServer = await startMcpServer(); // Iniciar el servidor proxy const server = createServer(app); server.listen(PROXY_PORT, () => { console.log(`Proxy SSE escuchando en el puerto ${PROXY_PORT}`); console.log(`Redirigiendo solicitudes a ${MCP_SERVER_URL}`); }); // Manejar la señal de terminación process.on('SIGINT', async () => { console.log('Cerrando el servidor proxy...'); server.close(); // Matar el servidor MCP if (mcpServer) { mcpServer.kill(); } process.exit(0); }); } catch (error) { console.error(`Error al iniciar el proxy: ${error.message}`); process.exit(1); } } // Iniciar el proxy startProxy().catch(console.error);

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/PuroDelphi/mcpFirebird'

If you have feedback or need assistance with the MCP directory API, please join our Discord server