# 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.
