Multi-vault Obsidian note management via Model Context Protocol. Provides tools for note CRUD operations, frontmatter management, content search, and section manipulation.
This server demonstrates solid definition quality with comprehensive tool coverage (22 tools), consistent naming conventions (all verb_noun style), and well-structured Pydantic models. All tools have descriptions and input schemas are present via model definitions. However, output schemas lack formal documentation in the response, several parameters could be better constrained with enums, and error handling guidance is minimal. The fastmcp framework handles Pydantic validation well, but LLMs cannot see the Python type hints, they need explicit JSON schema documentation in tool responses. Tool composition is excellent (write/read pairs, granular section operations), and vault parameter handling follows natural identifier patterns. The descriptions average ~180 chars, which is optimal for LLM selection. Descriptions are clear and actionable, mentioning when to use each tool and what to expect (e.g., 'Consider search_obsidian_content() first for preview'). However, no formal output schema documentation is visible in the source, which forces LLMs to infer return structure.
Append content to end of note (most efficient for additions). Adds content to note end, automatically inserting newline separator if needed. Most token-efficient way to add content without reading entire note.
Append content to end of section (before subsections). Adds content to end of heading's direct section content, placing it right before any subsections. Different from insert_after_heading which puts content immediately after heading line.
Create new note with markdown content (fails if exists). Creates markdown file in vault. Automatically creates parent folders if needed. Fails if note already exists.
Remove the frontmatter block while preserving body content. Returns status: "no_frontmatter" when the note does not contain a block, allowing callers to short-circuit follow-up workflows.
Delete a note from the vault (permanent). Permanently removes the note file from the vault.
Output schemas not documented in tool definitions. While Pydantic models exist internally (mentioned in docstrings as returning dict with fields), LLMs cannot access Python type hints. Each tool must formally document its return structure in machine-readable form (JSON Schema or explicit schema objects). Currently LLMs must infer structure from docstring prose like '{"vault": str, "note": str, ...}', which is error-prone and wastes tokens parsing natural language.
Inferred effective spec: <=2025-11-25.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | C | 60 | <=2025-11-25 | v2 |
| 2026-03-09 | D | 52 | - | v1 |
Delete heading and its section (removes heading and all content). Removes heading and everything under it until next heading of equal or higher level. Heading itself is also deleted.
Insert content immediately after a heading. Finds heading (case-insensitive) and inserts content right after it, before any existing content or subsections.
List notes in a specific folder (token-efficient, targeted). More efficient than list_obsidian_notes() when you know the folder. Returns only notes in specified folder, sorted by your preference.
List ALL notes in vault (complete inventory). Returns every note path in the vault. For large vaults (100+ notes), use search_obsidian_notes() for filtered results.
List configured Obsidian vaults and current session state. Returns metadata for all configured vaults including the default vault and currently active vault for this session. Primary entry point for vault discovery.
Move or rename a note, optionally updating backlinks. Moves a note to a new location and/or renames it. Can optionally update all wikilinks ([[link]]) and markdown links ([](link)) that reference the old path.
Prepend content to beginning of note. Adds content to note beginning, automatically inserting newline separator if needed.
Read frontmatter metadata without returning the markdown body. The input is validated automatically by Pydantic, providing detailed error messages for invalid inputs before any processing occurs.
Replace the entire frontmatter block (destructive). Use when you need the frontmatter to match an exact schema, such as when applying templates or resetting metadata.
Replace entire note content (overwrites everything). Completely replaces note content with new markdown. Use for rewriting or major restructuring. For adding content, use append/prepend instead.
Replace content under heading (until next same-level heading). Replaces everything under a heading until next heading of equal or higher level. Preserves the heading itself. Use for rewriting entire sections.
Retrieve complete note content (full markdown). Returns entire markdown content of a note. Can be expensive for large notes (5000+ tokens). Consider search_obsidian_content() first for preview.
Search notes by tags using frontmatter-only filtering (token-efficient). Loads only note frontmatter to find tagged notes, making it substantially more token-efficient than listing all notes and filtering in the client. Supports AND/OR semantics, metadata inclusion, and both string and list tag formats.
Search note contents and return contextual snippets (token-efficient). Searches inside note files and returns up to 3 snippets per file (200 chars each, 100 chars context on each side). Returns top 10 files by match count. Designed for preview before full retrieval.
Find notes matching search pattern (efficient, token-optimized). Case-insensitive substring search across note paths/titles. Returns only matching notes.
Set the active vault for this conversation session. All subsequent tool calls that omit the vault parameter will use the active vault. Session state persists for the conversation lifetime.
Merge new fields into an existing frontmatter block. Creates a frontmatter block when missing. Preserves fields that are not mentioned in frontmatter and recursively merges nested dictionaries.
Parameters accept free-form strings where enums would be better. Examples: 'sort_by' in list_obsidian_notes, search_obsidian_notes, and list_notes_in_folder accepts 'modified', 'created', 'size', or 'name' but is documented as a string without enum constraint. This invites hallucinated values like 'date_modified' or 'updated'. The rubric (pattern:constrained-input) requires enums for known value sets.
Error handling lacks actionable recovery guidance. Most tool docstrings list possible errors (ValidationError, FileNotFoundError, ValueError) but do not tell LLMs what to do next. Example: 'Note not found → FileNotFoundError' does not explain whether the LLM should search for the note first, create it, or inform the user. The rubric (pattern:recovery-guide) requires error responses to include suggested next steps.
Destructive operations (delete_obsidian_note, delete_obsidian_frontmatter, delete_section_obsidian_note) lack confirmation or dry-run support. The rubric (pattern:confirmation-request) recommends Irreversible operations support a confirm_before_execute step to prevent catastrophic agent errors. Currently, an LLM could delete an entire note without warning.
search_obsidian_content returns '3 snippets per file, 200 chars each' but no formal pagination or limit parameter. Large vaults could return results exceeding context windows. The rubric (mxe:enforce-result-limits) requires capping results and offering pagination. No 'limit' or 'max_files' parameter is documented; LLMs cannot control result size.
list_obsidian_notes warns 'For large vaults (100+ notes), use search_obsidian_notes()' but does not document whether it enforces a hard limit or returns everything. If a vault has 10,000 notes, LLMs cannot know in advance whether the call will succeed or timeout. Tool must document explicit caps and offer pagination (limit, offset, next_cursor).