- Unified localStorage key to 'theme-preference' across all components
- Fixed header.tsx using wrong localStorage key ('theme' instead of 'theme-preference')
- Added localStorage hybrid persistence for instant theme changes
- Removed router.refresh() which was causing stale data revert
- Replaced Blue theme with Sepia
- Consolidated auth() calls to prevent race conditions
- Updated UserSettingsData types to include all themes
12 KiB
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
cd mcp-server
npm install
2. Start Server
Option A: PowerShell Script (Recommended)
.\start-sse.ps1
Option B: Direct Node
npm run start:sse
# or
node index-sse.js
3. Verify Server is Running
Open browser to: http://localhost:3001
You should see:
{
"name": "Keep Notes MCP SSE Server",
"version": "2.0.0",
"status": "running",
"endpoints": {
"sse": "/sse",
"message": "/message"
}
}
🌐 Get Your IP Address
Windows
ipconfig
Look for "IPv4 Address" (usually 192.168.x.x)
Mac/Linux
ifconfig
# or
ip addr show
🔌 N8N Configuration
Method 1: MCP Client Community Node
If your N8N has MCP Client node installed:
-
Open N8N Settings → MCP Access
-
Add new server:
{ "name": "keep-notes", "transport": "sse", "url": "http://YOUR_IP:3001/sse" }Replace
YOUR_IPwith your machine's IP (e.g.,192.168.1.100) -
Enable "Available in MCP" for your workflow
-
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
{
"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 arrayreminder- Reminder date/time (ISO 8601)isReminderDone- Mark reminder as donereminderRecurrence- Reminder recurrence (daily, weekly, monthly, yearly)reminderLocation- Reminder locationisMarkdown- Enable markdown supportsize- Note size (small, medium, large)notebookId- Associate note with notebook
2. get_notes - Get all notes (supports filters)
{
"name": "get_notes",
"arguments": {
"includeArchived": false,
"search": "optional search query",
"notebookId": "cuid...",
"fullDetails": false
}
}
New Filters (v2.0):
notebookId- Filter by notebookfullDetails- Return full details including images (warning: large payload)
3. get_note - Get specific note by ID
{
"name": "get_note",
"arguments": {
"id": "cuid..."
}
}
4. update_note - Update existing note
Supports all fields from create_note. All are optional except id.
{
"name": "update_note",
"arguments": {
"id": "cuid...",
"title": "Updated Title",
"color": "green",
"isPinned": true
}
}
5. delete_note - Delete note
{
"name": "delete_note",
"arguments": {
"id": "cuid..."
}
}
6. search_notes - Search notes by query
{
"name": "search_notes",
"arguments": {
"query": "project",
"notebookId": "cuid..."
}
}
New (v2.0): notebookId filter support
7. get_labels - Get all unique labels (legacy method)
{
"name": "get_labels",
"arguments": {}
}
8. toggle_pin - Pin/unpin note
{
"name": "toggle_pin",
"arguments": {
"id": "cuid..."
}
}
9. toggle_archive - Archive/unarchive note
{
"name": "toggle_archive",
"arguments": {
"id": "cuid..."
}
}
Notebooks Tools (5) - NEW in v2.0
10. create_notebook - Create new notebook
{
"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
{
"name": "get_notebooks",
"arguments": {}
}
Returns: Array of notebooks with labels and notes count
12. get_notebook - Get notebook with notes
{
"name": "get_notebook",
"arguments": {
"id": "cuid..."
}
}
Returns: Notebook with labels, notes (parsed), and notes count
13. update_notebook - Update notebook
{
"name": "update_notebook",
"arguments": {
"id": "cuid...",
"name": "Updated Name",
"icon": "📁",
"color": "#10B981"
}
}
14. delete_notebook - Delete notebook
{
"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
{
"name": "create_label",
"arguments": {
"name": "Important",
"color": "red",
"notebookId": "cuid..."
}
}
Required: name and notebookId
16. get_labels_detailed - Get labels with details
{
"name": "get_labels_detailed",
"arguments": {
"notebookId": "cuid..."
}
}
Returns: Labels with notebook information
17. update_label - Update label
{
"name": "update_label",
"arguments": {
"id": "cuid...",
"name": "Updated Name",
"color": "blue"
}
}
18. delete_label - Delete label
{
"name": "delete_label",
"arguments": {
"id": "cuid..."
}
}
🧪 Testing the SSE Server
Test 1: Health Check
curl http://localhost:3001/
Test 2: SSE Connection
curl -N http://localhost:3001/sse
Test 3: Call a Tool (get_notes)
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
$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
$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
$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:
npx prisma generate
Error: Port 3001 already in use
Solution 1: Change port in index-sse.js:
const PORT = process.env.PORT || 3002;
Solution 2: Kill existing process:
Get-Process node | Where-Object {$_.Path -like "*index-sse*"}
Stop-Process -Id $process.Id
Error: Cannot connect from N8N
Checklist:
- ✅ Server is running (
http://localhost:3001works locally) - ✅ Firewall allows port 3001
- ✅ Using correct IP address (not
localhost) - ✅ N8N can reach your network
- ✅ Using
http://nothttps://
Test connectivity from N8N machine:
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:
- Add API key authentication
- Use HTTPS with SSL certificates
- Restrict CORS origins
- Use environment variables for secrets
- Deploy behind a reverse proxy (nginx, Caddy)
Add Basic API Key (Example)
// 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
cd keep-notes
npm run dev
# Runs on http://localhost:3000
Terminal 2: MCP SSE Server
cd mcp-server
npm run start:sse
# Runs on http://localhost:3001
Terminal 3: MCP stdio (for Claude Desktop)
cd mcp-server
npm start
# Runs as stdio process
📝 Configuration Examples
N8N Workflow (MCP Client)
{
"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
{
"name": "Create Notebook",
"type": "MCP Client",
"parameters": {
"server": "keep-notes",
"tool": "create_notebook",
"arguments": {
"name": "Work Projects",
"icon": "💼",
"color": "#3B82F6"
}
}
}
Create Label via MCP
{
"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:
{
"mcpServers": {
"keep-notes": {
"command": "node",
"args": ["D:/dev_new_pc/Keep/mcp-server/index.js"]
}
}
}
🚀 N8N Integration Guide
See N8N-SETUP.md for complete N8N workflow setup and N8N-WORKFLOWS.md for available workflows.
📚 Resources
- MCP Protocol Documentation
- Server-Sent Events Spec
- N8N MCP Integration Guide
- Express.js Documentation
🤝 Support
Issues? Check:
- START-SSE.md - Quick start guide
- README.md - Main project README
- COMPLETED-FEATURES.md - Implementation details
Version: 2.0.0 Last Updated: January 18, 2026 Status: ✅ Production Ready