Keep/MCP-SSE-ANALYSIS.md
sepehr 8d95f34fcc fix: Add debounced Undo/Redo system to avoid character-by-character history
- Add debounced state updates for title and content (500ms delay)
- Immediate UI updates with delayed history saving
- Prevent one-letter-per-undo issue
- Add cleanup for debounce timers on unmount
2026-01-04 14:28:11 +01:00

7.6 KiB

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é)

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!)

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)

// 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

#!/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:

cd mcp-server
npm install express

Démarrage:

node mcp-server/index-sse.js

Option B: Utiliser Next.js API Route avec SSE

Fichier: keep-notes/app/api/mcp/route.ts

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:

{
  "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:

# 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):

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


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.