A small, deliberate MCP server for reading and safely editing an Obsidian vault.
Strong foundation with clear naming, complete schemas, and good descriptions. All 7 tools follow verb_noun convention (vault_info, list_notes, search_notes, read_note, create_note, append_note, replace_note_text). Zod schemas are well-defined with type constraints and descriptions. Tool annotations (readOnlyHint, destructiveHint) are present. Main gaps: output schemas are not formally documented in tool definitions (only visible in code via structuredContent), and error handling lacks recovery guidance. Descriptions average ~100 chars, meeting baseline. Parameters are well-constrained (e.g., limit 1-1000, expectedSha256 length 64). No secrets exposed as parameters.
Append text to an existing note after confirming it has not changed since it was read.
Create a new Markdown note. Omit path to create it in the default folder.
List Markdown notes in the vault or in one folder without reading their contents.
Read one Markdown note. The sha256 value is required for a later edit.
Replace one exact, unique text span after confirming the note has not changed since it was read.
Search note contents using case-insensitive literal text and return matching lines.
Return the vault path, note count, and default collaboration folder.
Output schemas not formally documented in tool definitions. While code returns structured content via structuredContent field, the tool registration does not declare expected output fields, types, or pagination behavior. LLMs cannot plan downstream operations without knowing response structure.
Error handling lacks recovery guidance. Tools return errors (e.g., 'Note not found', 'SHA256 mismatch') but do not guide the LLM on next steps. Should include actionable hints like 'Try search_notes() to locate the file' or 'Re-read the note to get the current SHA256.'
create_note parameter 'title' is optional but its relationship to 'path' is underdocumented. Description says 'Used to create the filename when path is omitted' but does not clarify: is title required if path is omitted? What if both are omitted? What filename format is generated from title?
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | C | 64 | 2025-06-18+ | v2 |
list_notes and search_notes accept 'limit' but do not document pagination or cursor behavior. If results exceed limit, how does the LLM fetch the next page? No offset, cursor, or next_token field is mentioned.
search_notes returns 'excerpt' field but does not specify format (full line, truncated, with context). LLMs need to know if excerpts are complete or if they should call read_note for full content.