Metadata-Version: 2.4
Name: joplin-mcp
Version: 0.8.0
Summary: Model Context Protocol (MCP) server for Joplin note-taking application
Author: Alon Diament
Maintainer: Alon Diament
License: MIT License
        
        Copyright (c) 2025 Alon Diament
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE. 
Project-URL: Homepage, https://github.com/alondmnt/joplin-mcp
Project-URL: Documentation, https://github.com/alondmnt/joplin-mcp/blob/main/README.md
Project-URL: Repository, https://github.com/alondmnt/joplin-mcp
Project-URL: Issues, https://github.com/alondmnt/joplin-mcp/issues
Keywords: joplin,mcp,model-context-protocol,notes,ai,assistant
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Text Processing
Classifier: Topic :: Office/Business
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: mcp<2,>=1
Requires-Dist: joppy>=1.0.0
Requires-Dist: fastmcp!=3.3.1,<4,>=3
Requires-Dist: pydantic<3,>=2
Requires-Dist: httpx<1,>=0.24
Requires-Dist: typing-extensions>=4.0.0
Requires-Dist: PyYAML>=6.0.0
Requires-Dist: beautifulsoup4>=4.9.0
Requires-Dist: markdownify>=0.11.0
Requires-Dist: pathspec>=0.11
Provides-Extra: dev
Requires-Dist: pytest>=7.0.0; extra == "dev"
Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
Requires-Dist: pytest-mock>=3.10.0; extra == "dev"
Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
Requires-Dist: black>=23.0.0; extra == "dev"
Requires-Dist: mypy>=1.0.0; extra == "dev"
Requires-Dist: ruff>=0.1.0; extra == "dev"
Requires-Dist: coverage>=7.0.0; extra == "dev"
Requires-Dist: pre-commit>=3.0.0; extra == "dev"
Provides-Extra: docs
Requires-Dist: mkdocs>=1.4.0; extra == "docs"
Requires-Dist: mkdocs-material>=8.0.0; extra == "docs"
Requires-Dist: mkdocstrings[python]>=0.20.0; extra == "docs"
Dynamic: license-file

# Joplin MCP Server

A **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.

<!-- mcp-name: io.github.alondmnt/joplin-mcp -->

## Table of Contents

