joplin-mcp
joplin-mcp is a minimal MCP server that lets an MCP client read, write, and organize notes in a running Joplin Desktop instance via its local Web Clipper REST API, with per-notebook access control.
Search & read:
search_notes(query, limit=20)for full-text search;get_note(note_id)for a note's full content;list_notes_in_notebook(notebook_id, limit=20)to browse without a query;get_notes_by_tag(tag_id, limit=20)to list notes by tag.Write notes:
create_note(title, body, notebook_id),update_note(note_id, title, body)(only provided fields change;bodyreplaces the whole note), anddelete_note(note_id)(moves to Joplin's trash).To-dos:
complete_todo(note_id, completed=True)marks a to-do complete/incomplete (fails on non-to-do notes).Organize:
list_notebooks()andlist_tags()to discover ids;create_notebook(title, parent_id=None)at the root or nested inside an existing notebook.Access control: all note-touching tools and
create_notebookare scoped by thenotebookslist inconfig.json(readimplies default,writeimplies read;*for all;$rootfor root-level notebook creation). Fail-closed, with out-of-scope calls raisingNotebookAccessError.list_notebooks/list_tagsare unscoped metadata.Requirements/limits: Joplin Desktop must be running with the Web Clipper service enabled (no headless mode); API failures surface as
JoplinError.Note: the README also documents
update_note_sectionandappend_note_section, which are not present in this schema.
Provides tools to search, get, create, and update notes, as well as list notebooks in Joplin via its local Web Clipper REST API.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@joplin-mcplist my notebooks"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
joplin-mcp
A minimal MCP server for Joplin, built with FastMCP. Talks to Joplin's local Web Clipper REST API.
Contents
Related MCP server: Joplin MCP Server
Tools
Tool | Description |
| Full-text search |
| Fetch a note's full content |
| Create a new note |
| Edit an existing note ( |
| Replace one exact, unique substring within a note's body |
| Append content to the end of a note's body |
| Delete a note (moves it to Joplin's trash) |
| Mark a to-do note complete or incomplete |
| Browse a notebook's notes without a search query |
| List notebooks, to get a |
| Create a notebook, at the root or nested inside another |
| List tags, to get a |
| List notes with a given tag |
Setup
In Joplin Desktop: Tools > Options > Web Clipper, enable the service, copy the auth token shown there.
Install uv if you don't have it.
Copy
config.example.jsontoconfig.jsonat the repo root (already gitignored, so it won't be committed) and fill in:{ "token": "paste-your-token-here", "host": "localhost", "port": "41184", "notebooks": [ {"id": "notebook-id-or-name", "access": "write"}, {"id": "another-notebook-id-or-name", "access": "read"} ] }host/portare optional and default tolocalhost/41184. See Access control below for thenotebookslist.
Running it
No manual pip install needed — uv run resolves and caches dependencies
on first run.
uv run --directory /path/to/joplin-mcp joplin-mcp-serverThis looks for config.json in the working directory (which --directory
sets to the repo). To keep the config file somewhere else, set
JOPLIN_CONFIG to its path:
JOPLIN_CONFIG=/path/to/config.json uv run --directory /path/to/joplin-mcp joplin-mcp-serverWiring into an MCP client
Both approaches below point at the repo directory, which is where
config.json lives — one source of truth for secrets and access config.
Claude Code
claude mcp add joplin -s user -- uv run --directory /path/to/joplin-mcp joplin-mcp-server-s user registers it at user scope, so it's available in every Claude
Code session, not just this repo. Verify with claude mcp get joplin;
remove with claude mcp remove joplin -s user.
Claude Desktop
Edit ~/Library/Application Support/Claude/claude_desktop_config.json
(macOS) or %APPDATA%\Claude\claude_desktop_config.json (Windows), adding:
{
"mcpServers": {
"joplin": {
"command": "uv",
"args": ["run", "--directory", "/path/to/joplin-mcp", "joplin-mcp-server"]
}
}
}Fully quit and restart Claude Desktop afterward — it only picks up config
changes on launch. This is the schema documented at
support.claude.com
and modelcontextprotocol.io.
Some Claude Desktop builds manage MCP servers through a Settings UI
(Extensions/Connectors) instead of this file directly — check there first
if the file on disk doesn't have an mcpServers key already.
Using uvx instead (no local checkout needed)
uv run --directory ... (above) operates on a project already cloned to
disk — it needs a working copy of this repo, its pyproject.toml, and its
lockfile at that path. uvx (short for uv tool run) is different: it
fetches the package straight from git into uv's own cache and runs it in
an ephemeral environment, so the machine running the MCP client doesn't
need a local clone at all — just a config.json and JOPLIN_CONFIG
pointing at it.
uvx --from git+https://github.com/johnsarie27/joplin-mcp@<ref> joplin-mcp-server<ref> can be a branch (e.g. main) or a commit SHA. A branch ref is
re-resolved to whatever the current tip commit is on every launch (a
network round-trip, and a fresh dependency resolve/build whenever that tip
changes) — convenient while iterating, but it means the running server can
change without you touching either client config. Pinning <ref> to a
specific commit SHA, per the SHA-pinning convention, freezes both the code
and its resolved dependency versions until you deliberately bump the pin —
prefer this once the repo's been stable through some real usage.
Since there's no local checkout in this mode, set JOPLIN_CONFIG to an
absolute path so config.json can still be found. Swap the command/args
in whichever client config above to uvx/--from git+... instead of
uv/run --directory ..., and add the JOPLIN_CONFIG env var:
claude mcp add joplin -s user -e JOPLIN_CONFIG=/path/to/config.json -- uvx --from git+https://github.com/johnsarie27/joplin-mcp@<ref> joplin-mcp-server{
"mcpServers": {
"joplin": {
"command": "uvx",
"args": ["--from", "git+https://github.com/johnsarie27/joplin-mcp@<ref>", "joplin-mcp-server"],
"env": {
"JOPLIN_CONFIG": "/path/to/config.json"
}
}
}
}Release tags (v<major>.<minor>.<patch>) are also valid refs — see
Releasing in CONTRIBUTING.md for how they're cut. Use
one as <ref> when pinning uvx --from git+...@<ref> above.
Tip: you can run the server standalone and call each tool manually before wiring it into a client — see Testing changes in CONTRIBUTING.md.
Access control
search_notes, get_note, create_note, update_note,
update_note_section, append_note_section, delete_note,
complete_todo, list_notes_in_notebook, get_notes_by_tag, and
create_notebook are scoped by the notebooks list in config.json. Each
entry is:
{"id": "notebook-id-or-name", "access": "read"}access is "read" (default if omitted) or "write" (implies read).
search_notes/get_note/list_notes_in_notebook/get_notes_by_tag
require read; create_note/update_note/update_note_section/
append_note_section/delete_note/complete_todo require write on the
relevant notebook. create_notebook follows the same
rule when nesting inside an existing notebook (parent_id set) — it
requires write on that parent, same as create_note. Creating a notebook
at the root (parent_id omitted) is different: it isn't scoped to any
existing notebook id, so it's governed by the $root sentinel instead —
see below. This is fail-closed: if notebooks is missing, empty, or none
of its entries grant applicable access, these tools refuse to operate.
list_notebooks and list_tags are unaffected since they only return
notebook/tag metadata, not note content, and double as the way to find the
ids/names to pass to the scoped tools above.
Name matching is case-insensitive (Tech, tech, and TECH are
equivalent) and resolved against the live notebook list on each call, so
a rename takes effect immediately. Since Joplin doesn't require notebook
names to be unique (nested notebooks can share a title), a name that
matches more than one notebook grants that access level to all of them —
use the notebook id instead (from list_notebooks) if you need to scope
to just one of several same-named notebooks.
Use {"id": "*", "access": "read"} or {"id": "*", "access": "write"} to
grant that access level to all notebooks. This is a deliberate opt-in,
distinct from leaving notebooks empty.
Use the reserved id "$root" to grant permission to create notebooks at the
root of the notebook tree — i.e. create_notebook calls that omit
parent_id:
{"id": "$root", "access": "write"}This is a separate, narrower opt-in than blanket write access: it lets a
config that only grants write on specific notebooks (e.g. Tech) also
create new top-level notebooks, without granting write access to every
existing notebook. {"id": "*", "access": "write"} already implies it, so
you only need $root if you want root-level creation without full write
access to everything else. $root only has meaning with access: "write";
an entry for it with access: "read" (or omitted) is a no-op, since there's
nothing to read at the root. It also never grants read or write access to
any real notebook — it's checked before name/id resolution runs, so it
can't collide with an actual notebook, even one literally titled $root.
Two edge cases worth knowing about $root: matching is exact and
case-sensitive (unlike the case-insensitive name matching above), so a typo
like "$Root" won't be recognized as the sentinel — it silently falls
through to normal name/id resolution and matches nothing, rather than
raising an error. And because $root is intercepted before name/id
resolution runs, a real notebook titled $root can no longer be granted
access by name in the notebooks list — use its id instead (from
list_notebooks), same as with any other name collision.
Out-of-scope access raises a NotebookAccessError with a message naming
the notebook, distinct from a JoplinError (an actual Joplin API failure).
Notes on this build
Requires Joplin Desktop running with the Web Clipper service enabled (i.e. Joplin itself must be open — this doesn't run Joplin headlessly).
host/portinconfig.jsonoverride the defaults (localhost/41184) if needed.Errors from the Joplin API surface as
JoplinErrorwith the raw status/body — check these first if a tool call fails.
References
Related projects
Contributing
See CONTRIBUTING.md for development setup, testing, and the release process.
Available Tools
13 toolsappend_note_sectionAppend Note SectionA
Append content to the end of a note's body, without needing to know or resend its existing content. Inserts a blank line separator unless the note is empty or already ends in one.
| Name | Required | Description | Default |
|---|---|---|---|
| content | Yes | ||
| note_id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full disclosure burden. It does add genuine behavioral detail beyond the schema (the blank-line separator rule, with the empty-note and trailing-separator exceptions), but it omits whether the note must exist, whether the change is reversible, permission requirements, and the mutation semantics relative to update_note.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two lean sentences, front-loaded with the core action; the separator rule follows as the key edge case. Nothing is wasted and nothing important is buried.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be explained, and the description covers the main behavioral quirk. What remains thin is the mutation context (auth, failure when the note is missing), but for a simple append operation the coverage is nearly sufficient.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description must compensate. It does clarify that content is the text appended to the end of the body, but says nothing about note_id (format, where it comes from) or how content is merged. Partial compensation for a small two-parameter tool.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Specific verb + resource + scope: "Append content to the end of a note's body" tells the agent exactly what is modified and where. The phrase "without needing to know or resend its existing content" implicitly separates it from update_note/update_note_section, but no sibling is named explicitly, so differentiation is inferential rather than stated.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied: the append-without-resending framing suggests this over a full update when you only want to add text. However, there is no explicit when-to-use/when-not guidance, no mention of prerequisites such as the note existing, and no named alternative among the many sibling note tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
complete_todoComplete TodoA
Mark a to-do note complete or incomplete. Fails if the note isn't a to-do.
| Name | Required | Description | Default |
|---|---|---|---|
| note_id | Yes | ||
| completed | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full disclosure burden. It does add real value by revealing the failure mode ('Fails if the note isn't a to-do') and by implying the operation is reversible via the completed flag. It omits idempotency, permission requirements, and what happens to already-completed notes, though the output schema covers the success return.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences with no waste; the action and scope come first, and the failure condition follows immediately. Every clause earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple two-parameter toggle with an output schema covering the response, the description is nearly sufficient: it names the action, the bidirectional nature, and the key failure precondition. Only permission/auth context and error-detail expectations are missing, which is a modest gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0% for two parameters, so the description must compensate. 'Complete or incomplete' usefully clarifies that the `completed` boolean is a two-way toggle rather than a one-shot completion, but note_id and the default=true behavior are left to the schema, leaving half the semantic load unaddressed.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (mark) and resource (to-do note) plus the bidirectional scope (complete or incomplete), which cleanly separates it from the note CRUD siblings like update_note and create_note. An agent can identify what this does without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied rather than explicit: the tool is clearly meant for notes that are to-dos, and the precondition 'Fails if the note isn't a to-do' bounds applicability. However, there is no guidance on when to prefer this over update_note for the same field, nor any stated prerequisites such as required permissions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_noteCreate NoteB
Create a new note in the given notebook. Use list_notebooks to find a notebook_id.
| Name | Required | Description | Default |
|---|---|---|---|
| body | Yes | ||
| title | Yes | ||
| notebook_id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are supplied, so the description carries the full behavioral burden. It says nothing about whether the notebook must exist, whether it needs write permission, what happens on duplicate titles, or what the created object contains. For a mutation tool with zero annotation coverage this is a notable gap, though the presence of an output schema softens the impact.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences with no waste; the core action is front-loaded and the helpful pointer follows. Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Because an output schema exists, return values need not be explained. However, for a three-parameter mutation tool with no annotations and no schema descriptions, the definition leaves the caller guessing about field semantics and preconditions. Adequate but with clear gaps.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0% and all three parameters (title, body, notebook_id) are undocumented in the schema. The description only implicitly tells us what a note is made of and explicitly points to list_notebooks for notebook_id, leaving title and body semantics unstated. It partially compensates for the coverage gap but does not resolve it.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (create) and resource (note) with a scope qualifier (in the given notebook), which is clear on its own. It does not, however, distinguish itself from sibling create_notebook or explain how it differs from update_note beyond the obvious verb change.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The second sentence gives concrete, actionable guidance: call list_notebooks to obtain a notebook_id. That covers the main prerequisite for a first-time caller. No when-not-to-use guidance or mention of failure cases is provided, so it falls short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_notebookCreate NotebookA
Create a new notebook. Omit parent_id to create it at the root of the
notebook tree (requires a $root write entry in config, or blanket write
access); set parent_id to nest it inside an existing notebook (requires
write access to that notebook). Use list_notebooks to find a parent_id.
| Name | Required | Description | Default |
|---|---|---|---|
| title | Yes | ||
| parent_id | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full behavioral burden. It does well by disclosing the permission prerequisites for each mode ('$root' write entry or blanket write access for root; write access to the target notebook for nesting), which is genuine context beyond the schema. It does not describe the failure or response behavior, but an output schema exists to cover returns.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tight sentences, each earning its place, with the core action front-loaded and the parameter guidance following. No filler or restatement of the title.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a two-parameter creation tool with an output schema already defining returns, the description supplies the missing pieces: mode selection, permission requirements, and a pointer to the discovery tool. Nothing needed to call it correctly is absent.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate. It fully explains parent_id's duality (null → root, string → nested parent) and how to obtain a valid value, though 'title' is left to the obvious-name inference. Strong coverage given the low schema documentation.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Create a new notebook') and immediately scopes the operation by distinguishing root creation from nested creation. An agent can tell it apart from the sibling create_note and from list_notebooks without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit when-to-use guidance for the one ambiguous parameter: omit parent_id for root, set it to nest. It also names the alternative tool (list_notebooks) for finding a parent_id, which is exactly the routing an agent needs.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
delete_noteDelete NoteA
Delete a note by its id. Moves it to Joplin's trash rather than a permanent delete.
| Name | Required | Description | Default |
|---|---|---|---|
| note_id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full behavioral burden, and it discharges the most important part by disclosing that this is a soft delete moving the note to Joplin's trash rather than a permanent removal. It does not state permission requirements, error behavior for unknown ids, or whether the trash is recoverable/purgeable, so it falls short of exhaustive.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences, front-loaded with the core action and immediately followed by the crucial soft-delete nuance. Nothing is wasted and nothing important is buried.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a one-parameter mutation tool with an output schema (so return values need not be explained), the description covers the action and the key safety-relevant behavior. It could add recovery/permission context, but the essentials for correct invocation are present.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema documents the single note_id parameter only as type string with no description, so coverage is 0%. The description adds the meaning that the id refers to the note being deleted and is the targeting key, which is a modest but real increment over the bare schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (delete) and resource (note) with the identifier used to target it, and goes further by clarifying the deletion semantics ('by its id'). No sibling competes for this action, so an agent can select it unambiguously.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies when to use it (you have a note id and want it gone) but offers no explicit conditions, prerequisites, or contrast with related tools like update_note. Usage is inferable but not guided.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_noteGet NoteA
Fetch the full content of a single Joplin note by its id.
| Name | Required | Description | Default |
|---|---|---|---|
| note_id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the burden. 'Fetch' and 'full content' convey a read that returns the whole note body rather than a summary, but nothing is said about error behavior for a missing id or how this differs from partial/section reads.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single, front-loaded sentence with no filler; the verb, scope, and lookup key all appear immediately.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be described, and the tool is a simple one-param getter. The description is nearly complete, with only error/miss behavior left unstated.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
There is one parameter and schema coverage is 0%, so the description is the only source of meaning. It identifies note_id as 'its id', which is helpful, but adds no format, source, or lookup guidance beyond that.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Specific verb (Fetch) plus resource (single Joplin note) and the selection key (by its id). The word 'single' implicitly distinguishes it from search_notes and list_notes_in_notebook, though no sibling is named explicitly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is only implied: the phrase 'by its id' signals the id prerequisite, but the description never states when to prefer this over search_notes or list_notes_in_notebook, nor what happens if the id is unknown.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_notes_by_tagGet Notes By TagB
List notes with a given tag. Use list_tags to find a tag_id.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| tag_id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full behavioral burden. 'List' implies a read, but nothing is said about pagination, ordering, or what happens when a tag has no notes, and the implicit 20-item default limit is never surfaced.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences with the core action first and the prerequisite second. No filler, no redundancy with the title.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be described. However, with zero schema coverage and no annotations, the silent limit/default behavior and the absence of any pagination or result-count guidance leave a real gap for a simple but under-specified list tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate for both parameters. It explains where tag_id comes from (list_tags) but adds nothing about the limit parameter or its default, leaving half the inputs undocumented in prose.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: list notes filtered by a tag. It is distinguishable from siblings like list_notes_in_notebook and search_notes, though it never explicitly contrasts itself with those alternatives.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives a concrete prerequisite path by directing the agent to list_tags to obtain a tag_id. It does not state when-not to use this tool or when search_notes would be preferable, but the routing guidance present is actionable.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_notebooksList NotebooksA
List all Joplin notebooks (folders) with their ids, for use with create_note.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden. 'List all ... with their ids' implies a safe, complete read with no filtering or mutation, which is adequate for a zero-parameter listing tool, but it says nothing about ordering, pagination, or empty-result behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
One sentence, front-loaded with the action and resource, with the downstream-use clause tacked on efficiently. Nothing is wasted.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a trivial zero-param read tool with an output schema and 100% schema coverage, the description tells the agent enough to call it correctly. It stops short of noting ordering or that all notebooks are returned unfiltered, but the output schema covers the return shape.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so there is no parameter semantics to convey; the baseline of 4 applies. The description correctly notes that no filter argument exists by saying 'all'.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (List) and resource (Joplin notebooks), and disambiguates the domain term by equating notebooks with folders. It also clarifies what is returned (ids), which separates it from create_notebook and list_notes_in_notebook.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The phrase 'for use with create_note' signals the intended workflow and why an agent would call this first. However, it gives no explicit exclusion (e.g. when to prefer list_notes_in_notebook or list_tags instead).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_notes_in_notebookList Notes In NotebookA
List notes in a notebook without a search query. Use list_notebooks to find a notebook_id.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| notebook_id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden. It mentions the listing behavior and prerequisite but omits details such as pagination, permissions, or error behavior. With an output schema present, return values need not be described, but other behavioral aspects remain unaddressed.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two concise sentences that front-load the core action and immediately follow with essential prerequisite guidance. No superfluous information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no annotations, an output schema present, and 0% schema parameter description coverage, the description covers the required notebook_id but leaves the limit parameter unexplained. It also lacks behavioral details common for list operations, such as pagination or default limits.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate. It clarifies that notebook_id is required and directs the agent to obtain it via list_notebooks. However, it says nothing about the 'limit' parameter, which is undocumented in both schema and description.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('List') and resource ('notes in a notebook') with scope clarified by 'without a search query'. It doesn't explicitly name the contrasting sibling search_notes, but the phrase 'without a search query' implicitly distinguishes it from search-based note retrieval.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides a clear condition ('without a search query') and a prerequisite step ('Use list_notebooks to find a notebook_id'), which guides the agent on when and how to use this tool. However, it doesn't explicitly state when not to use it or name the alternative search_notes.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_tagsList TagsA
List all Joplin tags with their ids, for use with get_notes_by_tag.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the burden. It implies a safe, read-only list operation and indicates the return contains ids, but doesn't explicitly state read-only behavior, pagination, or ordering. Adequate but with gaps.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Single sentence, front-loaded with the action and resource, with no wasted words. It efficiently conveys the essential purpose and a key usage detail.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no parameters, full schema coverage, and an existing output schema, the description needn't explain return values in detail. It covers the core purpose and a critical usage link. The only minor gap is not stating read-only behavior explicitly, but the output schema and context make this clear enough.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Zero parameters, so baseline is 4. The description correctly notes the output includes ids, which is relevant return-value context even without parameters.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('List all Joplin tags'), and adds the purpose of the return value ('with their ids, for use with get_notes_by_tag'), which distinguishes it from sibling list_* tools like list_notebooks.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly names the downstream tool get_notes_by_tag, making the usage path clear. However, it doesn't state when not to use this tool or mention alternatives for other tag-related operations.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_notesSearch NotesC
Search Joplin notes by keyword. Returns matching note titles and ids.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| query | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full behavioral burden, yet it only discloses the return shape ('titles and ids'). It says nothing about match semantics (substring, case, fuzzy), ordering, or how limit truncates results.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short front-loaded sentences covering purpose and return value with zero filler. Nothing is wasted or buried.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need no elaboration, and the tool is a simple two-parameter read. However, with no annotations and no parameter documentation, the missing match semantics and limit behavior leave real gaps for an agent to call it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so both parameters are undocumented in structured form. The description hints that 'query' is a keyword but says nothing about the 'limit' parameter or its default of 20, leaving half the surface unexplained.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('Search') and resource ('Joplin notes') plus the matching mechanism ('by keyword'), which cleanly separates it from get_note and list_notes_in_notebook. It never names a sibling explicitly, so it stops short of full differentiation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance on when to choose this over the adjacent retrieval tools such as list_notes_in_notebook, get_notes_by_tag, or get_note. The agent must infer the search-vs-list distinction on its own.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
update_noteUpdate NoteA
Update an existing note's title and/or body. Only provided fields are
changed, but body, if provided, REPLACES the entire note body - it is
not a patch or append, and any content not included in body is lost.
For a targeted edit to part of a note, use update_note_section; to add
content to the end without resending the whole body, use
append_note_section.
| Name | Required | Description | Default |
|---|---|---|---|
| body | No | ||
| title | No | ||
| note_id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does disclose the critical destructive trait: 'body, if provided, REPLACES the entire note body - it is not a patch or append, and any content not included in body is lost.' It also notes partial-update semantics for unspecified fields. It does not cover authorization, error behavior, or rate limits, but the key data-loss risk is clearly surfaced.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, zero waste, and front-loaded: the purpose comes first, the destructive body behavior second, and the sibling routing last. Every sentence adds decision-relevant information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a three-parameter mutation tool with an output schema available, the description covers what the tool does, the destructive edge case, and how to choose among the related section-editing tools. Nothing an agent needs in order to call it safely is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate. It adds significant meaning for 'body' (full replacement, not append) and clarifies that only provided fields change, which implicitly explains omitting title/body. note_id is not explicitly described, but its role is evident from the verb and required status.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ('Update an existing note') and the exact fields affected ('title and/or body'). It differentiates itself from siblings by naming the alternative tools for targeted edits and appends, so an agent can select correctly without opening other schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly routes to alternatives: 'For a targeted edit to part of a note, use update_note_section; to add content to the end without resending the whole body, use append_note_section.' This gives concrete when-to-use conditions that map to distinct sibling tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
update_note_sectionUpdate Note SectionA
Replace an exact, unique substring within a note's body, without touching the rest of the note. Fails with no write if old_str isn't found, or if it matches more than once - use get_note to find a longer, unique old_str in that case.
| Name | Required | Description | Default |
|---|---|---|---|
| new_str | Yes | ||
| note_id | Yes | ||
| old_str | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden and delivers: it discloses atomic failure semantics ('Fails with no write'), the uniqueness constraint, both failure triggers, and the recovery path. This is unusually thorough behavioral disclosure for a mutation tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two tight sentences with the core operation front-loaded and failure behavior second. No filler, though a lead sentence naming the tool's uniqueness constraint could make it even more scannable.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Output schema exists so return values needn't be explained. The description covers purpose, failure modes, and recovery, which is sufficient for a 3-param mutating tool. Minor gap around deletion semantics aside, nothing critical is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate; it explains old_str semantics ('exact, unique substring') and that new_str replaces it, implying note_id selects the note. It doesn't spell out that empty new_str should be used for pure deletion, leaving a small gap.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a precise verb and resource ('Replace an exact, unique substring within a note's body') and delimits scope ('without touching the rest of the note'). This is clearly distinguishable from siblings append_note_section and update_note.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explains failure conditions and points to get_note as the remedy when old_str is non-unique, effectively routing to the right sibling. It doesn't state when to prefer update_note vs append_note_section, but the context is clear enough.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
2 tool updates
v0.5.0- Added
append_note_section - Added
update_note_section
1 tool update
v0.4.1- Added
create_notebook
8 tool updates
v0.3.1- Added
create_note - Added
delete_note - Added
get_notes_by_tag - Added
list_notebooks - Added
list_notes_in_notebook - Added
list_tags - Added
search_notes - Added
update_note
5 tool updates
v0.3.0- Added
complete_todo - Removed
create_note - Removed
list_notebooks - Removed
search_notes - Removed
update_note
5 tool updates
v0.1.0- First observed
create_note - First observed
get_note - First observed
list_notebooks - First observed
search_notes - First observed
update_note
TDQS
Scored across 13 tools
Each tool has a clearly distinct purpose, and the descriptions explicitly disambiguate the tricky trio: update_note (full-body replace), update_note_section (targeted substring), and append_note_section (append). The listing tools (search_notes, list_notes_in_notebook, get_notes_by_tag) are also clearly separated by their input method.
Every tool follows a consistent snake_case verb_noun pattern (search_notes, get_note, create_note, update_note, delete_note, list_notebooks, create_notebook, list_tags, etc.). Suffixes like _section and _in_notebook are applied predictably, so names are fully readable.
13 tools is well-scoped for a note-taking server, giving good granularity between note reads, writes, and structured edits. No tool feels redundant or out of place.
Note lifecycle is fully covered (search/get/create/update/delete plus section edits, todos, and tag listings). However, notebook and tag management is asymmetric: only create_notebook and list_notebooks exist (no update/delete notebook), and tags are read-only with no way to create, delete, or attach a tag to a note.
Maintenance
Related MCP Connectors
Google Keep-style notes app with an MCP server for AI agents to read/write notes.
Markdown-based note-taking with a hosted MCP server. Your notes serve you and your AI.
MCP-native open-source Notion alternative: read & write pages, databases and kanban boards.
An MCP server that used to create notes
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceA MCP server for Joplin note-taking application that enables interaction with Joplin notes through the web clipper API, supporting notebook hierarchy and running in Docker.-
- AlicenseNot gradedqualityDmaintenanceMCP server that provides standardized tools for querying and retrieving notes from Joplin personal knowledge manager through its API, enabling AI assistants to access and reference personal notes contextually.9MIT
- AlicenseNot gradedqualityAmaintenanceMCP server for Joplin Server that gives LLMs full access to notes, notebooks, tags, and attachments via the REST API.5MIT
- AlicenseNot gradedqualityCmaintenanceEnables interaction with Joplin notes through MCP, allowing searching, creating, updating, and deleting notes via the Joplin Web Clipper API.3 npmMIT