diff --git a/src/index.ts b/src/index.ts index 033d2be..b40e41f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -26,6 +26,320 @@ app.use(cors({ app.use(express.json()); app.use(express.text()); +// Página principal con información de la API +app.get('/', (req: Request, res: Response) => { + const baseUrl = req.protocol + '://' + req.get('host'); + res.send(` + + + + + + MCP INE Server - API del Instituto Nacional de Estadística + + + +
+
+

🚀 MCP INE Server

+

API del Instituto Nacional de Estadística de España

+

+ MCP Protocol + REST API + Swagger Docs +

+
+ +
+
+

📊 Estadísticas del Servidor

+
+
+ ${tools.length} + Herramientas MCP +
+
+ 24 + Endpoints INE +
+
+ 3 + Protocolos +
+
+
+ +
+

🔌 Endpoints MCP (Model Context Protocol)

+
+
+ POST + ${baseUrl}/mcp/v1 +

JSON-RPC Endpoint - Endpoint principal para MCP sobre HTTP usando JSON-RPC 2.0. Este es el endpoint recomendado para la mayoría de clientes.

+
+
+ GET + ${baseUrl}/mcp/v1/sse +

Conexión SSE - Endpoint alternativo para conexión MCP con Server-Sent Events (experimental).

+
+
+ +

📝 Configuración para VS Code AI Toolkit

+
+ { + "mcpServers": { + "mcp-ine": { + "url": "${baseUrl}/mcp/v1", + "transport": "http" + } + } +} +

Agrega esta configuración a ~/.aitk/mcp.json

+
+ +

🧪 Probar el Endpoint

+
+ curl -X POST ${baseUrl}/mcp/v1 \\ + -H "Content-Type: application/json" \\ + -d '{"jsonrpc":"2.0","method":"initialize","params":{},"id":1}' +
+
+ +
+

🛠️ Herramientas MCP Disponibles

+

El servidor expone ${tools.length} herramientas para consultar datos del INE:

+
+ ${tools.map(tool => ` +
+ ${tool.name} + ${tool.description} +
+ `).join('')} +
+
+ +
+

📚 Documentación y APIs

+
+
+ GET + ${baseUrl}/api-docs +

Swagger UI - Documentación interactiva completa de la API REST con todos los endpoints disponibles.

+
+
+ GET + ${baseUrl}/health +

Health Check - Verifica el estado del servidor.

+
+
+
+ +
+

🌐 API REST Directa

+

Además del protocolo MCP, puedes acceder directamente a los datos mediante endpoints REST:

+
+
+ GET + /api/operaciones-disponibles +

Lista todas las operaciones estadísticas disponibles

+
+
+ GET + /api/operacion/:idOperacion +

Información detallada de una operación (ej: IPC, EPA)

+
+
+ GET + /api/datos-tabla/:idTabla +

Datos completos de una tabla estadística

+
+
+ GET + /api/datos-serie/:idSerie +

Datos de una serie temporal específica

+
+
+ GET + /api/variables +

Lista todas las variables estadísticas

+
+
+ GET + /api/series-operacion/:idOperacion +

Todas las series de una operación

+
+
+
+ +
+

💡 Ejemplos de Uso

+ +

Consulta directa con curl:

+
+ curl "${baseUrl}/api/operaciones-disponibles?idioma=ES" +
+ +

Consulta mediante MCP:

+
+ // Usa la herramienta ine_operaciones_disponibles +// desde tu cliente MCP (VS Code AI Toolkit, etc.) +
+
+ +
+

ℹ️ Información

+

Servidor: MCP INE Server v1.0.0

+

Protocolo: Model Context Protocol (MCP) + REST API

+

Fuente de datos: Instituto Nacional de Estadística (INE)

+

Documentación MCP: modelcontextprotocol.io

+
+
+
+ + + `); +}); + // Swagger Documentation app.use('/api-docs', ...swaggerUi.serve as any); app.get('/api-docs', swaggerUi.setup(swaggerSpec) as any); @@ -35,7 +349,18 @@ app.get('/health', (req: Request, res: Response) => { res.json({ status: 'ok', timestamp: new Date().toISOString(), - service: 'MCP INE Server' + service: 'MCP INE Server', + version: '1.0.0', + tools: tools.length, + endpoints: { + mcp: '/mcp/v1', + mcp_sse: '/mcp/v1/sse', + mcp_message: '/mcp/v1/message', + swagger: '/api-docs', + health: '/health' + }, + protocol: 'JSON-RPC 2.0', + mcp_version: '2024-11-05' }); }); @@ -504,9 +829,127 @@ function createMCPServer(): Server { return server; } +/** + * Endpoint MCP JSON-RPC directo (más compatible y simple) + */ +app.post('/mcp/v1', async (req: Request, res: Response) => { + console.log('MCP JSON-RPC Request:', req.body); + + try { + const { jsonrpc, method, params, id } = req.body; + + // Validar JSON-RPC 2.0 + if (jsonrpc !== '2.0') { + return res.status(400).json({ + jsonrpc: '2.0', + error: { + code: -32600, + message: 'Invalid Request: jsonrpc must be "2.0"' + }, + id: id || null + }); + } + + // Initialize - Handshake inicial de MCP + if (method === 'initialize') { + return res.json({ + jsonrpc: '2.0', + result: { + protocolVersion: '2024-11-05', + serverInfo: { + name: 'ine-mcp-server', + version: '1.0.0' + }, + capabilities: { + tools: {} + } + }, + id + }); + } + + // Initialized - Confirmación del cliente + if (method === 'notifications/initialized') { + console.log('Cliente MCP inicializado'); + return res.status(204).send(); + } + + // Listar herramientas + if (method === 'tools/list') { + return res.json({ + jsonrpc: '2.0', + result: { tools }, + id + }); + } + + // Llamar a una herramienta + if (method === 'tools/call') { + const { name, arguments: args } = params || {}; + + if (!name) { + return res.status(400).json({ + jsonrpc: '2.0', + error: { + code: -32602, + message: 'Invalid params: name is required' + }, + id + }); + } + + const result = await handleToolCall(name, args || {}); + + return res.json({ + jsonrpc: '2.0', + result: { + content: [ + { + type: 'text', + text: JSON.stringify(result, null, 2) + } + ] + }, + id + }); + } + + // Ping/Pong + if (method === 'ping') { + return res.json({ + jsonrpc: '2.0', + result: {}, + id + }); + } + + // Método no soportado + return res.status(404).json({ + jsonrpc: '2.0', + error: { + code: -32601, + message: `Method not found: ${method}` + }, + id + }); + + } catch (error: any) { + console.error('Error en MCP:', error); + return res.status(500).json({ + jsonrpc: '2.0', + error: { + code: -32603, + message: error.message || 'Internal error', + data: { stack: error.stack } + }, + id: req.body.id || null + }); + } +}); + /** * Endpoint MCP HTTP con SSE (Server-Sent Events) - * Este es el protocolo oficial de MCP para HTTP + * Alternativa para clientes que prefieren SSE */ app.get('/mcp/v1/sse', async (req: Request, res: Response) => { console.log('Nueva conexión SSE MCP'); @@ -536,7 +979,6 @@ app.get('/mcp/v1/sse', async (req: Request, res: Response) => { app.post('/mcp/v1/message', async (req: Request, res: Response) => { try { // Este endpoint es manejado internamente por SSEServerTransport - // Solo necesitamos asegurarnos de que el body parser esté configurado res.status(202).json({ received: true }); } catch (error: any) { console.error('Error procesando mensaje:', error); @@ -589,10 +1031,13 @@ app.get('/api/tablas-operacion/:idOperacion', async (req, res) => { app.listen(PORT, () => { console.log(`🚀 MCP INE Server ejecutándose en http://localhost:${PORT}`); console.log(`📚 Documentación Swagger: http://localhost:${PORT}/api-docs`); - console.log(`🔧 Endpoint MCP SSE: http://localhost:${PORT}/mcp/v1/sse`); - console.log(`📨 Endpoint MCP Message: http://localhost:${PORT}/mcp/v1/message`); + console.log(`🔧 Endpoint MCP JSON-RPC: POST http://localhost:${PORT}/mcp/v1`); + console.log(`🔧 Endpoint MCP SSE: GET http://localhost:${PORT}/mcp/v1/sse`); + console.log(`📨 Endpoint MCP Message: POST http://localhost:${PORT}/mcp/v1/message`); console.log(`💚 Health check: http://localhost:${PORT}/health`); console.log(`\n📋 Herramientas disponibles: ${tools.length}`); + console.log(`\n🔗 Configuración AI Toolkit:`); + console.log(` {"mcpServers": {"mcp-ine": {"url": "http://localhost:${PORT}/mcp/v1", "transport": "http"}}}`); }); // Para uso con stdio (AI Toolkit local)