# Keep Notes MCP SSE Server Server-Sent Events (SSE) version of Keep Notes MCP Server for remote N8N access. ## ๐ŸŽฏ Purpose This SSE server allows N8N (or other MCP clients) running on **remote machines** to connect to Keep Notes via HTTP/SSE instead of stdio. ### stdio vs SSE || Feature | stdio (`index.js`) | SSE (`index-sse.js`) | ||---------|-------------------|---------------------| || **Connection** | Local process | Network HTTP | || **Remote access** | โŒ No | โœ… Yes | || **Use case** | Claude Desktop, local tools | N8N on remote machine | || **Port** | N/A | 3001 | || **Version** | 2.0.0 | 2.0.0 | || **Tools** | 19 | 19 | ## ๐Ÿš€ Quick Start ### 1. Install Dependencies ```bash cd mcp-server npm install ``` ### 2. Start Server **Option A: PowerShell Script (Recommended)** ```powershell .\start-sse.ps1 ``` **Option B: Direct Node** ```bash npm run start:sse # or node index-sse.js ``` ### 3. Verify Server is Running Open browser to: `http://localhost:3001` You should see: ```json { "name": "Keep Notes MCP SSE Server", "version": "2.0.0", "status": "running", "endpoints": { "sse": "/sse", "message": "/message" } } ``` ## ๐ŸŒ Get Your IP Address ### Windows ```powershell ipconfig ``` Look for "IPv4 Address" (usually 192.168.x.x) ### Mac/Linux ```bash ifconfig # or ip addr show ``` ## ๐Ÿ”Œ N8N Configuration ### Method 1: MCP Client Community Node If your N8N has MCP Client node installed: 1. Open N8N Settings โ†’ MCP Access 2. Add new server: ```json { "name": "keep-notes", "transport": "sse", "url": "http://YOUR_IP:3001/sse" } ``` Replace `YOUR_IP` with your machine's IP (e.g., `192.168.1.100`) 3. Enable "Available in MCP" for your workflow 4. Use MCP Client node to call tools ### Method 2: HTTP Request Nodes (Fallback) Use N8N's standard HTTP Request nodes with the REST API: - POST `http://YOUR_IP:3000/api/notes` (Keep Notes REST API) ## ๐Ÿ› ๏ธ Available Tools (19) ### Notes Tools (9) #### 1. **create_note** - Create new note with full support ```json { "name": "create_note", "arguments": { "title": "My Note", "content": "Note content", "color": "blue", "type": "text", "checkItems": [{"id": "1", "text": "Task", "checked": false}], "labels": ["work", "important"], "isPinned": false, "isArchived": false, "images": ["data:image/png;base64,..."], "links": ["https://example.com"], "reminder": "2026-01-20T10:00:00Z", "isReminderDone": false, "reminderRecurrence": "daily", "reminderLocation": "Office", "isMarkdown": false, "size": "medium", "notebookId": "cuid..." } } ``` **New Fields (v2.0):** - `links` - Note links as array - `reminder` - Reminder date/time (ISO 8601) - `isReminderDone` - Mark reminder as done - `reminderRecurrence` - Reminder recurrence (daily, weekly, monthly, yearly) - `reminderLocation` - Reminder location - `isMarkdown` - Enable markdown support - `size` - Note size (small, medium, large) - `notebookId` - Associate note with notebook #### 2. **get_notes** - Get all notes (supports filters) ```json { "name": "get_notes", "arguments": { "includeArchived": false, "search": "optional search query", "notebookId": "cuid...", "fullDetails": false } } ``` **New Filters (v2.0):** - `notebookId` - Filter by notebook - `fullDetails` - Return full details including images (warning: large payload) #### 3. **get_note** - Get specific note by ID ```json { "name": "get_note", "arguments": { "id": "cuid..." } } ``` #### 4. **update_note** - Update existing note Supports all fields from create_note. All are optional except `id`. ```json { "name": "update_note", "arguments": { "id": "cuid...", "title": "Updated Title", "color": "green", "isPinned": true } } ``` #### 5. **delete_note** - Delete note ```json { "name": "delete_note", "arguments": { "id": "cuid..." } } ``` #### 6. **search_notes** - Search notes by query ```json { "name": "search_notes", "arguments": { "query": "project", "notebookId": "cuid..." } } ``` **New (v2.0):** `notebookId` filter support #### 7. **get_labels** - Get all unique labels (legacy method) ```json { "name": "get_labels", "arguments": {} } ``` #### 8. **toggle_pin** - Pin/unpin note ```json { "name": "toggle_pin", "arguments": { "id": "cuid..." } } ``` #### 9. **toggle_archive** - Archive/unarchive note ```json { "name": "toggle_archive", "arguments": { "id": "cuid..." } } ``` ### Notebooks Tools (5) - NEW in v2.0 #### 10. **create_notebook** - Create new notebook ```json { "name": "create_notebook", "arguments": { "name": "Work Projects", "icon": "๐Ÿ’ผ", "color": "#3B82F6", "order": 1 } } ``` **Returns:** Notebook with labels and notes count #### 11. **get_notebooks** - Get all notebooks ```json { "name": "get_notebooks", "arguments": {} } ``` **Returns:** Array of notebooks with labels and notes count #### 12. **get_notebook** - Get notebook with notes ```json { "name": "get_notebook", "arguments": { "id": "cuid..." } } ``` **Returns:** Notebook with labels, notes (parsed), and notes count #### 13. **update_notebook** - Update notebook ```json { "name": "update_notebook", "arguments": { "id": "cuid...", "name": "Updated Name", "icon": "๐Ÿ“", "color": "#10B981" } } ``` #### 14. **delete_notebook** - Delete notebook ```json { "name": "delete_notebook", "arguments": { "id": "cuid..." } } ``` **Warning:** Deletes all notes in the notebook ### Labels Tools (5) - NEW in v2.0 #### 15. **create_label** - Create new label ```json { "name": "create_label", "arguments": { "name": "Important", "color": "red", "notebookId": "cuid..." } } ``` **Required:** `name` and `notebookId` #### 16. **get_labels_detailed** - Get labels with details ```json { "name": "get_labels_detailed", "arguments": { "notebookId": "cuid..." } } ``` **Returns:** Labels with notebook information #### 17. **update_label** - Update label ```json { "name": "update_label", "arguments": { "id": "cuid...", "name": "Updated Name", "color": "blue" } } ``` #### 18. **delete_label** - Delete label ```json { "name": "delete_label", "arguments": { "id": "cuid..." } } ``` ## ๐Ÿงช Testing the SSE Server ### Test 1: Health Check ```bash curl http://localhost:3001/ ``` ### Test 2: SSE Connection ```bash curl -N http://localhost:3001/sse ``` ### Test 3: Call a Tool (get_notes) ```bash 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 }' ``` ### Test 4: Create Note via MCP ```powershell $body = @{ jsonrpc = "2.0" method = "tools/call" params = @{ name = "create_note" arguments = @{ content = "Test from MCP SSE" title = "SSE Test" color = "green" } } id = 1 } | ConvertTo-Json -Depth 5 Invoke-RestMethod -Method POST -Uri "http://localhost:3001/message" ` -Body $body -ContentType "application/json" ``` ### Test 5: Create Notebook ```powershell $body = @{ jsonrpc = "2.0" method = "tools/call" params = @{ name = "create_notebook" arguments = @{ name = "Test Notebook" icon = "๐Ÿ“" color = "#3B82F6" } } id = 1 } | ConvertTo-Json -Depth 5 Invoke-RestMethod -Method POST -Uri "http://localhost:3001/message" ` -Body $body -ContentType "application/json" ``` ### Test 6: Create Label ```powershell $body = @{ jsonrpc = "2.0" method = "tools/call" params = @{ name = "create_label" arguments = @{ name = "Test Label" color = "blue" notebookId = "YOUR_NOTEBOOK_ID" } } id = 1 } | ConvertTo-Json -Depth 5 Invoke-RestMethod -Method POST -Uri "http://localhost:3001/message" ` -Body $body -ContentType "application/json" ``` ## ๐Ÿ”ฅ Troubleshooting ### Error: Prisma Client not initialized **Solution**: Generate Prisma Client: ```bash npx prisma generate ``` ### Error: Port 3001 already in use **Solution 1:** Change port in `index-sse.js`: ```javascript const PORT = process.env.PORT || 3002; ``` **Solution 2:** Kill existing process: ```powershell Get-Process node | Where-Object {$_.Path -like "*index-sse*"} Stop-Process -Id $process.Id ``` ### Error: Cannot connect from N8N **Checklist:** 1. โœ… Server is running (`http://localhost:3001` works locally) 2. โœ… Firewall allows port 3001 3. โœ… Using correct IP address (not `localhost`) 4. โœ… N8N can reach your network 5. โœ… Using `http://` not `https://` **Test connectivity from N8N machine:** ```bash curl http://YOUR_IP:3001/ ``` ### SSE Connection Keeps Dropping This is normal! SSE maintains a persistent connection. If it drops: - Client should automatically reconnect - Check network stability - Verify firewall/proxy settings ## ๐Ÿ”’ Security Notes โš ๏ธ **This server has NO AUTHENTICATION!** For production use: 1. Add API key authentication 2. Use HTTPS with SSL certificates 3. Restrict CORS origins 4. Use environment variables for secrets 5. Deploy behind a reverse proxy (nginx, Caddy) ### Add Basic API Key (Example) ```javascript // In index-sse.js, add middleware: app.use((req, res, next) => { const apiKey = req.headers['x-api-key']; if (apiKey !== process.env.MCP_API_KEY) { return res.status(401).json({ error: 'Unauthorized' }); } next(); }); ``` ## ๐Ÿ“Š Endpoints | Method | Path | Description | |--------|------|-------------| | GET | `/` | Health check | | GET | `/sse` | SSE connection endpoint | | POST | `/message` | MCP message handler | ## ๐Ÿ†š Comparison with REST API | Feature | MCP SSE | REST API | |---------|---------|----------| | **Protocol** | SSE (MCP) | HTTP JSON | | **Port** | 3001 | 3000 (Next.js) | | **Format** | MCP JSON-RPC | REST JSON | | **Use case** | MCP clients | Standard HTTP clients | | **Tools** | 19 MCP tools | 4 CRUD endpoints | **Both work!** Use MCP SSE for proper MCP integration, or REST API for simpler HTTP requests. ## ๐Ÿ”„ Development Workflow ### Running Both Servers **Terminal 1: Next.js + REST API** ```bash cd keep-notes npm run dev # Runs on http://localhost:3000 ``` **Terminal 2: MCP SSE Server** ```bash cd mcp-server npm run start:sse # Runs on http://localhost:3001 ``` **Terminal 3: MCP stdio (for Claude Desktop)** ```bash cd mcp-server npm start # Runs as stdio process ``` ## ๐Ÿ“ Configuration Examples ### N8N Workflow (MCP Client) ```json { "nodes": [ { "name": "Get Keep Notes", "type": "MCP Client", "typeVersion": 1, "position": [250, 300], "parameters": { "server": "keep-notes", "tool": "get_notes", "arguments": { "includeArchived": false } } } ] } ``` ### Create Notebook via MCP ```json { "name": "Create Notebook", "type": "MCP Client", "parameters": { "server": "keep-notes", "tool": "create_notebook", "arguments": { "name": "Work Projects", "icon": "๐Ÿ’ผ", "color": "#3B82F6" } } } ``` ### Create Label via MCP ```json { "name": "Create Label", "type": "MCP Client", "parameters": { "server": "keep-notes", "tool": "create_label", "arguments": { "name": "Important", "color": "red", "notebookId": "WORKBOOK_ID" } } } ``` ### Claude Desktop Config (stdio) Use original `index.js` with stdio: ```json { "mcpServers": { "keep-notes": { "command": "node", "args": ["D:/dev_new_pc/Keep/mcp-server/index.js"] } } } ``` ## ๐Ÿš€ N8N Integration Guide See [N8N-SETUP.md](./N8N-SETUP.md) for complete N8N workflow setup and [N8N-WORKFLOWS.md](./N8N-WORKFLOWS.md) for available workflows. ## ๐Ÿ“š Resources - [MCP Protocol Documentation](https://modelcontextprotocol.io) - [Server-Sent Events Spec](https://html.spec.whatwg.org/multipage/server-sent-events.html) - [N8N MCP Integration Guide](https://community.n8n.io) - [Express.js Documentation](https://expressjs.com) ## ๐Ÿค Support Issues? Check: 1. [START-SSE.md](./START-SSE.md) - Quick start guide 2. [README.md](../README.md) - Main project README 3. [COMPLETED-FEATURES.md](../COMPLETED-FEATURES.md) - Implementation details --- **Version**: 2.0.0 **Last Updated**: January 18, 2026 **Status**: โœ… Production Ready