# MCP et SSE (Server-Sent Events) - Analyse ## Question **Peut-on utiliser le MCP en SSE?** ## Réponse: OUI ✅ (avec nuances) Le SDK MCP (@modelcontextprotocol/sdk) supporte **plusieurs transports**, dont certains utilisent SSE. --- ## Transports MCP Disponibles ### 1. **stdio** (Actuellement utilisé) ✅ ```javascript import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; ``` **Avantages**: - Simple, direct, pas de réseau - Idéal pour processus locaux - Utilisé par Claude Desktop, Cline, etc. **Inconvénients**: - ❌ Nécessite accès fichier local - ❌ Pas adapté pour N8N sur machine distante - ❌ N8N doit avoir accès à `D:/dev_new_pc/Keep/mcp-server/index.js` --- ### 2. **SSE via HTTP** ✅ (RECOMMANDÉ pour N8N distant!) ```javascript import { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js'; ``` **Avantages**: - ✅ Fonctionne sur le réseau (parfait pour N8N distant!) - ✅ Connexion persistante unidirectionnelle - ✅ Standard HTTP/HTTPS - ✅ Pas de WebSocket nécessaire - ✅ Compatible avec la plupart des firewalls **Comment ça marche**: 1. Client (N8N) se connecte à `http://your-ip:3001/sse` 2. Serveur maintient la connexion ouverte 3. Envoie des événements SSE au format `data: {...}\n\n` 4. Client peut envoyer des requêtes via POST sur `/message` --- ### 3. **HTTP avec WebSockets** (Alternative) ```javascript // Pas officiellement documenté dans SDK 1.0.4 // Mais possible avec implémentation custom ``` --- ## Configuration SSE pour Memento MCP Server ### Option A: Créer un serveur SSE séparé **Fichier**: `mcp-server/index-sse.js` ```javascript #!/usr/bin/env node import { Server } from '@modelcontextprotocol/sdk/server/index.js'; import { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js'; import express from 'express'; import { PrismaClient } from '@prisma/client'; import { join, dirname } from 'path'; import { fileURLToPath } from 'url'; const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); const app = express(); const PORT = 3001; // Initialize Prisma const prisma = new PrismaClient({ datasources: { db: { url: `file:${join(__dirname, '../keep-notes/prisma/dev.db')}` } } }); // Helper function function parseNote(dbNote) { return { ...dbNote, checkItems: dbNote.checkItems ? JSON.parse(dbNote.checkItems) : null, labels: dbNote.labels ? JSON.parse(dbNote.labels) : null, images: dbNote.images ? JSON.parse(dbNote.images) : null, }; } // Initialize MCP Server const server = new Server( { name: 'memento-mcp-server', version: '1.0.0', }, { capabilities: { tools: {}, }, } ); // Register all tools (same as stdio version) server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools: [ // ... tous les tools comme create_note, get_notes, etc. ], }; }); server.setRequestHandler(CallToolRequestSchema, async (request) => { // ... même logique que stdio version }); // SSE Endpoint app.get('/sse', async (req, res) => { const transport = new SSEServerTransport('/message', res); await server.connect(transport); }); // Message Endpoint app.post('/message', express.json(), async (req, res) => { // Handled by SSEServerTransport }); app.listen(PORT, () => { console.log(`MCP SSE Server running on http://localhost:${PORT}`); console.log(`SSE endpoint: http://localhost:${PORT}/sse`); }); ``` **Dépendances à ajouter**: ```bash cd mcp-server npm install express ``` **Démarrage**: ```bash node mcp-server/index-sse.js ``` --- ### Option B: Utiliser Next.js API Route avec SSE **Fichier**: `keep-notes/app/api/mcp/route.ts` ```typescript import { Server } from '@modelcontextprotocol/sdk/server/index.js'; import { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js'; import { prisma } from '@/lib/prisma'; import { NextRequest } from 'next/server'; const mcpServer = new Server( { name: 'memento-mcp-server', version: '1.0.0', }, { capabilities: { tools: {}, }, } ); // Register tools... export async function GET(req: NextRequest) { const encoder = new TextEncoder(); const stream = new ReadableStream({ async start(controller) { const transport = new SSEServerTransport('/api/mcp/message', { write: (data) => controller.enqueue(encoder.encode(data)), }); await mcpServer.connect(transport); }, }); return new Response(stream, { headers: { 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache', 'Connection': 'keep-alive', }, }); } export async function POST(req: NextRequest) { // Handle messages const body = await req.json(); // Process via mcpServer return Response.json({ success: true }); } ``` **Avantage**: Même serveur Next.js, pas de port séparé! --- ## Configuration N8N avec SSE ### Méthode 1: MCP Client Community Node (si supporte SSE) **Configuration**: ```json { "name": "memento-sse", "transport": "sse", "url": "http://YOUR_IP:3001/sse" } ``` ### Méthode 2: HTTP Request Nodes (Fallback) Si le MCP Client ne supporte pas SSE, utiliser les nodes HTTP Request standards de N8N avec l'API REST existante (comme actuellement). --- ## Comparaison: stdio vs SSE | Feature | stdio | SSE | |---------|-------|-----| | **Connexion** | Process local | HTTP réseau | | **N8N distant** | ❌ Non | ✅ Oui | | **Latence** | Très faible | Faible | | **Setup** | Simple | Moyen | | **Firewall** | N/A | Standard HTTP | | **Scaling** | 1 instance | Multiple clients | | **Debugging** | Console logs | Network logs + curl | --- ## Recommandation pour ton cas ### Contexte - N8N déployé sur une **machine séparée** - Besoin d'accès distant au MCP server - MCP Client Community Node installé ### Solution: **SSE via Express** ✅ **Pourquoi**: 1. stdio nécessite accès fichier local (impossible si N8N sur autre machine) 2. SSE fonctionne sur HTTP standard (réseau) 3. Facile à tester avec curl 4. Compatible avec la plupart des clients MCP **Étapes**: 1. Créer `mcp-server/index-sse.js` avec Express + SSE 2. Ajouter `express` aux dépendances 3. Démarrer sur port 3001 (ou autre) 4. Trouver l'IP de ta machine Windows: `ipconfig` 5. Configurer N8N MCP Client avec `http://YOUR_IP:3001/sse` 6. Tester avec N8N workflows --- ## Test SSE sans N8N ### Avec curl: ```bash # Test connexion SSE curl -N http://localhost:3001/sse # Test appel d'un tool curl -X POST http://localhost:3001/message \ -H "Content-Type: application/json" \ -d '{ "jsonrpc": "2.0", "method": "tools/call", "params": { "name": "get_notes", "arguments": {} }, "id": 1 }' ``` ### Avec JavaScript (test rapide): ```javascript const eventSource = new EventSource('http://localhost:3001/sse'); eventSource.onmessage = (event) => { console.log('Received:', event.data); }; eventSource.onerror = (error) => { console.error('SSE Error:', error); }; ``` --- ## Prochaines étapes 1. ✅ **Je peux créer le serveur SSE si tu veux** 2. ✅ **Tester localement avec curl** 3. ✅ **Configurer N8N pour pointer vers SSE endpoint** 4. ✅ **Vérifier que MCP Client Community Node supporte SSE** **Tu veux que je crée le serveur SSE maintenant?** --- ## Ressources - [MCP SDK Documentation](https://github.com/modelcontextprotocol/sdk) - [SSE Specification](https://html.spec.whatwg.org/multipage/server-sent-events.html) - [N8N MCP Integration](https://community.n8n.io/) --- **Conclusion**: Oui, MCP peut utiliser SSE! C'est même **recommandé** pour ton cas avec N8N sur une machine distante. Le transport stdio actuel ne fonctionne que pour processus locaux.