A Model Context Protocol Server for Joplin that provides tools to search, retrieve, and manage notes with semantic search capabilities
The server has 10 tools with complete, well-structured definitions. Tool names follow verb_noun conventions consistently (search_notes, get_note, list_notes, create_note, update_note, delete_note, build_semantic_index, find_neighbours, similar_notes). Descriptions are detailed and contextual, above the 10-1024 char baseline (search_notes: 426 chars, get_note: 60 chars, create_note: 32 chars). All parameters have type definitions and descriptions. However, output schemas are NOT explicitly documented, the rubric requires documented return types for A+ scores. Risk classifications are present (READ_ONLY, WRITE, DESTRUCTIVE), but tool annotations are not declared in the MCP tool registration (no readOnlyHint/destructiveHint in schema). Error handling is minimal, no guidance on what to do when a note is not found, semantic index fails to build, or when the LLM should retry. Parameter descriptions could be more actionable (e.g., 'keyword_weight: 0-1, raise for identifier queries' is good; more explicit constraints needed). Default values are sensible (limit=20, order_dir='DESC') and unlikely to cause data loss. No secrets exposed as parameters. Parameter relationships (e.g., 'mode=semantic requires build_semantic_index to be called first') are documented in descriptions, which is good. Overall: solid foundations, but missing output schema documentation and error recovery patterns.
Build or rebuild the semantic search index over all notes in Joplin. This embeds the entire note library using a local MiniLM model for later semantic search queries. Rebuilding is automatic when the library changes, but you can force a rebuild with the force parameter.
Create a new note in Joplin.
Delete a note from Joplin.
Find notes linked to or from a given note, optionally including semantically similar notes. Walks the note graph breadth-first from the given note up to a specified depth.
Retrieve the full text of a specific note by ID.
List all notebooks (folders) in Joplin, including nested structure.
Output schemas are not documented in tool definitions. LLMs cannot predict what fields each tool returns, forcing them to reason about response structure and risking extraction errors. Rubric requires 100% of A+ tools document return types.
Error handling lacks recovery guidance. When search_notes falls back to keyword search (semantic index missing), or when get_note fails (note not found), the LLM receives no actionable next steps. Responses should include: what went wrong, why, and what to do next.
Inferred effective spec: <=2025-11-25.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | D | 59 | <=2025-11-25 | v2 |
| 2026-03-09 | F | 0 | - | v1 |
List notes in Joplin, optionally filtered by notebook or sorted by various fields.
Search for notes in Joplin by keyword, meaning, or both. Hybrid is the default and is usually what you want: keyword search alone misses notes that make the same point in different words, and meaning-based search alone is poor at exact strings such as ticket keys or identifiers, which embeddings barely represent. Blending covers both failure modes. Semantic modes need an index; call build_semantic_index first. Without one this falls back to keyword search and says so in the response. Returns a short excerpt of each match, normally enough to judge relevance. Call get_note for the full text of the ones worth reading.
Find semantically similar notes to a given note. Requires the semantic index to be built.
Update an existing note in Joplin.
Tool annotations (readOnlyHint, destructiveHint, idempotentHint) are not declared in the MCP tool schema. The server documents risk levels (READ_ONLY, WRITE, DESTRUCTIVE) in comments, but does not expose them as MCP-schema properties. Per the current spec (2026-07-28), these should be in the tool registration.
Irreversible operations (delete_note) lack a dry-run or confirmation step. Agents make mistakes, without a confirmation pattern, permanent deletions cannot be undone. The 'permanent' parameter helps, but no warning or review step is documented.
Parameter descriptions for numeric bounds are incomplete. 'limit' parameters lack min/max (should be bounded, e.g., 1 - 200). 'depth' parameter in find_neighbours states 'max: 3' in description but does not declare it as a JSON Schema constraint. Rubric requires both description text AND formal constraints (min, max, enum).
Tool composition: find_neighbours and similar_notes both operate on semantic graph traversal. While distinct (link-based vs embedding-based), naming could better distinguish intent. 'find_neighbours' is vague, 'find_linked_notes' and 'find_semantically_similar_notes' would be clearer.