fix endpoints

Signed-off-by: ale <ale@manalejandro.com>
Este commit está contenido en:
ale
2025-11-09 22:10:51 +01:00
padre 9335220808
commit 58fdf20620
Se han modificado 2 ficheros con 100 adiciones y 69 borrados

Ver fichero

@@ -833,11 +833,14 @@ function createMCPServer(): Server {
* Endpoint MCP JSON-RPC directo (más compatible y simple) * Endpoint MCP JSON-RPC directo (más compatible y simple)
*/ */
app.post('/mcp/v1', async (req: Request, res: Response) => { app.post('/mcp/v1', async (req: Request, res: Response) => {
console.log('MCP JSON-RPC Request:', req.body); console.log('MCP JSON-RPC Request:', JSON.stringify(req.body, null, 2));
try { try {
const { jsonrpc, method, params, id } = req.body; const { jsonrpc, method, params, id } = req.body;
// Establecer headers correctos
res.setHeader('Content-Type', 'application/json');
// Validar JSON-RPC 2.0 // Validar JSON-RPC 2.0
if (jsonrpc !== '2.0') { if (jsonrpc !== '2.0') {
return res.status(400).json({ return res.status(400).json({
@@ -852,7 +855,8 @@ app.post('/mcp/v1', async (req: Request, res: Response) => {
// Initialize - Handshake inicial de MCP // Initialize - Handshake inicial de MCP
if (method === 'initialize') { if (method === 'initialize') {
return res.json({ console.log('MCP Initialize received');
return res.status(200).json({
jsonrpc: '2.0', jsonrpc: '2.0',
result: { result: {
protocolVersion: '2024-11-05', protocolVersion: '2024-11-05',
@@ -868,15 +872,16 @@ app.post('/mcp/v1', async (req: Request, res: Response) => {
}); });
} }
// Initialized - Confirmación del cliente // Initialized - Confirmación del cliente (es una notificación, no requiere respuesta)
if (method === 'notifications/initialized') { if (method === 'notifications/initialized') {
console.log('Cliente MCP inicializado'); console.log('Cliente MCP inicializado');
return res.status(204).send(); return res.status(200).json({});
} }
// Listar herramientas // Listar herramientas
if (method === 'tools/list') { if (method === 'tools/list') {
return res.json({ console.log('MCP tools/list received');
return res.status(200).json({
jsonrpc: '2.0', jsonrpc: '2.0',
result: { tools }, result: { tools },
id id
@@ -887,6 +892,8 @@ app.post('/mcp/v1', async (req: Request, res: Response) => {
if (method === 'tools/call') { if (method === 'tools/call') {
const { name, arguments: args } = params || {}; const { name, arguments: args } = params || {};
console.log(`MCP tools/call: ${name}`, args);
if (!name) { if (!name) {
return res.status(400).json({ return res.status(400).json({
jsonrpc: '2.0', jsonrpc: '2.0',
@@ -900,7 +907,9 @@ app.post('/mcp/v1', async (req: Request, res: Response) => {
const result = await handleToolCall(name, args || {}); const result = await handleToolCall(name, args || {});
return res.json({ console.log(`MCP tools/call result for ${name}: success`);
return res.status(200).json({
jsonrpc: '2.0', jsonrpc: '2.0',
result: { result: {
content: [ content: [
@@ -916,7 +925,7 @@ app.post('/mcp/v1', async (req: Request, res: Response) => {
// Ping/Pong // Ping/Pong
if (method === 'ping') { if (method === 'ping') {
return res.json({ return res.status(200).json({
jsonrpc: '2.0', jsonrpc: '2.0',
result: {}, result: {},
id id
@@ -924,7 +933,8 @@ app.post('/mcp/v1', async (req: Request, res: Response) => {
} }
// Método no soportado // Método no soportado
return res.status(404).json({ console.log(`MCP method not found: ${method}`);
return res.status(200).json({
jsonrpc: '2.0', jsonrpc: '2.0',
error: { error: {
code: -32601, code: -32601,
@@ -935,7 +945,7 @@ app.post('/mcp/v1', async (req: Request, res: Response) => {
} catch (error: any) { } catch (error: any) {
console.error('Error en MCP:', error); console.error('Error en MCP:', error);
return res.status(500).json({ return res.status(200).json({
jsonrpc: '2.0', jsonrpc: '2.0',
error: { error: {
code: -32603, code: -32603,

Ver fichero

@@ -12,12 +12,14 @@ import type { Idioma } from './types/ine.types.js';
const PORT = process.env.PORT || 3001; const PORT = process.env.PORT || 3001;
const app = express(); const app = express();
app.use(cors()); app.use(cors({
origin: '*',
methods: ['GET', 'POST', 'OPTIONS'],
allowedHeaders: ['Content-Type', 'Accept'],
credentials: false
}));
app.use(express.json()); app.use(express.json());
// Almacenamiento de sesiones SSE
const sessions = new Map<string, { server: Server; transport: SSEServerTransport }>();
/** /**
* Maneja las llamadas a las herramientas MCP * Maneja las llamadas a las herramientas MCP
*/ */
@@ -128,73 +130,86 @@ const tools = [
* Endpoint SSE para conexión MCP * Endpoint SSE para conexión MCP
*/ */
app.get('/sse', async (req: Request, res: Response) => { app.get('/sse', async (req: Request, res: Response) => {
const sessionId = Math.random().toString(36).substring(7); console.log('Nueva conexión SSE iniciada');
// Configurar SSE try {
res.writeHead(200, { // Crear servidor MCP
'Content-Type': 'text/event-stream', const server = new Server(
'Cache-Control': 'no-cache', {
'Connection': 'keep-alive' name: 'ine-mcp-server-sse',
}); version: '1.0.0',
// Crear servidor MCP
const server = new Server(
{
name: 'ine-mcp-server-sse',
version: '1.0.0',
},
{
capabilities: {
tools: {},
}, },
} {
); capabilities: {
tools: {},
},
}
);
// Registrar handlers // Registrar handlers
server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools })); server.setRequestHandler(ListToolsRequestSchema, async () => {
console.log('SSE: ListTools request received');
return { tools };
});
server.setRequestHandler(CallToolRequestSchema, async (request) => { server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params; const { name, arguments: args } = request.params;
const result = await handleToolCall(name, args || {}); console.log(`SSE: CallTool request - ${name}`, args);
const result = await handleToolCall(name, args || {});
return {
content: [
{
type: 'text',
text: JSON.stringify(result, null, 2)
}
]
};
});
// Crear transporte SSE - este configura los headers automáticamente
const transport = new SSEServerTransport('/message', res);
return { // Conectar servidor con transporte
content: [ await server.connect(transport);
{
type: 'text', console.log('SSE: Servidor MCP conectado');
text: JSON.stringify(result, null, 2)
}
]
};
});
// Crear transporte SSE // Manejar cierre de conexión
const transport = new SSEServerTransport('/messages', res); req.on('close', () => {
await server.connect(transport); console.log('SSE: Conexión cerrada por el cliente');
server.close().catch(err => console.error('Error cerrando servidor:', err));
});
sessions.set(sessionId, { server, transport }); } catch (error: any) {
console.error('Error en conexión SSE:', error);
// Limpiar al cerrar conexión if (!res.headersSent) {
req.on('close', () => { res.status(500).json({
sessions.delete(sessionId); error: error.message,
console.log(`Sesión SSE cerrada: ${sessionId}`); stack: error.stack
}); });
}
console.log(`Nueva sesión SSE iniciada: ${sessionId}`); }
}); });
/** /**
* Endpoint para enviar mensajes (POST) * Endpoint para enviar mensajes (POST)
* Este endpoint recibe los mensajes JSON-RPC del cliente
*/ */
app.post('/messages', async (req: Request, res: Response) => { app.post('/message', express.json(), async (req: Request, res: Response) => {
console.log('SSE Message received:', JSON.stringify(req.body, null, 2));
try { try {
// Este endpoint procesa mensajes enviados por el cliente // El SDK de MCP maneja esto internamente a través del SSEServerTransport
const message = req.body; // Solo necesitamos confirmar la recepción
console.log('Mensaje recibido:', message); res.status(202).json({ received: true });
res.json({ success: true });
} catch (error: any) { } catch (error: any) {
console.error('Error procesando mensaje:', error); console.error('Error procesando mensaje SSE:', error);
res.status(500).json({ error: error.message }); res.status(500).json({
error: error.message,
stack: error.stack
});
} }
}); });
@@ -203,8 +218,14 @@ app.get('/health', (req: Request, res: Response) => {
res.json({ res.json({
status: 'ok', status: 'ok',
transport: 'SSE', transport: 'SSE',
sessions: sessions.size, timestamp: new Date().toISOString(),
timestamp: new Date().toISOString() service: 'MCP INE Server (SSE)',
version: '1.0.0',
endpoints: {
sse: '/sse',
message: '/message',
health: '/health'
}
}); });
}); });