{
  "markdown": "# Joplin MCP Server\n\nA **FastMCP-based Model Context Protocol (MCP) server** for [Joplin](https://joplinapp.org/) note-taking application via its Python API [joppy](https://github.com/marph91/joppy), enabling AI assistants to interact with your Joplin notes, notebooks, and tags through a standardized interface.\n\n<!-- mcp-name: io.github.alondmnt/joplin-mcp -->\n\n## Table of Contents\n\n- [What You Can Do](#what-you-can-do)\n- [Quick Start](#quick-start)\n- [Supported Clients](#supported-clients)\n- [Example Usage](#example-usage)\n- [Tool Permissions](#tool-permissions)\n- [Notebook Allowlist](#notebook-allowlist)\n- [Advanced Configuration](#advanced-configuration)\n- [Docker](#docker)\n- [Project Structure](#project-structure)\n- [Testing](#testing)\n- [Complete Tool Reference](#complete-tool-reference)\n- [Changelog](CHANGELOG.md)\n\n## What You Can Do\n\nThis MCP server provides **26 optimized tools** for comprehensive Joplin integration:\n\n### **Note Management**\n- **Find & Search**: `find_notes` (supports `trash=True` for trashed notes), `find_notes_with_tag`, `find_notes_in_notebook`, `get_all_notes`\n- **CRUD Operations**: `get_note`, `get_note_resources` (read OCR text from attached images/PDFs), `get_links`, `create_note`, `update_note`, `edit_note`, `delete_note`\n\n### **Notebook Management** \n- **Organize**: `list_notebooks`, `create_notebook`, `update_notebook`, `delete_notebook`\n\n### **Tag Management**\n- **Categorize**: `list_tags`, `create_tag`, `update_tag`, `delete_tag`, `get_tags_by_note`\n- **Link**: `tag_note`, `untag_note`\n\n### **Trash Management**\n- **Recover**: `restore_from_trash` - Restore soft-deleted notes or notebooks\n\n### **Import**\n- **File Import**: `import_from_file` - Import Markdown, HTML, CSV, TXT, JEX files and directories\n\n### **System**\n- **Health**: `ping_joplin`\n\n## Quick Start\n\n1. Open **Joplin Desktop** → **Tools** → **Options** → **Web Clipper**\n2. **Enable** the Web Clipper service\n3. **Copy** the Authorization token\n4. Set up your preferred client below\n\n## Supported Clients\n\n> Any MCP-compatible client should work. Below are the ones with documented setup instructions.\n\n### Claude Desktop\n\nRun the automated installer:\n\n```bash\n# Install and configure everything automatically (pip)\npip install joplin-mcp\njoplin-mcp-install\n\n# Or use zero-install with uvx (recommended if you have uv)\nuvx --from joplin-mcp joplin-mcp-install\n\n# Optional: pin a specific version/range for stability\nuvx --from joplin-mcp==0.4.1 joplin-mcp-install\nuvx --from 'joplin-mcp>=0.4,<0.5' joplin-mcp-install\n```\n\nThis script will:\n- Configure your Joplin API token\n- Set tool permissions (Create/Update/Delete)\n- Set up Claude Desktop automatically\n- Test the connection\n\nAfter setup, restart Claude Desktop and you're ready to go!\n\n### Claude Code\n\nInstall the orchestration plugin for smarter tool usage (edit vs update, long-note reading, bulk tagging):\n\n```bash\n/plugin marketplace add alondmnt/joplin-mcp\n/plugin install joplin-mcp\n```\n\nYou'll be prompted for your Joplin API token on first use. The skill is invoked automatically when working with Joplin tools, or manually with `/joplin`.\n\n### Jan AI\n\n1. **Install Jan AI** from [https://jan.ai](https://jan.ai)\n\n2. **Add MCP Server** in Jan's interface:\n   - Open Jan AI\n   - Go to **Settings** → **Extensions** → **Model Context Protocol**\n   - Click **Add MCP Server**\n   - Configure:\n     - **Name**: `joplin`\n     - **Command**: `uvx --from joplin-mcp joplin-mcp-server` *(requires `uv` installed)*\n     - **Environment Variables**:\n       - `JOPLIN_TOKEN`: `your_joplin_api_token_here`\n   - Enable the server\n\n3. **Start chatting** with access to your Joplin notes!\n\n**Automated Setup (Alternative)**\n\n```bash\n# Install and configure Jan AI automatically (if Jan is already installed)\npip install joplin-mcp\njoplin-mcp-install\n```\n\nThis will detect and configure Jan AI automatically, just like Claude Desktop.\n\n### OllMCP (Local Ollama Models)\n\n**Auto-discovery (if you set up Claude Desktop first)**\n```bash\n# Install ollmcp\npip install ollmcp\n\n# Run with auto-discovery (requires existing Claude Desktop config)\nollmcp --auto-discovery --model qwen3:4b\n```\n\n**Manual setup (works independently)**\n```bash\n# Install ollmcp\npip install ollmcp\n\n# Set environment variable\nexport JOPLIN_TOKEN=\"your_joplin_api_token_here\"\n\n# Run with uvx (requires uv installed)\nollmcp --server \"joplin:uvx --from joplin-mcp joplin-mcp-server\" --model qwen3:4b\n\n# Or with an installed package (pip install joplin-mcp)\nollmcp --server \"joplin:joplin-mcp-server\" --model qwen3:4b\n```\n\n## Example Usage\n\nOnce configured, you can ask your AI assistant:\n\n- **\"List all my notebooks\"** - See your Joplin organization\n- **\"Find notes about Python programming\"** - Search your knowledge base  \n- **\"Create a meeting note for today's standup\"** - Quick note creation\n- **\"Tag my recent AI notes as 'important'\"** - Organize with tags\n- **\"Show me my todos\"** - Find task items with `find_notes(task=True)`\n\n## Tool Permissions\n\nThe setup script offers **4 permission levels**:\n\n- **Read** (always enabled): Browse and search your notes safely\n- **Write** (optional): Create new notes, notebooks, and tags\n- **Update** (optional): Modify existing content\n- **Delete** (optional): Remove content permanently\n\nChoose the level that matches your comfort and use case.\n\n## Notebook Allowlist\n\nRestrict AI access to specific notebooks using pattern-based access control. When configured, only matching notebooks (and their contents) are visible — all other notebooks are hidden.\n\n### Quick Setup\n\n**JSON config** (`joplin-mcp.json`):\n```json\n{\n  \"token\": \"your_token\",\n  \"notebook_allowlist\": [\"Work\", \"Projects/Public\"]\n}\n```\n\n**Environment variable**:\n```bash\nexport JOPLIN_NOTEBOOK_ALLOWLIST=\"Work,Projects/Public\"\n```\n\n### Pattern Syntax\n\nPatterns use [gitignore/gitwildmatch](https://git-scm.com/docs/gitignore) semantics:\n\n| Pattern | Matches | Example |\n|---------|---------|---------|\n| `Work` | Exact notebook name (and all children) | `Work`, `Work/Tasks`, `Work/Notes` |\n| `Projects/*` | Direct children of Projects | `Projects/Alpha`, `Projects/Beta` |\n| `Projects/**` | All descendants recursively | `Projects/Alpha/Tasks/Q1` |\n| `!Projects/Secret` | Exclude (negate) a specific path | Everything in Projects *except* Secret |\n\nNegation patterns always win over positive patterns (any negation match on a path or ancestor denies access).\n\n### How It Works\n\n- **Hierarchical access**: Allowing a parent notebook grants access to all its children. Allowing `Projects` means notes in `Projects/Work/Tasks` are also accessible.\n- **Read protection**: `get_note`, `get_note_resources`, `find_notes`, `get_links` — notes in blocked notebooks are filtered out or rejected.\n- **Write protection**: `create_note`, `update_note`, `edit_note`, `delete_note` — operations on notes in blocked notebooks are rejected.\n- **Notebook operations**: `list_notebooks` only shows accessible notebooks. `create_notebook` is rejected both under a blocked parent and at the top level (no `parent_name`) when an allowlist is set, and `update_notebook` rejects moves to top-level (`parent_name=\"/\"`) under the same policy — both would let the agent silently move a notebook out of allowlist-enforced scope. To grow the allowlist, create or relocate the notebook in the Joplin UI, then add it to `notebook_allowlist` and restart the server.\n- **Search filtering**: `find_notes` results are filtered to only include notes in accessible notebooks.\n- **Tag operations**: `tag_note`, `untag_note`, `get_tags_by_note` enforce access on the note's notebook.\n- **Error privacy**: Blocked access raises a generic \"Notebook not accessible\" error without revealing notebook names or IDs.\n\n### Configuration Examples\n\n**Single project focus** (notebook name containing a space):\n```json\n{ \"notebook_allowlist\": [\"Work Projects\"] }\n```\n\n**Multiple notebooks with exclusion:**\n```json\n{ \"notebook_allowlist\": [\"Projects\", \"!Projects/Secret\", \"AI\", \"Reference\"] }\n```\n\n**Glob patterns:**\n```json\n{ \"notebook_allowlist\": [\"Projects/*\", \"!Projects/Private\"] }\n```\n\n**No allowlist (default)** — all notebooks accessible:\n```json\n{ \"notebook_allowlist\": null }\n```\n\n### Startup Behavior\n\nAt server startup, the allowlist is validated and logged:\n- Each entry is resolved against existing notebooks\n- Unresolvable patterns trigger warnings (but never block startup)\n- If the allowlist resolves to zero accessible notebooks, a warning is logged\n\n---\n\n## Advanced Configuration\n\n### Development Installation\n\nFor developers or users who want the latest features:\n\n```bash\ngit clone https://github.com/alondmnt/joplin-mcp.git\ncd joplin-mcp\npython bootstrap.py\n```\n\n`bootstrap.py` is cross-platform: it offers to create a `./venv`, runs `pip install -e .`, then launches the interactive installer. Pass `--no-venv` to install into whichever Python is already active.\n\n### Manual Configuration\n\nIf you prefer manual setup or the script doesn't work:\n\n> Note on `uvx`: `uvx` runs Python applications without permanently installing them (requires `uv`: `pip install uv`). It can read and write user configuration files (e.g., Claude/Jan configs), so `uvx --from joplin-mcp joplin-mcp-install` works for setup just like a pip install.\n\n> Version pinning (optional): For long‑lived client configs or CI, you can pin or range-constrain the version for reproducibility, e.g. `uvx --from joplin-mcp==0.4.1 joplin-mcp-install` or `uvx --from 'joplin-mcp>=0.4,<0.5' joplin-mcp-install`.\n\n#### 1. Create Configuration File\n\nCreate `joplin-mcp.json` in your project directory:\n\n```json\n{\n  \"token\": \"your_api_token_here\",\n  \"host\": \"localhost\", \n  \"port\": 41184,\n  \"timeout\": 30,\n  \"verify_ssl\": false\n}\n```\n\n#### 2. Claude Desktop Configuration\n\nAdd to your `claude_desktop_config.json`:\n\n**Option A: Using uvx (Zero-install)**\n```json\n{\n  \"mcpServers\": {\n    \"joplin\": {\n      \"command\": \"uvx\",\n      \"args\": [\"--from\", \"joplin-mcp\", \"joplin-mcp-server\"],\n      \"env\": {\n        \"JOPLIN_TOKEN\": \"your_token_here\"\n      }\n    }\n  }\n}\n```\n*Requires `uv` installed: `pip install uv`*\n\n**Option B: Using installed package**\n```json\n{\n  \"mcpServers\": {\n    \"joplin\": {\n      \"command\": \"joplin-mcp-server\",\n      \"env\": {\n        \"JOPLIN_TOKEN\": \"your_token_here\"\n      }\n    }\n  }\n}\n```\n\n#### 3. More Client Configuration Examples\n\nFor additional client configurations including different transport options (HTTP, SSE, Streamable HTTP), see [client-config.json.example](client-config.json.example).\n\nThis file includes configurations for:\n- **STDIO transport** (default, most compatible)\n- **HTTP transport** (basic HTTP server mode)\n- **SSE transport** (recommended for gemini-cli and OpenAI clients)\n- **Streamable HTTP transport** (advanced web clients)\n- **HTTP-compat transport** (bridges modern `/mcp` JSON-RPC with legacy `/sse`/`/messages` clients)\n\n### Tool Permission Configuration\n\nFine-tune which operations the AI can perform by editing your config:\n\n```json\n{\n  \"tools\": {\n    \"create_note\": true,\n    \"update_note\": true,\n    \"delete_note\": false,\n    \"create_notebook\": true,\n    \"update_notebook\": false,\n    \"delete_notebook\": false,\n    \"create_tag\": true,\n    \"update_tag\": false,\n    \"delete_tag\": false,\n    \"get_all_notes\": false,\n    \"import_from_file\": true\n  }\n}\n```\n\n### Environment Variables\n\nUsable instead of a JSON config file, or alongside one:\n\n```bash\n# Connection settings\nexport JOPLIN_TOKEN=\"your_api_token_here\"\nexport JOPLIN_HOST=\"localhost\"\nexport JOPLIN_PORT=\"41184\"\nexport JOPLIN_TIMEOUT=\"30\"\n```\n\nEnvironment variables override the config file key by key, so the `env`\nblock in your MCP client's configuration wins over whatever file the\nserver discovers. A variable only takes part when it is actually set, so\nsetting one leaves the rest of your file alone. Full order: direct\nparameters > environment > config file > defaults.\n\n#### Per-Tool Env Vars\n\nEvery tool can be toggled individually via `JOPLIN_TOOL_<NAME>=true|false`. These take precedence over config file settings.\n\n| Env var | Default |\n|---------|---------|\n| `JOPLIN_TOOL_FIND_NOTES` | `true` |\n| `JOPLIN_TOOL_FIND_NOTES_WITH_TAG` | `true` |\n| `JOPLIN_TOOL_FIND_NOTES_IN_NOTEBOOK` | `true` |\n| `JOPLIN_TOOL_FIND_IN_NOTE` | `true` |\n| `JOPLIN_TOOL_GET_ALL_NOTES` | `false` |\n| `JOPLIN_TOOL_GET_NOTE` | `true` |\n| `JOPLIN_TOOL_GET_LINKS` | `true` |\n| `JOPLIN_TOOL_CREATE_NOTE` | `true` |\n| `JOPLIN_TOOL_UPDATE_NOTE` | `true` |\n| `JOPLIN_TOOL_EDIT_NOTE` | `true` |\n| `JOPLIN_TOOL_DELETE_NOTE` | `false` |\n| `JOPLIN_TOOL_LIST_NOTEBOOKS` | `true` |\n| `JOPLIN_TOOL_CREATE_NOTEBOOK` | `true` |\n| `JOPLIN_TOOL_UPDATE_NOTEBOOK` | `false` |\n| `JOPLIN_TOOL_DELETE_NOTEBOOK` | `false` |\n| `JOPLIN_TOOL_LIST_TAGS` | `true` |\n| `JOPLIN_TOOL_CREATE_TAG` | `true` |\n| `JOPLIN_TOOL_UPDATE_TAG` | `false` |\n| `JOPLIN_TOOL_DELETE_TAG` | `false` |\n| `JOPLIN_TOOL_GET_TAGS_BY_NOTE` | `true` |\n| `JOPLIN_TOOL_TAG_NOTE` | `true` |\n| `JOPLIN_TOOL_UNTAG_NOTE` | `true` |\n| `JOPLIN_TOOL_PING_JOPLIN` | `true` |\n| `JOPLIN_TOOL_RESTORE_FROM_TRASH` | `true` |\n| `JOPLIN_TOOL_IMPORT_FROM_FILE` | `false` |\n\n#### Notebook Allowlist Env Var\n\n| Env var | Default | Description |\n|---------|---------|-------------|\n| `JOPLIN_NOTEBOOK_ALLOWLIST` | *(not set)* | Comma-separated list of notebook patterns (e.g., `Work,Projects/*,!Projects/Secret`). Not set means no restriction; set but empty denies every notebook |\n\n### HTTP Transport Support\n\nThe server supports both STDIO and HTTP transports:\n\n```bash\n# STDIO (default)\njoplin-mcp-server --config ~/.joplin-mcp.json\n\n# HTTP transport (development, from repo)\nPYTHONPATH=src python -m joplin_mcp.server --transport http --port 8000 --config ./joplin-mcp.json\n\n# Opt-in HTTP compatibility bundle (modern + legacy SSE endpoints)\nPYTHONPATH=src python -m joplin_mcp.server --transport http-compat --port 8000 --config ./joplin-mcp.json\n# or keep --transport http and export MCP_HTTP_COMPAT=1/true to toggle the same behavior.\n```\n\n#### HTTP client config\n\nNote: Claude Desktop currently uses STDIO transport and does not consume HTTP/SSE configs directly. The following example applies to clients that support network transports.\n```json\n{\n  \"mcpServers\": {\n    \"joplin\": {\n      \"transport\": \"http\",\n      \"url\": \"http://localhost:8000/mcp\"\n    }\n  }\n}\n```\n\n### Configuration Reference\n\n#### Basic Settings\n| Option | Default | Description |\n|--------|---------|-------------|\n| `token` | *required* | Joplin API authentication token |\n| `host` | `localhost` | Joplin server hostname |\n| `port` | `41184` | Joplin Web Clipper port |\n| `timeout` | `30` | Request timeout in seconds |\n| `verify_ssl` | `false` | SSL certificate verification |\n\n#### Tool Permissions\n| Option | Default | Description |\n|--------|---------|-------------|\n| `tools.create_note` | `true` | Allow creating new notes |\n| `tools.update_note` | `true` | Allow modifying existing notes |\n| `tools.edit_note` | `true` | Allow precision edits (find/replace, append, prepend) |\n| `tools.delete_note` | `false` | Allow deleting notes *(disabled by default — destructive)* |\n| `tools.create_notebook` | `true` | Allow creating new notebooks |\n| `tools.update_notebook` | `false` | Allow modifying notebook titles and emoji icons |\n| `tools.delete_notebook` | `false` | Allow deleting notebooks *(disabled by default — destructive)* |\n| `tools.create_tag` | `true` | Allow creating new tags |\n| `tools.update_tag` | `false` | Allow modifying tag titles |\n| `tools.delete_tag` | `false` | Allow deleting tags *(disabled by default — destructive)* |\n| `tools.tag_note` | `true` | Allow adding tags to notes |\n| `tools.untag_note` | `true` | Allow removing tags from notes |\n| `tools.restore_from_trash` | `true` | Allow restoring soft-deleted notes or notebooks |\n| `tools.find_notes` | `true` | Allow text search across notes (with task filtering) |\n| `tools.find_notes_with_tag` | `true` | Allow finding notes by tag (with task filtering) |\n| `tools.find_notes_in_notebook` | `true` | Allow finding notes by notebook (with task filtering) |\n| `tools.find_in_note` | `true` | Allow regex search within a single note |\n| `tools.get_all_notes` | `false` | Allow getting all notes (disabled by default - can fill context window) |\n| `tools.get_note` | `true` | Allow getting specific notes |\n| `tools.get_note_resources` | `true` | Allow reading a note's resources and their OCR text |\n| `tools.get_links` | `true` | Allow extracting links to other notes |\n| `tools.list_notebooks` | `true` | Allow listing all notebooks |\n| `tools.list_tags` | `true` | Allow listing all tags |\n| `tools.get_tags_by_note` | `true` | Allow getting tags for specific notes |\n| `tools.ping_joplin` | `true` | Allow testing server connectivity |\n| `tools.import_from_file` | `false` | Allow importing files/directories (MD, HTML, CSV, TXT, JEX) |\n\n#### Notebook Allowlist\n| Option | Default | Description |\n|--------|---------|-------------|\n| `notebook_allowlist` | `null` | List of notebook patterns to allow access to. `null` = no restriction. Supports gitignore-style patterns: exact names, `*` wildcards, `**` recursive, `!` negation |\n\n#### Content Exposure (Privacy Settings)\n| Option | Default | Description |\n|--------|---------|-------------|\n| `content_exposure.search_results` | `\"preview\"` | Content visibility in all search and listing results: `\"none\"`, `\"preview\"`, `\"full\"` |\n| `content_exposure.individual_notes` | `\"full\"` | Content visibility for individual notes: `\"none\"`, `\"preview\"`, `\"full\"` |\n| `content_exposure.max_preview_length` | `300` | Maximum length of content previews (characters) |\n| `content_exposure.smart_toc_threshold` | `2000` | Notes longer than this show a table of contents instead of the full body |\n| `content_exposure.enable_smart_toc` | `true` | Turn the table-of-contents fallback off to always return full note bodies |\n| `content_exposure.output_hints` | `false` | Emit worked follow-up calls (`NEXT_STEPS`, `NEXT_PAGE`) alongside results. Useful for smaller models, repetition for capable ones |\n\nLowering `max_preview_length` and `smart_toc_threshold`, or setting\n`search_results` to `\"none\"`, is the main way to cut how many tokens a\nsession spends. `list_notebooks` and `list_tags` return only the fields\nan agent acts on; pass `verbose=True` for icons, parent ids and\ntimestamps. See [docs/content-privacy.md](docs/content-privacy.md).\n\n## Docker\n\nRun the MCP server in a container. Default transport is HTTP for broad compatibility; switch via environment variables.\n\n### Build\n```bash\ndocker build -t joplin-mcp .\n```\n\n### Run (HTTP default)\n```bash\ndocker run --rm \\\n  -p 8000:8000 \\\n  -e JOPLIN_TOKEN=your_api_token \\\n  joplin-mcp\n```\n\n### With mounted config\n```bash\ndocker run --rm \\\n  -p 8000:8000 \\\n  -v $PWD/joplin-mcp.json:/config/joplin-mcp.json:ro \\\n  joplin-mcp\n```\n\n### Choose transport\n- SSE (streaming): `-e MCP_TRANSPORT=sse`\n- Streamable HTTP: `-e MCP_TRANSPORT=streamable-http`\n- STDIO (no port): `-e MCP_TRANSPORT=stdio`\n\nExample (SSE):\n```bash\ndocker run --rm \\\n  -p 8000:8000 \\\n  -e JOPLIN_TOKEN=your_api_token \\\n  -e MCP_TRANSPORT=sse \\\n  joplin-mcp\n```\n\nThe container listens on `0.0.0.0:8000` by default. If exposing publicly, place behind a reverse proxy and terminate TLS there. For SSE, ensure proxy keep-alives and buffering are configured appropriately.\n\n\n## Project Structure\n\n- **`src/joplin_mcp/`** - Main package directory\n  - `fastmcp_server.py` - Server implementation with 26 tools and Pydantic validation types\n  - `config.py` - Configuration management (including notebook allowlist)\n  - `notebook_utils.py` - Notebook path resolution, allowlist matching, and caching\n  - `server.py` - Server entrypoint (module and CLI)\n  - `tools/` - Tool implementations (notes, notebooks, tags)\n  - `ui_integration.py` - UI integration utilities\n- **`docs/`** - Documentation (troubleshooting, privacy controls, enhancement proposals)\n- **`tests/`** - Unit test suite\n- **`tests/e2e/`** - End-to-end tests against a real Joplin Desktop (3.x) via the Web Clipper API; see \"Running Tests\"\n\n## Testing\n\nTest your connection:\n\n```bash\n# For pip install\njoplin-mcp-server --config ~/.joplin-mcp.json\n\n# For development (from repo)\nPYTHONPATH=src python -m joplin_mcp.server --config ./joplin-mcp.json\n```\n\nYou should see:\n```\nStarting Joplin FastMCP Server...\nSuccessfully connected to Joplin!\nFound X notebooks, Y notes, Z tags\nFastMCP server starting...\nAvailable tools: 26 tools ready\n```\n\n### Running Tests\n\n```bash\n# Unit tests (no Joplin instance required)\npytest tests/ --ignore=tests/e2e\n\n# E2E tests (requires a running Joplin instance)\nJOPLIN_TOKEN=your_api_token \\\nJOPLIN_HOST=localhost \\\nJOPLIN_PORT=41184 \\\npytest tests/e2e/ -v -m e2e --override-ini=\"addopts=\"\n```\n\nThe E2E suite talks to a real Joplin Desktop via the Web Clipper API and exercises every tool including notebook allowlist enforcement. If `JOPLIN_HOST:JOPLIN_PORT` is unreachable the suite skips itself, so it's safe to run alongside the unit tests. Requires Joplin 3.x (the trash schema introduced in 3.0 — earlier versions fail with `no such column: deleted_time`).\n\n## Complete Tool Reference\n\n| Tool | Permission | Description |\n|------|------------|-------------|\n| **Finding Notes** | | |\n| `find_notes` | Read | Full-text search across all notes (supports task filtering; `trash=True` with `query=\"*\"` lists trashed notes) |\n| `find_notes_with_tag` | Read | Find notes with specific tag (supports task filtering) |\n| `find_notes_in_notebook` | Read | Find notes in specific notebook (supports task filtering) |\n| `get_all_notes` | Read | Get all notes, most recent first *(disabled by default)* |\n| `get_note` | Read | Get specific note by ID |\n| `find_in_note` | Read | Regex search within a single note (paginated matches & context, multiline anchors on by default) |\n| `get_links` | Read | Extract links to other notes from a note |\n| `get_note_resources` | Read | List a note's resources (images, PDFs, attachments) and read their OCR text |\n| **Managing Notes** | | |\n| `create_note` | Write | Create new notes |\n| `update_note` | Update | Modify existing notes (incl. moving between notebooks) |\n| `edit_note` | Update | Precision edit note content (find/replace, append, prepend) |\n| `delete_note` | Delete | Remove notes |\n| **Managing Notebooks** | | |\n| `list_notebooks` | Read | Browse all notebooks |\n| `create_notebook` | Write | Create new notebooks under an optional parent (by name or path), optionally with an emoji icon |\n| `update_notebook` | Update | Rename, change emoji icon, or move a notebook under another parent (or to top-level with `parent_name=\"/\"`) |\n| `delete_notebook` | Delete | Remove notebooks |\n| **Managing Tags** | | |\n| `list_tags` | Read | View all available tags |\n| `create_tag` | Write | Create new tags |\n| `update_tag` | Update | Modify tag titles |\n| `delete_tag` | Delete | Remove tags |\n| `get_tags_by_note` | Read | List tags on specific note |\n| **Tag-Note Relationships** | | |\n| `tag_note` | Update | Add one or more tags to one or more notes (accepts lists) |\n| `untag_note` | Update | Remove one or more tags from one or more notes (accepts lists) |\n| **Trash Management** | | |\n| `restore_from_trash` | Update | Restore a soft-deleted note or notebook (pass `item_type='note'` or `'notebook'`) |\n| **Import Tools** | | |\n| `import_from_file` | Write | Import files/directories (MD, HTML, CSV, TXT, JEX) |\n| **System Tools** | | |\n| `ping_joplin` | Read | Test connectivity |\n",
  "bytes": 23479,
  "sha": "64105dbc592109f2ac21fc3d08cc5b424a1a28e7a84455f586e4cdc9fdc66219",
  "repo_slug": "alondmnt/joplin-mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_alondmnt_joplin_mcp_200439cd/readme"
}