
Obsidian MCP Server
io.github.tylern91Published by GitHub account tylern91v0.3.0Updated Oct 24, 2026
Filesystem-based MCP server for Obsidian vaults — read, search, and edit notes, no app required.
Overview
Lets an assistant read, search, edit, and organize notes in a local Obsidian vault directly on the filesystem, without Obsidian running.
- What you can do
- A local stdio MCP server that works on an Obsidian vault directory. It exposes tools to read, write, patch, move, and delete notes; parse and update YAML frontmatter; add, remove, list, and rename tags; compute backlinks; run BM25 full-text and RE2 regex or glob searches; read batch notes; fetch periodic notes; and audit the vault for orphans, dangling links, untagged notes, and duplicate titles. It also provides read-only resources and prompt templates such as summarize_note and vault_health_check.
- When to use it
- Useful when an assistant should work with a personal or team Obsidian vault: summarizing and reviewing notes, finding related notes, cleaning up tags and links, or searching note content. It is a good fit if you want vault access without keeping the Obsidian app open.
- Requirements
- Runs as a local process on the user's machine; the vault path is required via the --vault flag or the OBSIDIAN_VAULT_PATH environment variable. Installable as a Claude Desktop .mcpb bundle, a release binary, Homebrew, or built from source with Go 1.27+. Optional HTTP transport uses TLS and bearer token auth. No accounts or API keys are declared.
Installation
In SourceWeft
- Open Obsidian MCP Server in the dashboard and add it to a workspace.
- Enable the server for the chats that should use its tools.
Desktop only via STDIO. STDIO servers start a local process, so they need the SourceWeft desktop host.
Other MCP clients
Follow the launch instructions in the repository.
README
obsidian-mcp-server
[CI] [Release] [Go Report Card] [License: Apache-2.0] [Go Version]
A Go Model Context Protocol (MCP) server for Obsidian vaults. It gives AI agents and development tools direct filesystem access to your vault — no running Obsidian instance required.
Features
- Read, write, and list notes and directories via MCP tools
- Frontmatter — parse and update YAML frontmatter with format-preserving rewrites
- Tags — extract inline
#tags, aggregate vault-wide tag counts, add/remove tags - Backlinks — on-demand reverse link graph (wikilinks and markdown links)
- Mutations — heading-anchored patch, safe delete, and move with confirmation guards
- Full-text search — BM25 Okapi ranked search with match snippets
- Regex/glob search — RE2 regex or filepath glob search across paths and content
- Path security — 4-layer validation: lexical checks, ignore/extension filters, case-insensitive existence lookup, and symlink escape prevention
- Stdio transport — works with any MCP client (Claude Code, Claude Desktop, etc.)
- Streamable HTTP transport (optional) — TLS 1.3 + bearer token auth by default, loopback-only unless explicitly widened; see
--transport httpin Configuration andSECURITY.md§ HTTP transport - Zero Obsidian dependency — operates on the vault directory directly
- Token counting — responses include approximate token counts (cl100k_base)
MCP Tools
search_notes, search_regex, list_directory, and get_recent_changes results also include an
obsidian://open deepLink field per note, built from --vault-name (see Configuration below).
Notes
patch_note semantics: position controls where content is inserted relative to the heading:
before— inserted immediately before the heading lineafter— inserted after the heading's body (before the next same-level or higher heading)replace_body— replaces everything between the heading line and the next same-level heading
search_notes parameters:
Returns: { query, results: [{ path, score, matchCount, matches: [{line, snippet, term}], tokenCount, reason }], total }
search_regex parameters:
Returns: { pattern, scope, results: [{ path, matches: [{line, snippet}] }], total }
Batch tools (read_multiple_notes, get_notes_info): The paths parameter is a JSON array string — e.g. '["Notes/foo.md","Notes/bar.md"]'. summary:true returns headOf (first N runes from headChars, default 200) instead of full content, which is useful for large notes to stay within context limits. Both tools enforce --max-batch (default 10); requests with more paths are silently truncated and the response includes "truncated": true.
Optimistic concurrency (if_match / etag): read_note, read_multiple_notes, and get_notes_info return a SHA-256 etag of the note's content. Pass that value as if_match on write_note, patch_note, update_frontmatter, manage_tags, delete_note, or move_note to make the write conditional — if the note has changed since you read it, the call fails with a REVISION_CONFLICT error instead of silently overwriting someone else's edit. if_match is optional everywhere; omitting it writes unconditionally, as before. Two edge cases: passing if_match for a note that doesn't exist yet is always a conflict (it never creates the note), and move_note's dryRun:true preview does not enforce if_match.
Periodic notes (get_periodic_note, get_recent_periodic_notes): Configuration (folder and date format per granularity) is read from .obsidian/plugins/periodic-notes/data.json inside the vault. If that file is missing, built-in defaults are used: daily notes use YYYY-MM-DD in Daily Notes/, weekly notes use gggg-[W]ww in Weekly Notes/, and so on. offset=0 resolves to the current period, offset=-1 to the previous period (yesterday, last week, etc.), and offset=+1 to the next period. createIfMissing=true creates an empty note at the resolved path if it does not already exist.
get_vault_stats: Returns noteCount, totalBytes, totalLinks, totalTags, topTags (top 20 by count), oldestNote, newestNote, and vaultRoot. Setting includeTokenCounts:true runs token counting across every note — this is expensive for large vaults and is disabled by default.
audit_notes classes:
orphans— notes that have no tags AND no incoming wikilinks or markdown links (completely isolated notes)dangling-links— notes containing links to vault paths that do not exist (broken references)untagged— notes with no frontmatter tags and no inline#tagsduplicate-titles— multiple notes sharing the same filename stem, which causes wikilink ambiguity
Each class result is capped at limit entries (default 20). When results are truncated, the response includes "truncated": true.
MCP Prompts
Prompts are server-defined conversation starters that the host (Claude Code, Claude Desktop) exposes in its UI. Each prompt pulls live vault data and constructs a ready-to-use message for the LLM.
Prompts are invoked from the host's prompt picker (e.g. / in Claude Code). They never modify the vault.
MCP Resources
Resources are read-only vault data that the host can attach directly to a conversation context window — no explicit tool call required.
Static resources (obsidian://vault/*) are always available in the resource picker. Template resources are resolved when the host reads them — if the note does not exist, the resource returns an explanatory empty body instead of an error.
Installation
Install script
Downloads the right binary for your OS/architecture, verifies its checksum, and installs it to
~/.local/bin (override with a second argument):
Pin a version instead of latest:
Claude Desktop (.mcpb bundle)
Download obsidian-mcp-<version>.mcpb from the latest release and double-click it — Claude Desktop installs the extension and prompts for your vault path. No manual JSON editing.
Release binary
Download a prebuilt binary from the latest release, verify its checksum, and install:
Homebrew (macOS/Linux)
go install
Requires Go 1.27+ to build from source. Building with GOTOOLCHAIN=local on an older Go
requires upgrading first — GOTOOLCHAIN=auto (the default since Go 1.21) downloads a matching
toolchain automatically.
Build from source
Requires Go 1.27+. Building with GOTOOLCHAIN=local on an older Go
requires upgrading first — GOTOOLCHAIN=auto (the default since Go 1.21) downloads a matching
toolchain automatically.
Usage
Claude Code
Claude Desktop
Add to claude_desktop_config.json:
Cursor
Edit the vault path after install — the deeplink can't know it in advance.
VS Code
[Install in VS Code] [Install in VS Code Insiders]
Edit the vault path after install — the deeplink can't know it in advance.
Direct
Print the version and exit:
Configuration
Configuration follows CLI flag > environment variable > default precedence.
Examples
Precedence in action: with OBSIDIAN_LOG_LEVEL=debug exported, obsidian-mcp --vault ... --log-level info runs at info — the explicit flag wins. Unset flags inherit the env var; if neither is set, the default applies.
Security
All paths are validated through a 4-layer security model before any filesystem operation:
- Lexical — rejects absolute paths,
..traversal, and null bytes - Filter — blocks ignored patterns (
.git,.obsidian, etc.) and unapproved extensions - Existence — verifies the file exists with a case-insensitive fallback; rejects ambiguous matches
- Symlink — resolves symlinks and verifies the target remains inside the vault root
The optional --transport http listener has its own security posture (TLS, bearer auth,
loopback-only default, session binding) — see SECURITY.md § HTTP transport.
Project Structure
Development
License
Source: README.md at commit f1de1bf
Tools
0Version history
1- v0.3.0LatestSep 16, 2026
Score
50% of the applicable checks met
How complete this listing is, computed from the registry entry, the endpoint and public sources. Not a rating of the server and not a statement that it is safe or working today: reachability is a dated check, and no installs or reviews go into the score.
- Reached in the last 30 days25 pts
Keep the endpoint answering the MCP handshake; SourceWeft probes it every 30 days.
- Auth declared10 pts
Declare the credential headers in the registry entry, or keep the endpoint answering the probe so its auth can be classified.
- Tools listed15 pts
Answer tools/list without a credential, or ship a package that starts in a sandbox without one.
- DescriptionRequired15 pts
- Logo10 pts
- Documentation15 pts
- License10 pts
