MCP server for Obsidian vault operations — read, write, search, and navigate notes
Strong foundation with 14 well-named tools, comprehensive descriptions (avg 180 chars), and complete input schemas. All tools follow verb_noun naming (obsidian_list_*, obsidian_read_*, obsidian_create_*, etc.). Descriptions clearly state WHAT the tool does and WHEN to use it. All parameters have type definitions and descriptions. Pagination is properly implemented with limit/offset. However, output schemas are not explicitly documented in the source code, only inferred from descriptions. Error handling is mentioned in descriptions but recovery guidance is minimal. No tool annotations (readOnlyHint, destructiveHint, idempotentHint) visible in schema definitions, despite risk levels being clearly marked.
Append content to the end of a note. Creates the note if it does not exist. A newline separator is inserted automatically if the existing content does not end with one. Useful for daily notes, logs, and running task lists. Args: - path (string): Vault-relative path to the note - content (string): Markdown content to append - response_format: 'markdown' | 'json' (default: 'markdown') Returns: Updated note metadata.
Create a new folder in the vault. Parent folders are created as needed. Creating a folder that already exists is a no-op (idempotent). Args: - path (string): Vault-relative path for the new folder, e.g. "projects/2025" Returns: Confirmation message.
Create a new Obsidian note. Fails by default if the note already exists. Parent folders are created automatically. Frontmatter is serialized as YAML at the top of the file. Use overwrite=true to replace an existing note. Args: - path (string): Vault-relative path for the new note, e.g. "projects/new-idea" - body (string): Markdown content for the note body - frontmatter (object, optional): Key-value pairs to include as YAML frontmatter - overwrite (boolean): Replace the note if it already exists (default: false) - response_format: 'markdown' | 'json' (default: 'markdown') Returns: Metadata of the created note. Errors: - "Note already exists" if the note exists and overwrite=false
Permanently delete an Obsidian note from the vault. This action removes the file from disk and cannot be undone (unless the vault uses a version-control system). Does NOT update backlinks in other notes. Args: - path (string): Vault-relative path to the note Returns: Confirmation message.
Output schemas not explicitly documented in source code. Descriptions mention return structure but no formal schema definitions visible for tool responses.
Tool annotations (readOnlyHint, destructiveHint, idempotentHint) not visible in schema definitions, despite clear risk levels (READ_ONLY, WRITE, DESTRUCTIVE, IRREVERSIBLE) being marked in metadata.
Error handling descriptions are minimal. obsidian_create_note mentions 'Note already exists' error but does not provide recovery guidance (e.g., 'Use overwrite=true or call obsidian_read_note to check first').
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | C | 62 | 2026-07-28+ | v2 |
Find all notes that link to a given note using Obsidian wiki-link syntax. Matches [[note-name]], [[folder/note-name]], and aliased links [[note|alias]]. The search is case-insensitive. The target note itself is excluded from results. Args: - path (string): Vault-relative path of the note to find backlinks for - limit (number): Max results per page, 1–100 (default: 20) - offset (number): Pagination offset (default: 0) - response_format: 'markdown' | 'json' (default: 'markdown') Returns: Paginated list of notes containing wiki-links to the target note, with the matching line and surrounding context.
Get metadata of a note without loading its body. More efficient than obsidian_read_note when only metadata is needed. Returns frontmatter, tags, and file timestamps. Args: - path (string): Vault-relative path to the note - response_format: 'markdown' | 'json' (default: 'markdown') Returns: Note metadata (path, name, frontmatter, tags, timestamps).
Check whether the Obsidian MCP server and vault are accessible and responding. Useful for diagnosing connectivity or timeout issues.
List all folders in the vault (or a subfolder), with note counts. Hidden directories (those starting with .) such as .obsidian and .trash are automatically excluded. Args: - folder (string, optional): Vault-relative path to list subfolders of (default: vault root) - response_format: 'markdown' | 'json' (default: 'markdown') Returns: List of folders with vault-relative paths, names, and note counts.
List markdown notes in the Obsidian vault, optionally scoped to a folder. Returns note paths, names, tags, and modification dates. Results are paginated. Args: - folder (string, optional): Vault-relative folder to list (default: vault root) - limit (number): Max results per page, 1–100 (default: 20) - offset (number): Pagination offset (default: 0) - response_format: 'markdown' | 'json' (default: 'markdown') Returns: Paginated list with total, count, has_more, and next_offset.
Move or rename a note to a new vault-relative path. Parent directories at the destination are created automatically. Existing `[[wikilinks]]` in other notes that point to the old path are not updated automatically. Args: - from_path (string): Current vault-relative path of the note - to_path (string): Destination vault-relative path - response_format: 'markdown' | 'json' (default: 'markdown') Returns: Metadata of the note at its new path.
Read the full content of an Obsidian note by its vault-relative path. Accepts paths with or without the .md extension. Returns the note body, parsed frontmatter, all tags (inline and frontmatter), and file timestamps. Args: - path (string): Vault-relative path, e.g. "projects/my-note" or "projects/my-note.md" - response_format: 'markdown' | 'json' (default: 'markdown') Returns: Full note content with frontmatter, body, tags, and file metadata.
Find all notes that have a specific tag. Searches both inline tags (#tagname in the body) and frontmatter tag arrays. The # prefix is optional — "project" and "#project" are equivalent. Args: - tag (string): Tag to search for (with or without # prefix) - limit (number): Max results per page, 1–100 (default: 20) - offset (number): Pagination offset (default: 0) - response_format: 'markdown' | 'json' (default: 'markdown') Returns: Paginated list of notes that carry the specified tag. Examples: - All notes tagged "project": tag="project" - All notes tagged "#meeting": tag="#meeting"
Full-text search across all notes in the vault. Case-insensitive substring match over note bodies and frontmatter. Returns matching excerpts with up to one line of surrounding context. Args: - query (string): Search string (case-insensitive, minimum 1 character) - limit (number): Max results per page, 1–100 (default: 20) - offset (number): Pagination offset (default: 0) - response_format: 'markdown' | 'json' (default: 'markdown') Returns: Paginated list of matches — file path, line number, and context excerpt. Examples: - Find meeting notes about Q2: query="Q2 meeting" - Find all TODO items: query="- [ ]"
Overwrite the full content of an existing Obsidian note. Replaces the entire note including frontmatter. Use obsidian_append_to_note to add content non-destructively. Creates the note if it does not exist. Args: - path (string): Vault-relative path to the note - body (string): New markdown body content - frontmatter (object, optional): New frontmatter (replaces existing frontmatter) - response_format: 'markdown' | 'json' (default: 'markdown') Returns: Updated note metadata.
obsidian_health description is generic (75 chars). Should explain what 'accessible and responding' means and what to do if health check fails.
No batch variants for tools agents might call in loops (e.g., create multiple notes, delete multiple notes). Sequential calls waste tokens and latency.