# Technical Design Document: Trilium MCP Server
## 1. Introduction
The Trilium MCP Server provides a Model Context Protocol (MCP) interface to Trilium Notes, allowing LLMs to search, read, and manipulate notes within a Trilium instance. This implementation is built in Python with minimal dependencies and communicates over STDIO.
## 2. Requirements
- Python 3.x
- `requests` library for HTTP communication with Trilium.
- No external MCP framework (e.g., `mcp-python-sdk`).
- Communication via JSON-RPC 2.0 over STDIO.
## 3. Architecture
### 3.1. MCP Protocol Layer
Handles the low-level JSON-RPC communication:
- **Main Loop:** Reads from `sys.stdin` line-by-line.
- **JSON-RPC Parser:**
- Validates `jsonrpc`, `id`, `method`.
- Maps `initialize`, `initialized`, `tools/list`, `tools/call` to specific functions.
- **ResponseWriter:**
- Formats results as `{"jsonrpc": "2.0", "id": <id>, "result": <result>}`.
- Formats errors as `{"jsonrpc": "2.0", "id": <id>, "error": {"code": <code>, "message": <message>}}`.
- Writes to `sys.stdout` followed by a newline and `sys.stdout.flush()`.
- **Error Handling:** Standard codes:
- `-32700`: Parse error
- `-32600`: Invalid Request
- `-32601`: Method not found
- `-32602`: Invalid params
- `-32603`: Internal error
### 3.2. Trilium API Client
A thin wrapper around `requests` to interact with the Trilium ETAPI:
- **Authentication:** Uses the Trilium ETAPI token (passed via environment variable `TRILIUM_TOKEN`).
- **Base URL:** Configuration via `TRILIUM_URL`.
- **Endpoints:**
- `GET /etapi/notes/{noteId}`: Fetch note metadata and content.
- `GET /etapi/notes/{noteId}/children`: List child notes.
- `POST /etapi/notes`: Create new notes.
- `PATCH /etapi/notes/{noteId}`: Update note content/metadata.
- `GET /etapi/notes-search`: Search for notes using Trilium's search syntax.
### 3.3. Tools Implementation
The following MCP tools will be exposed via `tools/list` and `tools/call`:
- `search_notes(query: string)`:
- Calls `GET /etapi/notes-search?query={query}`.
- Returns a list of note metadata (noteId, title, type).
- `get_note_content(noteId: string)`:
- Calls `GET /etapi/notes/{noteId}/content`.
- Returns the raw content of the note (likely HTML).
- `get_note_metadata(noteId: string)`:
- Calls `GET /etapi/notes/{noteId}`.
- Returns full note attributes, including tags and properties.
- `create_note(parentNoteId: string, title: string, content: string, type: string = "text")`:
- Calls `POST /etapi/notes` with given parameters.
- Defaults `parentNoteId` to `root` if not provided.
- `update_note_content(noteId: string, content: string)`:
- Calls `PATCH /etapi/notes/{noteId}/content` (or similar endpoint).
- Updates the content of an existing note.
- `get_note_children(noteId: string)`:
- Calls `GET /etapi/notes/{noteId}/children`.
- Returns a list of children for the specified note.
## 4. Implementation Details
### 4.1. Message Handling
The server will follow the MCP lifecycle:
1. **Initialize:** Receive `initialize` request, return server capabilities (tools).
2. **Initialized:** Receive `notifications/initialized`.
3. **Operation:** Handle `list_tools` and `call_tool`.
### 4.2. File Structure
- `server.py`: Main entry point, JSON-RPC loop.
- `trilium_client.py`: Trilium ETAPI interaction logic.
- `handlers.py`: Mapping of MCP tool calls to Trilium client calls.
## 5. Security & Configuration
- **Environment Variables:**
- `TRILIUM_URL`: URL of the Trilium instance (e.g., `http://localhost:8080`).
- `TRILIUM_TOKEN`: ETAPI token for authentication.
- **Note on Safety:** Destructive operations (delete) will be omitted in the initial version to prevent accidental data loss.
## 6. Verification Plan
- **Unit Tests:** Mock the `requests` calls and test the Trilium client logic.
- **Integration Tests:** Use a local Trilium instance to verify tool functionality.
- **MCP Validation:** Manually test the JSON-RPC interface using a tool like `mcp-inspector`.