MCP server for Joplin note-taking application, providing tools to list, create, update, delete, and search notes, as well as manage folders and tags
This server demonstrates good foundational quality with all 8 tools explicitly defined in source code with JSON schemas and descriptions. Tool naming follows verb_noun convention appropriately (list_notes, get_note, create_note, etc.). All tools have non-empty descriptions (averaging ~60 chars, within baseline range). Input schemas are present and properly typed for all tools. However, there are notable gaps: (1) output schemas are completely undocumented, LLMs cannot infer what fields each tool returns, (2) parameter descriptions lack specificity about constraints/formats (e.g., 'limit' says 'max 100' but no min; 'page' has no guidance on zero-indexing vs one-indexing despite claiming 'starts at 1'), (3) error handling is generic with no recovery guidance in descriptions, (4) no tool annotations (readOnlyHint, destructiveHint, idempotentHint) despite clear risk classification in metadata. The server correctly implements required parameters for critical tools (note_id for get/update/delete), but optional parameters lack smart defaults to reduce agent reasoning. Description quality is functional but not LLM-optimized, they state WHAT but not WHEN or WHY to use each tool relative to similar alternatives.
Create a new note
Delete a note (moves to trash by default)
Get a specific note by ID
List all notebooks/folders
List all notes or notes in a specific folder
List all tags
Search for notes using Joplin's search syntax
No output schemas documented. LLMs cannot infer what fields each tool returns (e.g., does list_notes return note IDs, titles, dates, or full bodies?). This breaks tool chaining, get_note returns some fields, but without schema documentation, agents cannot reliably extract the note_id to pass to update_note.
Missing tool annotations (readOnlyHint, destructiveHint, idempotentHint) despite clear risk classification in metadata. delete_note is marked DESTRUCTIVE but lacks destructiveHint. This deprives agents of explicit signal to require confirmation or handle with extra caution.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | C | 62 | 2026-07-28+ | v2 |
| 2026-03-09 | F | 41 | 2024-11-05+ | v1 |
Update an existing note
Parameter descriptions lack constraint specifications. 'limit' says 'max 100' but no minimum. 'page' claims 'starts at 1' but no guidance on invalid values or boundary behavior. 'type' in search_notes lists 'note, folder, tag' as examples but without an enum constraint, LLM could hallucinate 'attachment' or 'resource'.
Descriptions lack recovery guidance and error context. If get_note('invalid-id') fails, the description does not hint 'Try search_notes() to discover valid note IDs'. This forces agents to navigate failure without guidance.
list_folders and list_tags descriptions are under 50 chars and lack LLM context. 'List all tags' does not explain when/why an agent would call this vs relying on search, or whether pagination is supported.
search_notes 'type' parameter should be an enum ('note'|'folder'|'tag') but is defined as a free-form string. LLM could pass invalid types, wasting a call.
update_note requires note_id but title and body are both optional, description should explicitly state that at least one of title or body must be provided, or the API will silently succeed without changing anything.