Bidirectional knowledge flow between Claude Code and Obsidian — 20 MCP tools, skills, and hooks for PKM
Well-structured tool definitions with comprehensive descriptions and proper JSON schemas. All 16 tools have explicit registrations with names, descriptions, and input schemas. Descriptions are detailed and contextual (averaging ~250 chars, well within the 10-1024 char baseline). Parameters include type definitions and most have descriptions. However, output schemas are NOT documented, the rubric requires documented output schemas for A-tier tools. Tool annotations (readOnlyHint, destructiveHint, idempotentHint) are absent. No examples of error handling guidance in descriptions. Most tools accept fuzzy/partial identifiers (e.g., 'devlog' resolves to full path), which aligns with natural-identifiers pattern. The LINK_FORMAT_NOTE appended to read-only tools is an excellent design pattern to prevent the LLM from passing markdown links back into path parameters. Naming is consistent and action-oriented (vault_read, vault_write, vault_delete). Parameter relationships are documented (e.g., 'position' requires 'heading'). Some tools like vault_semantic_search expose optional OpenAI key dependency without documenting fallback behavior.
Query the activity log: view all tool calls made in this session or previous ones, optionally filtered by tool name, session ID, timestamp range, or file path. Useful for understanding the history of vault modifications and remembering what was discussed. Paths in this tool's output are formatted as markdown links `[vault-relative-path.md](obsidian://...)` so users can Cmd/Ctrl-click to open in Obsidian. Preserve the link form when relaying paths to the user; pass only the bracket text (e.g. `01-Projects/Foo/note.md`) to other vault tools' `path` arguments, never the full markdown link.
Append content to an existing file, optionally under a specific heading. When 'position' is specified, heading is required and must exist in the file. Paths in this tool's output are formatted as markdown links `[vault-relative-path.md](obsidian://...)` so users can Cmd/Ctrl-click to open in Obsidian. Preserve the link form when relaying paths to the user; pass only the bracket text (e.g. `01-Projects/Foo/note.md`) to other vault tools' `path` arguments, never the full markdown link.
Delete a file from the vault. This is permanent. Optionally rewrites wikilinks in other files to remove broken references. Paths in this tool's output are formatted as markdown links `[vault-relative-path.md](obsidian://...)` so users can Cmd/Ctrl-click to open in Obsidian. Preserve the link form when relaying paths to the user; pass only the bracket text (e.g. `01-Projects/Foo/note.md`) to other vault tools' `path` arguments, never the full markdown link.
Edit a file by replacing an exact string match. The old_string must appear exactly once in the file for safety. Paths in this tool's output are formatted as markdown links `[vault-relative-path.md](obsidian://...)` so users can Cmd/Ctrl-click to open in Obsidian. Preserve the link form when relaying paths to the user; pass only the bracket text (e.g. `01-Projects/Foo/note.md`) to other vault tools' `path` arguments, never the full markdown link.
Output schemas not documented. The rubric requires 'Document the output schema. LLMs need to know what fields to expect so they can plan downstream tool calls and extract the right data.' No tool provides a documented outputSchema describing what fields are returned, their types, or how to chain results to other tools.
Tool annotations missing. readOnlyHint, destructiveHint, and idempotentHint are not declared on tools. vault_delete and vault_rename should be marked destructive; vault_read, vault_peek, vault_search, vault_list, vault_recent, vault_graph_neighbors, vault_wikilink_extract, vault_stats should be marked readonly. This prevents clients from applying appropriate safeguards.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | C | 64 | 2026-07-28+ | v2 |
| 2026-03-09 | F | 0 | - | v1 |
Explore the knowledge graph around a note: see files linking to it, files it links to, and their metadata. Use this to understand the context of a note within the vault. Returns nodes grouped by hop distance (depth). Paths in this tool's output are formatted as markdown links `[vault-relative-path.md](obsidian://...)` so users can Cmd/Ctrl-click to open in Obsidian. Preserve the link form when relaying paths to the user; pass only the bracket text (e.g. `01-Projects/Foo/note.md`) to other vault tools' `path` arguments, never the full markdown link.
List files and folders in the vault. Paths in this tool's output are formatted as markdown links `[vault-relative-path.md](obsidian://...)` so users can Cmd/Ctrl-click to open in Obsidian. Preserve the link form when relaying paths to the user; pass only the bracket text (e.g. `01-Projects/Foo/note.md`) to other vault tools' `path` arguments, never the full markdown link.
Inspect a file's metadata and structure without reading full content. Returns file size, frontmatter, heading outline with approximate section sizes, and a brief preview. Use this to plan which sections to read from large files. Paths in this tool's output are formatted as markdown links `[vault-relative-path.md](obsidian://...)` so users can Cmd/Ctrl-click to open in Obsidian. Preserve the link form when relaying paths to the user; pass only the bracket text (e.g. `01-Projects/Foo/note.md`) to other vault tools' `path` arguments, never the full markdown link.
Read the contents of a markdown file from the vault. Supports pagination: read a single section by heading, last N lines, last N heading-level sections, chunk number, or line range. Files exceeding ~80k characters auto-redirect to peek data (file structure/outline) unless a pagination param or force=true is specified. Paths in this tool's output are formatted as markdown links `[vault-relative-path.md](obsidian://...)` so users can Cmd/Ctrl-click to open in Obsidian. Preserve the link form when relaying paths to the user; pass only the bracket text (e.g. `01-Projects/Foo/note.md`) to other vault tools' `path` arguments, never the full markdown link.
Get recently modified files. Paths in this tool's output are formatted as markdown links `[vault-relative-path.md](obsidian://...)` so users can Cmd/Ctrl-click to open in Obsidian. Preserve the link form when relaying paths to the user; pass only the bracket text (e.g. `01-Projects/Foo/note.md`) to other vault tools' `path` arguments, never the full markdown link.
Rename a file and automatically update all wikilinks pointing to it (in other files). This operation is atomic: either the entire rename + relink succeeds, or it all rolls back. Returns a summary of files modified. Paths in this tool's output are formatted as markdown links `[vault-relative-path.md](obsidian://...)` so users can Cmd/Ctrl-click to open in Obsidian. Preserve the link form when relaying paths to the user; pass only the bracket text (e.g. `01-Projects/Foo/note.md`) to other vault tools' `path` arguments, never the full markdown link.
Search for text across all markdown files in the vault. Paths in this tool's output are formatted as markdown links `[vault-relative-path.md](obsidian://...)` so users can Cmd/Ctrl-click to open in Obsidian. Preserve the link form when relaying paths to the user; pass only the bracket text (e.g. `01-Projects/Foo/note.md`) to other vault tools' `path` arguments, never the full markdown link.
Search the vault using semantic similarity (requires VAULT_PKM_OPENAI_KEY). Returns notes most similar in meaning to your query, even if they don't contain exact keyword matches. Useful for discovering related ideas across the vault. Only available if OpenAI API key is configured. Paths in this tool's output are formatted as markdown links `[vault-relative-path.md](obsidian://...)` so users can Cmd/Ctrl-click to open in Obsidian. Preserve the link form when relaying paths to the user; pass only the bracket text (e.g. `01-Projects/Foo/note.md`) to other vault tools' `path` arguments, never the full markdown link.
Get statistics about the vault: total file count, total markdown size, recently modified files, semantic index status (if enabled). Paths in this tool's output are formatted as markdown links `[vault-relative-path.md](obsidian://...)` so users can Cmd/Ctrl-click to open in Obsidian. Preserve the link form when relaying paths to the user; pass only the bracket text (e.g. `01-Projects/Foo/note.md`) to other vault tools' `path` arguments, never the full markdown link.
Update YAML frontmatter fields in an existing note. Parses existing frontmatter, updates specified fields, preserves everything else. Set a field to null to remove it. Protected fields (type, created, tags) cannot be removed. Field values are validated against the note's type (e.g. task status must be: pending, active, done, cancelled; task priority must be: low, normal, high, urgent). Paths in this tool's output are formatted as markdown links `[vault-relative-path.md](obsidian://...)` so users can Cmd/Ctrl-click to open in Obsidian. Preserve the link form when relaying paths to the user; pass only the bracket text (e.g. `01-Projects/Foo/note.md`) to other vault tools' `path` arguments, never the full markdown link.
Extract all wikilinks from a file and resolve them to their full paths (accounting for ambiguities). Useful for understanding the internal link structure of a note. Paths in this tool's output are formatted as markdown links `[vault-relative-path.md](obsidian://...)` so users can Cmd/Ctrl-click to open in Obsidian. Preserve the link form when relaying paths to the user; pass only the bracket text (e.g. `01-Projects/Foo/note.md`) to other vault tools' `path` arguments, never the full markdown link.
Create a new note from a template. Notes must be created from templates to ensure proper frontmatter. Available templates: ${templateDescriptions || "(Loading...)"} Built-in variables (auto-substituted): - <% tp.date.now("YYYY-MM-DD") %> - Current date - <% tp.file.title %> - Derived from output path filename Required: frontmatter.tags - provide at least one tag for the note. Optional: frontmatter.status, frontmatter.priority, frontmatter.project, frontmatter.deciders, frontmatter.due, frontmatter.source (depending on template type). Pass custom <%...%> variables via the 'variables' parameter. Paths in this tool's output are formatted as markdown links `[vault-relative-path.md](obsidian://...)` so users can Cmd/Ctrl-click to open in Obsidian. Preserve the link form when relaying paths to the user; pass only the bracket text (e.g. `01-Projects/Foo/note.md`) to other vault tools' `path` arguments, never the full markdown link.
No error handling guidance in tool descriptions. Descriptions state what the tool does but do not guide the LLM on recovery strategies (e.g., 'If path resolution fails, try vault_search() to find the file'). vault_read mentions auto-redirect for large files but does not explain what the LLM should do if it encounters the redirect.
vault_stats has minimal schema. Its inputSchema has an empty properties object with no parameters documented. While this may be intentional (stats are unconditional), it should be explicit: 'No parameters required.'
vault_semantic_search conditionally available but no fallback documented. Description states 'Only available if OpenAI API key is configured' but does not tell the LLM what to do if the key is missing, should it retry, use vault_search instead, or fail gracefully?
vault_write template enum is empty in provided code. The template field has `enum: []` (templateNames is empty at definition time), which means the LLM cannot select a valid template. The enum is populated at runtime, but this is not visible in static analysis. Runtime-populated enums break offline/static tool discovery.