- [What You Can Do](#what-you-can-do)
- [Quick Start](#quick-start)
- [Supported Clients](#supported-clients)
- [Example Usage](#example-usage)
- [Tool Permissions](#tool-permissions)
- [Notebook Allowlist](#notebook-allowlist)
- [Advanced Configuration](#advanced-configuration)
- [Docker](#docker)
- [Project Structure](#project-structure)
- [Testing](#testing)
- [Complete Tool Reference](#complete-tool-reference)
- [Changelog](CHANGELOG.md)

## What You Can Do

This MCP server provides **25 optimized tools** for comprehensive Joplin integration:

### **Note Management**
- **Find & Search**: `find_notes` (supports `trash=True` for trashed notes), `find_notes_with_tag`, `find_notes_in_notebook`, `get_all_notes`
- **CRUD Operations**: `get_note`, `get_links`, `create_note`, `update_note`, `edit_note`, `delete_note`

### **Notebook Management** 
- **Organize**: `list_notebooks`, `create_notebook`, `update_notebook`, `delete_notebook`

### **Tag Management**
- **Categorize**: `list_tags`, `create_tag`, `update_tag`, `delete_tag`, `get_tags_by_note`
- **Link**: `tag_note`, `untag_note`

### **Trash Management**
- **Recover**: `restore_from_trash` - Restore soft-deleted notes or notebooks

### **Import**
- **File Import**: `import_from_file` - Import Markdown, HTML, CSV, TXT, JEX files and directories

### **System**
- **Health**: `ping_joplin`

## Quick Start

1. Open **Joplin Desktop** → **Tools** → **Options** → **Web Clipper**
2. **Enable** the Web Clipper service
3. **Copy** the Authorization token
4. Set up your preferred client below

## Supported Clients

> Any MCP-compatible client should work. Below are the ones with documented setup instructions.

### Claude Desktop

Run the automated installer:

```bash
# Install and configure everything automatically (pip)
pip install joplin-mcp
joplin-mcp-install

# Or use zero-install with uvx (recommended if you have uv)
uvx --from joplin-mcp joplin-mcp-install

# Optional: pin a specific version/range for stability
uvx --from joplin-mcp==0.4.1 joplin-mcp-install
uvx --from 'joplin-mcp>=0.4,<0.5' joplin-mcp-install
```

This script will:
- Configure your Joplin API token
- Set tool permissions (Create/Update/Delete)
- Set up Claude Desktop automatically
- Test the connection

After setup, restart Claude Desktop and you're ready to go!

### Claude Code

Install the orchestration plugin for smarter tool usage (edit vs update, long-note reading, bulk tagging):

```bash
/plugin marketplace add alondmnt/joplin-mcp
/plugin install joplin-mcp
```

You'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`.

### Jan AI

1. **Install Jan AI** from [https://jan.ai](https://jan.ai)

2. **Add MCP Server** in Jan's interface:
   - Open Jan AI
   - Go to **Settings** → **Extensions** → **Model Context Protocol**
   - Click **Add MCP Server**
   - Configure:
     - **Name**: `joplin`
     - **Command**: `uvx --from joplin-mcp joplin-mcp-server` *(requires `uv` installed)*
     - **Environment Variables**:
       - `JOPLIN_TOKEN`: `your_joplin_api_token_here`
   - Enable the server

3. **Start chatting** with access to your Joplin notes!

**Automated Setup (Alternative)**

```bash
# Install and configure Jan AI automatically (if Jan is already installed)
pip install joplin-mcp
joplin-mcp-install
```

This will detect and configure Jan AI automatically, just like Claude Desktop.

### OllMCP (Local Ollama Models)

**Auto-discovery (if you set up Claude Desktop first)**
```bash
# Install ollmcp
pip install ollmcp

# Run with auto-discovery (requires existing Claude Desktop config)
ollmcp --auto-discovery --model qwen3:4b
```

**Manual setup (works independently)**
```bash
# Install ollmcp
pip install ollmcp

# Set environment variable
export JOPLIN_TOKEN="your_joplin_api_token_here"

# Run with uvx (requires uv installed)
ollmcp --server "joplin:uvx --from joplin-mcp joplin-mcp-server" --model qwen3:4b

# Or with an installed package (pip install joplin-mcp)
ollmcp --server "joplin:joplin-mcp-server" --model qwen3:4b
```

## Example Usage

Once configured, you can ask your AI assistant:

- **"List all my notebooks"** - See your Joplin organization
- **"Find notes about Python programming"** - Search your knowledge base  
- **"Create a meeting note for today's standup"** - Quick note creation
- **"Tag my recent AI notes as 'important'"** - Organize with tags
- **"Show me my todos"** - Find task items with `find_notes(task=True)`

## Tool Permissions

The setup script offers **4 permission levels**:

- **Read** (always enabled): Browse and search your notes safely
- **Write** (optional): Create new notes, notebooks, and tags
- **Update** (optional): Modify existing content
- **Delete** (optional): Remove content permanently

Choose the level that matches your comfort and use case.

## Notebook Allowlist

Restrict 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.

### Quick Setup

**JSON config** (`joplin-mcp.json`):
```json
{
  "token": "your_token",
  "notebook_allowlist": ["Work", "Projects/Public"]
}
```

**Environment variable**:
```bash
export JOPLIN_NOTEBOOK_ALLOWLIST="Work,Projects/Public"
```

### Pattern Syntax

Patterns use [gitignore/gitwildmatch](https://git-scm.com/docs/gitignore) semantics:

| Pattern | Matches | Example |
|---------|---------|---------|
| `Work` | Exact notebook name (and all children) | `Work`, `Work/Tasks`, `Work/Notes` |
| `Projects/*` | Direct children of Projects | `Projects/Alpha`, `Projects/Beta` |
| `Projects/**` | All descendants recursively | `Projects/Alpha/Tasks/Q1` |
| `!Projects/Secret` | Exclude (negate) a specific path | Everything in Projects *except* Secret |

Negation patterns always win over positive patterns (any negation match on a path or ancestor denies access).

### How It Works

- **Hierarchical access**: Allowing a parent notebook grants access to all its children. Allowing `Projects` means notes in `Projects/Work/Tasks` are also accessible.
- **Read protection**: `get_note`, `find_notes`, `get_links` — notes in blocked notebooks are filtered out or rejected.
- **Write protection**: `create_note`, `update_note`, `edit_note`, `delete_note` — operations on notes in blocked notebooks are rejected.
- **Notebook operations**: `list_notebooks` only shows accessible notebooks. `create_notebook` is rejected both under a blocked parent and at the top level (no `parent_id`) when an allowlist is set — top-level creation would let the agent silently expand its own scope. To grow the allowlist, create the notebook in the Joplin UI, then add it to `notebook_allowlist` and restart the server.
- **Search filtering**: `find_notes` results are filtered to only include notes in accessible notebooks.
- **Tag operations**: `tag_note`, `untag_note`, `get_tags_by_note` enforce access on the note's notebook.
- **Error privacy**: Blocked access raises a generic "Notebook not accessible" error without revealing notebook names or IDs.

### Configuration Examples

**Single project focus** (notebook name containing a space):
```json
{ "notebook_allowlist": ["Work Projects"] }
```

**Multiple notebooks with exclusion:**
```json
{ "notebook_allowlist": ["Projects", "!Projects/Secret", "AI", "Reference"] }
```

**Glob patterns:**
```json
{ "notebook_allowlist": ["Projects/*", "!Projects/Private"] }
```

**No allowlist (default)** — all notebooks accessible:
```json
{ "notebook_allowlist": null }
```

### Startup Behavior

At server startup, the allowlist is validated and logged:
- Each entry is resolved against existing notebooks
- Unresolvable patterns trigger warnings (but never block startup)
- If the allowlist resolves to zero accessible notebooks, a warning is logged

---

## Advanced Configuration

### Development Installation

For developers or users who want the latest features:

**macOS/Linux:**
```bash
git clone https://github.com/alondmnt/joplin-mcp.git
cd joplin-mcp
./install.sh
```

**Windows:**
```batch
git clone https://github.com/alondmnt/joplin-mcp.git
cd joplin-mcp
install.bat
```

### Manual Configuration

If you prefer manual setup or the script doesn't work:

> 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.

> 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`.

#### 1. Create Configuration File

Create `joplin-mcp.json` in your project directory:

```json
{
  "token": "your_api_token_here",
  "host": "localhost", 
  "port": 41184,
  "timeout": 30,
  "verify_ssl": false
}
```

#### 2. Claude Desktop Configuration

Add to your `claude_desktop_config.json`:

**Option A: Using uvx (Zero-install)**
```json
{
  "mcpServers": {
    "joplin": {
      "command": "uvx",
      "args": ["--from", "joplin-mcp", "joplin-mcp-server"],
      "env": {
        "JOPLIN_TOKEN": "your_token_here"
      }
    }
  }
}
```
*Requires `uv` installed: `pip install uv`*

**Option B: Using installed package**
```json
{
  "mcpServers": {
    "joplin": {
      "command": "joplin-mcp-server",
      "env": {
        "JOPLIN_TOKEN": "your_token_here"
      }
    }
  }
}
```

#### 3. More Client Configuration Examples

For additional client configurations including different transport options (HTTP, SSE, Streamable HTTP), see [client-config.json.example](client-config.json.example).

This file includes configurations for:
- **STDIO transport** (default, most compatible)
- **HTTP transport** (basic HTTP server mode)
- **SSE transport** (recommended for gemini-cli and OpenAI clients)
- **Streamable HTTP transport** (advanced web clients)
- **HTTP-compat transport** (bridges modern `/mcp` JSON-RPC with legacy `/sse`/`/messages` clients)

### Tool Permission Configuration

Fine-tune which operations the AI can perform by editing your config:

```json
{
  "tools": {
    "create_note": true,
    "update_note": true,
    "delete_note": false,
    "create_notebook": true,
    "update_notebook": false,
    "delete_notebook": false,
    "create_tag": true,
    "update_tag": false,
    "delete_tag": false,
    "get_all_notes": false,
    "import_from_file": true
  }
}
```

### Environment Variables

Alternative to JSON configuration:

```bash
# Connection settings
export JOPLIN_TOKEN="your_api_token_here"
export JOPLIN_HOST="localhost"
export JOPLIN_PORT="41184"
export JOPLIN_TIMEOUT="30"
```

#### Per-Tool Env Vars

Every tool can be toggled individually via `JOPLIN_TOOL_<NAME>=true|false`. These take precedence over config file settings.

| Env var | Default |
|---------|---------|
| `JOPLIN_TOOL_FIND_NOTES` | `true` |
| `JOPLIN_TOOL_FIND_NOTES_WITH_TAG` | `true` |
| `JOPLIN_TOOL_FIND_NOTES_IN_NOTEBOOK` | `true` |
| `JOPLIN_TOOL_FIND_IN_NOTE` | `true` |
| `JOPLIN_TOOL_GET_ALL_NOTES` | `false` |
| `JOPLIN_TOOL_GET_NOTE` | `true` |
| `JOPLIN_TOOL_GET_LINKS` | `true` |
| `JOPLIN_TOOL_CREATE_NOTE` | `true` |
| `JOPLIN_TOOL_UPDATE_NOTE` | `true` |
| `JOPLIN_TOOL_EDIT_NOTE` | `true` |
| `JOPLIN_TOOL_DELETE_NOTE` | `false` |
| `JOPLIN_TOOL_LIST_NOTEBOOKS` | `true` |
| `JOPLIN_TOOL_CREATE_NOTEBOOK` | `true` |
| `JOPLIN_TOOL_UPDATE_NOTEBOOK` | `false` |
| `JOPLIN_TOOL_DELETE_NOTEBOOK` | `false` |
| `JOPLIN_TOOL_LIST_TAGS` | `true` |
| `JOPLIN_TOOL_CREATE_TAG` | `true` |
| `JOPLIN_TOOL_UPDATE_TAG` | `false` |
| `JOPLIN_TOOL_DELETE_TAG` | `false` |
| `JOPLIN_TOOL_GET_TAGS_BY_NOTE` | `true` |
| `JOPLIN_TOOL_TAG_NOTE` | `true` |
| `JOPLIN_TOOL_UNTAG_NOTE` | `true` |
| `JOPLIN_TOOL_PING_JOPLIN` | `true` |
| `JOPLIN_TOOL_RESTORE_FROM_TRASH` | `true` |
| `JOPLIN_TOOL_IMPORT_FROM_FILE` | `false` |

#### Notebook Allowlist Env Var

| Env var | Default | Description |
|---------|---------|-------------|
| `JOPLIN_NOTEBOOK_ALLOWLIST` | *(not set)* | Comma-separated list of notebook patterns (e.g., `Work,Projects/*,!Projects/Secret`) |

### HTTP Transport Support

The server supports both STDIO and HTTP transports:

```bash
# STDIO (default)
joplin-mcp-server --config ~/.joplin-mcp.json

# HTTP transport (development, from repo)
PYTHONPATH=src python -m joplin_mcp.server --transport http --port 8000 --config ./joplin-mcp.json

# Opt-in HTTP compatibility bundle (modern + legacy SSE endpoints)
PYTHONPATH=src python -m joplin_mcp.server --transport http-compat --port 8000 --config ./joplin-mcp.json
# or keep --transport http and export MCP_HTTP_COMPAT=1/true to toggle the same behavior.
```

#### HTTP client config

Note: Claude Desktop currently uses STDIO transport and does not consume HTTP/SSE configs directly. The following example applies to clients that support network transports.
```json
{
  "mcpServers": {
    "joplin": {
      "transport": "http",
      "url": "http://localhost:8000/mcp"
    }
  }
}
```

### Configuration Reference

#### Basic Settings
| Option | Default | Description |
|--------|---------|-------------|
| `token` | *required* | Joplin API authentication token |
| `host` | `localhost` | Joplin server hostname |
| `port` | `41184` | Joplin Web Clipper port |
| `timeout` | `30` | Request timeout in seconds |
| `verify_ssl` | `false` | SSL certificate verification |

#### Tool Permissions
| Option | Default | Description |
|--------|---------|-------------|
| `tools.create_note` | `true` | Allow creating new notes |
| `tools.update_note` | `true` | Allow modifying existing notes |
| `tools.edit_note` | `true` | Allow precision edits (find/replace, append, prepend) |
| `tools.delete_note` | `false` | Allow deleting notes *(disabled by default — destructive)* |
| `tools.create_notebook` | `true` | Allow creating new notebooks |
| `tools.update_notebook` | `false` | Allow modifying notebook titles |
| `tools.delete_notebook` | `false` | Allow deleting notebooks *(disabled by default — destructive)* |
| `tools.create_tag` | `true` | Allow creating new tags |
| `tools.update_tag` | `false` | Allow modifying tag titles |
| `tools.delete_tag` | `false` | Allow deleting tags *(disabled by default — destructive)* |
| `tools.tag_note` | `true` | Allow adding tags to notes |
| `tools.untag_note` | `true` | Allow removing tags from notes |
| `tools.restore_from_trash` | `true` | Allow restoring soft-deleted notes or notebooks |
| `tools.find_notes` | `true` | Allow text search across notes (with task filtering) |
| `tools.find_notes_with_tag` | `true` | Allow finding notes by tag (with task filtering) |
| `tools.find_notes_in_notebook` | `true` | Allow finding notes by notebook (with task filtering) |
| `tools.find_in_note` | `true` | Allow regex search within a single note |
| `tools.get_all_notes` | `false` | Allow getting all notes (disabled by default - can fill context window) |
| `tools.get_note` | `true` | Allow getting specific notes |
| `tools.get_links` | `true` | Allow extracting links to other notes |
| `tools.list_notebooks` | `true` | Allow listing all notebooks |
| `tools.list_tags` | `true` | Allow listing all tags |
| `tools.get_tags_by_note` | `true` | Allow getting tags for specific notes |
| `tools.ping_joplin` | `true` | Allow testing server connectivity |
| `tools.import_from_file` | `false` | Allow importing files/directories (MD, HTML, CSV, TXT, JEX) |

#### Notebook Allowlist
| Option | Default | Description |
|--------|---------|-------------|
| `notebook_allowlist` | `null` | List of notebook patterns to allow access to. `null` = no restriction. Supports gitignore-style patterns: exact names, `*` wildcards, `**` recursive, `!` negation |

#### Content Exposure (Privacy Settings)
| Option | Default | Description |
|--------|---------|-------------|
| `content_exposure.search_results` | `"preview"` | Content visibility in search results: `"none"`, `"preview"`, `"full"` |
| `content_exposure.individual_notes` | `"full"` | Content visibility for individual notes: `"none"`, `"preview"`, `"full"` |
| `content_exposure.listings` | `"none"` | Content visibility in note listings: `"none"`, `"preview"`, `"full"` |
| `content_exposure.max_preview_length` | `300` | Maximum length of content previews (characters) |

## Docker

Run the MCP server in a container. Default transport is HTTP for broad compatibility; switch via environment variables.

### Build
```bash
docker build -t joplin-mcp .
```

### Run (HTTP default)
```bash
docker run --rm \
  -p 8000:8000 \
  -e JOPLIN_TOKEN=your_api_token \
  joplin-mcp
```

### With mounted config
```bash
docker run --rm \
  -p 8000:8000 \
  -v $PWD/joplin-mcp.json:/config/joplin-mcp.json:ro \
  joplin-mcp
```

### Choose transport
- SSE (streaming): `-e MCP_TRANSPORT=sse`
- Streamable HTTP: `-e MCP_TRANSPORT=streamable-http`
- STDIO (no port): `-e MCP_TRANSPORT=stdio`

Example (SSE):
```bash
docker run --rm \
  -p 8000:8000 \
  -e JOPLIN_TOKEN=your_api_token \
  -e MCP_TRANSPORT=sse \
  joplin-mcp
```

The 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.


## Project Structure

- **`src/joplin_mcp/`** - Main package directory
  - `fastmcp_server.py` - Server implementation with 25 tools and Pydantic validation types
  - `config.py` - Configuration management (including notebook allowlist)
  - `notebook_utils.py` - Notebook path resolution, allowlist matching, and caching
  - `server.py` - Server entrypoint (module and CLI)
  - `tools/` - Tool implementations (notes, notebooks, tags)
  - `ui_integration.py` - UI integration utilities
- **`docs/`** - Documentation (troubleshooting, privacy controls, enhancement proposals)
- **`tests/`** - Unit test suite
- **`tests/e2e/`** - End-to-end tests against a real Joplin Desktop (3.x) via the Web Clipper API; see "Running Tests"

## Testing

Test your connection:

```bash
# For pip install
joplin-mcp-server --config ~/.joplin-mcp.json

# For development (from repo)
PYTHONPATH=src python -m joplin_mcp.server --config ./joplin-mcp.json
```

You should see:
```
Starting Joplin FastMCP Server...
Successfully connected to Joplin!
Found X notebooks, Y notes, Z tags
FastMCP server starting...
Available tools: 25 tools ready
```

### Running Tests

```bash
# Unit tests (no Joplin instance required)
pytest tests/ --ignore=tests/e2e

# E2E tests (requires a running Joplin instance)
JOPLIN_TOKEN=your_api_token \
JOPLIN_HOST=localhost \
JOPLIN_PORT=41184 \
pytest tests/e2e/ -v -m e2e --override-ini="addopts="
```

The 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`).

## Complete Tool Reference

| Tool | Permission | Description |
|------|------------|-------------|
| **Finding Notes** | | |
| `find_notes` | Read | Full-text search across all notes (supports task filtering; `trash=True` with `query="*"` lists trashed notes) |
| `find_notes_with_tag` | Read | Find notes with specific tag (supports task filtering) |
| `find_notes_in_notebook` | Read | Find notes in specific notebook (supports task filtering) |
| `get_all_notes` | Read | Get all notes, most recent first *(disabled by default)* |
| `get_note` | Read | Get specific note by ID |
| `find_in_note` | Read | Regex search within a single note (paginated matches & context, multiline anchors on by default) |
| `get_links` | Read | Extract links to other notes from a note |
| **Managing Notes** | | |
| `create_note` | Write | Create new notes |
| `update_note` | Update | Modify existing notes (incl. moving between notebooks) |
| `edit_note` | Update | Precision edit note content (find/replace, append, prepend) |
| `delete_note` | Delete | Remove notes |
| **Managing Notebooks** | | |
| `list_notebooks` | Read | Browse all notebooks |
| `create_notebook` | Write | Create new notebooks |
| `update_notebook` | Update | Modify notebook titles |
| `delete_notebook` | Delete | Remove notebooks |
| **Managing Tags** | | |
| `list_tags` | Read | View all available tags |
| `create_tag` | Write | Create new tags |
| `update_tag` | Update | Modify tag titles |
| `delete_tag` | Delete | Remove tags |
| `get_tags_by_note` | Read | List tags on specific note |
| **Tag-Note Relationships** | | |
| `tag_note` | Update | Add one or more tags to one or more notes (accepts lists) |
| `untag_note` | Update | Remove one or more tags from one or more notes (accepts lists) |
| **Trash Management** | | |
| `restore_from_trash` | Update | Restore a soft-deleted note or notebook (pass `item_type='note'` or `'notebook'`) |
| **Import Tools** | | |
| `import_from_file` | Write | Import files/directories (MD, HTML, CSV, TXT, JEX) |
| **System Tools** | | |
| `ping_joplin` | Read | Test connectivity |
