Model Context Protocol (MCP) server for the Joplin note-taking app.
Designed by belsar.ai to be easy to install & enjoyable to use.
https://www.youtube.com/watch?v=B3qJa7ycqNM&t=6s
This MCP server uses a Script Execution architecture. Instead of exposing 30+ restricted tools, it exposes a single, powerful tool: execute_joplin_script.
This allows the AI to write and execute secure JavaScript/TypeScript code to interact with your Joplin instance. This enables:
- Complex Workflows: "Find all notes tagged 'work' and append a checklist to them" (1 turn vs. 50 turns).
- Data Processing: Filter, sort, and aggregate data using standard JS array methods.
- Efficiency: Drastically reduces context usage and latency.
- Open Joplin & navigate to tools > web clipper > enable web clipper service
- The Joplin app needs to remain running (minimized is fine)
- Pick the install command for your platform:
claude mcp add --transport stdio joplin -- npx -y @belsar-ai/joplin-mcpcodex mcp add joplin -- npx -y @belsar-ai/joplin-mcpgemini extensions install https://github.com/belsar-ai/joplin-mcp- That's it. Send a test request like "Find my notes about installing Fedora linux".
Create .mcp-config/joplin-mcp.toml in your project root to scope which notebooks are visible:
[defaults]
notebook = "Notes"
[scope]
notebooks = ["Notes", "Software"]defaults.notebook: Where new notes go if you don't specify a notebookscope.notebooks: Only these notebooks are visible to the AI
The config file is discovered by walking up from the current directory (like .git).
To uninstall:
claude mcp remove joplincodex mcp remove joplingemini extensions uninstall joplin-mcpThe AI can now handle complex requests in a single shot:
Find my notes about installing Arch Linux.
Look for all notes whose last update time was before 2025. tag those as 'archived'.
Show me all notes in my Work Projects notebook.
Make a new note with a Mermaid diagram showing how a bill is passed on Capitol Hill.
The AI has access to a global joplin object with the following methods:
searchNotes(query: string): Smart search with "any:1" logic.listAllNotes(fields?, ...): Get all notes.getNote(id): Get full note content.createNote(title, body, notebookId, ...): Create a new note.updateNote(id, updates): Update properties or body.appendToNote(id, text): Add text to the end.prependToNote(id, text): Add text to the beginning.deleteNote(id): Move to trash.
listNotebooks(): Get folder structure.getNotebookTree(notebookId, depth?): Get formatted tree of a notebook with notes (📁/📝).getAllNotebooksTree({ exclude? }): Get formatted tree of all notebooks (📁 only).getScopedTree({ exclude?, depth? }): Get formatted tree of scoped notebooks with notes.createNotebook(title, parentId?)updateNotebook(id, updates)deleteNotebook(id)
listTags()getNotesByTagName(tagName): Find notes by tag name.addTagsToNote(noteId, tags): e.g., "urgent, work"removeTagsFromNote(noteId, tags)createTag(title)
- Verify Joplin desktop app is running
- Confirm Web Clipper is enabled in Joplin settings
- Ensure Joplin is listening on port 41184 (default)
- If auto-discovery fails, set
JOPLIN_TOKENin your environment (add to.bashrcor shell config) - Go outside for a nice walk