fix: unify theme system - fix theme switching persistence

- 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
This commit is contained in:
2026-01-18 22:33:41 +01:00
parent ef60dafd73
commit ddb67ba9e5
306 changed files with 59580 additions and 6063 deletions

View File

@@ -1,36 +1,41 @@
# Memento MCP SSE Server
# Keep Notes MCP SSE Server
Server-Sent Events (SSE) version of the Memento MCP Server for remote N8N access.
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 Memento via HTTP/SSE instead of stdio.
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 |
|| 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 the Server
### 2. Start Server
**Option A: PowerShell Script (Recommended)**
```powershell
.\start-sse.ps1
```
**Option B: Direct Node**
```bash
npm run start:sse
# or
@@ -42,10 +47,11 @@ node index-sse.js
Open browser to: `http://localhost:3001`
You should see:
```json
{
"name": "Memento MCP SSE Server",
"version": "1.0.0",
"name": "Keep Notes MCP SSE Server",
"version": "2.0.0",
"status": "running",
"endpoints": {
"sse": "/sse",
@@ -57,12 +63,15 @@ You should see:
## 🌐 Get Your IP Address
### Windows
```powershell
ipconfig
```
Look for "IPv4 Address" (usually 192.168.x.x)
### Mac/Linux
```bash
ifconfig
# or
@@ -73,13 +82,13 @@ ip addr show
### Method 1: MCP Client Community Node
If your N8N has the MCP Client node installed:
If your N8N has MCP Client node installed:
1. Open N8N Settings → MCP Access
2. Add new server:
```json
{
"name": "memento",
"name": "keep-notes",
"transport": "sse",
"url": "http://YOUR_IP:3001/sse"
}
@@ -92,57 +101,289 @@ If your N8N has the MCP Client node installed:
### Method 2: HTTP Request Nodes (Fallback)
Use N8N's standard HTTP Request nodes with the REST API:
- POST `http://YOUR_IP:3000/api/notes` (Memento REST API)
- POST `http://YOUR_IP:3000/api/notes` (Keep Notes REST API)
## 🛠️ Available Tools (9)
## 🛠️ Available Tools (19)
All tools from the stdio version are available:
### Notes Tools (9)
1. **create_note** - Create new note
```json
{
"name": "create_note",
"arguments": {
"content": "My note",
"title": "Optional title",
"color": "blue",
"images": ["data:image/png;base64,..."]
}
}
```
#### 1. **create_note** - Create new note with full support
2. **get_notes** - Get all notes
```json
{
"name": "get_notes",
"arguments": {
"includeArchived": false,
"search": "optional search query"
}
}
```
```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..."
}
}
```
3. **get_note** - Get specific note by ID
4. **update_note** - Update existing note
5. **delete_note** - Delete note
6. **search_notes** - Search notes
7. **get_labels** - Get all unique labels
8. **toggle_pin** - Pin/unpin note
9. **toggle_archive** - Archive/unarchive note
**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" \
@@ -158,6 +399,7 @@ curl -X POST http://localhost:3001/message \
```
### Test 4: Create Note via MCP
```powershell
$body = @{
jsonrpc = "2.0"
@@ -177,38 +419,81 @@ 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 in the main app:
**Solution**: Generate Prisma Client:
```bash
cd ..\keep-notes
npx prisma generate
```
### Error: Port 3001 already in use
**Solution**: Change port in `index-sse.js`:
**Solution 1:** Change port in `index-sse.js`:
```javascript
const PORT = process.env.PORT || 3002;
```
Or set environment variable:
**Solution 2:** Kill existing process:
```powershell
$env:PORT=3002; node index-sse.js
Get-Process node | Where-Object {$_.Path -like "*index-sse*"}
Stop-Process -Id $process.Id
```
### Error: Cannot connect from N8N
**Checklist**:
**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**:
**Test connectivity from N8N machine:**
```bash
curl http://YOUR_IP:3001/
```
@@ -260,7 +545,7 @@ app.use((req, res, next) => {
| **Port** | 3001 | 3000 (Next.js) |
| **Format** | MCP JSON-RPC | REST JSON |
| **Use case** | MCP clients | Standard HTTP clients |
| **Tools** | 9 MCP tools | 4 CRUD endpoints |
| **Tools** | 19 MCP tools | 4 CRUD endpoints |
**Both work!** Use MCP SSE for proper MCP integration, or REST API for simpler HTTP requests.
@@ -297,12 +582,12 @@ npm start
{
"nodes": [
{
"name": "Get Memento Notes",
"name": "Get Keep Notes",
"type": "MCP Client",
"typeVersion": 1,
"position": [250, 300],
"parameters": {
"server": "memento",
"server": "keep-notes",
"tool": "get_notes",
"arguments": {
"includeArchived": false
@@ -313,13 +598,49 @@ npm start
}
```
### 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 the original `index.js` with stdio:
Use original `index.js` with stdio:
```json
{
"mcpServers": {
"memento": {
"keep-notes": {
"command": "node",
"args": ["D:/dev_new_pc/Keep/mcp-server/index.js"]
}
@@ -327,6 +648,10 @@ Use the original `index.js` with stdio:
}
```
## 🚀 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)
@@ -337,12 +662,12 @@ Use the original `index.js` with stdio:
## 🤝 Support
Issues? Check:
1. [MCP-SSE-ANALYSIS.md](../MCP-SSE-ANALYSIS.md) - Detailed SSE analysis
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**: 1.0.0
**Last Updated**: January 4, 2026
**Version**: 2.0.0
**Last Updated**: January 18, 2026
**Status**: ✅ Production Ready