Skip to main content
Glama
bettyguo

obsidian-mcp

by bettyguo
README.md
# obsidian-mcp

> Your agent, native in your Obsidian vault. MIT-licensed, local-first, MCP-native.

An MCP (Model Context Protocol) server plus a bundle of seven Claude Skills for [Obsidian](https://obsidian.md) vaults. Lets Claude, Cursor, ChatGPT, and any MCP-capable agent read, search, write, link, and reason about your vault while respecting Obsidian's conventions (wikilinks, frontmatter, tags, daily notes, MOCs).

```bash
pipx install obsidian-mcp
obsidian-mcp install --client claude-desktop --vault ~/Vaults/main
# Restart Claude Desktop and ask: "What's in my vault?"
```

[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![Python 3.11+](https://img.shields.io/badge/python-3.11+-blue.svg)](https://www.python.org/)

---

## Why this exists

Most existing Obsidian-MCP wrappers are read-only file listers. Few of them respect Obsidian's conventions (wikilink graph semantics, frontmatter round-trip, tag hierarchies, daily-note path patterns, MOCs), and none ship a workflow-centric skill bundle.

This project does both:

1. MCP-native + filesystem-direct. Structured tool calls, cross-client portable (Claude Desktop, Cursor, Codex, ChatGPT). No Local REST API plugin dependency. The vault is just a folder; we read and write it directly.
2. Seven workflow-centric Claude Skills. `kepano/obsidian-skills` (Steph Ango / Obsidian's CEO) ships file-format primitives; our skills compose them into end-user rituals: daily-note synthesis, MOC building, orphan integration, tag-tree refactoring.
3. Round-trip safety as a hard requirement. Every note we touch is parsed, mutated, re-serialized, and verified byte-identical. We don't mangle your markdown. [See the protocol.](docs/write-safety.md)
4. Local-first. Vault content never leaves your machine except via the MCP transport, where it's returned only to the LLM you've explicitly chosen. [See the privacy doc.](docs/privacy.md)

Complementary, not adversarial, to in-Obsidian AI plugins like [Smart Connections](https://github.com/brianpetro/obsidian-smart-connections) and [Copilot for Obsidian](https://github.com/logancyang/obsidian-copilot): those embed an LLM UI inside Obsidian; we let an agent outside Obsidian reach in. Use both.

---

## What you can ask

```
> Summarize the threads in my last 90 days of daily notes about RAG research.
> Find orphan notes in my vault that should connect to my "second-brain" MOC.
> Build a Map of Content for "agent design", linking the 30 most relevant notes.
> Refactor my tag tree — I have #ai, #AI, and #artificial-intelligence all in use.
> What are the most central notes in my vault right now?
> Prep a writing scratchpad for an essay on "evals as a craft".
> Walk my Inbox folder and help me integrate yesterday's captures.
> Compare my Q1 and Q2 daily notes — what's the trajectory of my thinking?
```

Each maps to a tool (or skill) we ship. The full tool surface — 22 MCP tools — is documented in [docs/tools.md](docs/tools.md).

---

## Quickstart

### 1. Install

```bash
pipx install obsidian-mcp
```

Or in a Python environment:

```bash
pip install obsidian-mcp
```

### 2. Register with your client

```bash
# For Claude Desktop:
obsidian-mcp install --client claude-desktop --vault /path/to/your/vault

# For Cursor:
obsidian-mcp install --client cursor --vault /path/to/your/vault
```

The install command writes an entry to your client's config and preserves any other MCP servers you have configured. Restart the client to pick up the new server.

### 3. Verify

```bash
obsidian-mcp doctor --vault /path/to/your/vault
```

Reports vault topology, daily-note pattern, round-trip safety, and graph stats. If something is wrong, this is where it surfaces.

### 4. Ask

Open Claude Desktop / Cursor / your client of choice and ask one of the example queries above. The agent will discover the tools automatically.

---

## Privacy

**Your vault stays on your machine.** Indexing, embeddings, and graph analysis run locally.

The only network traffic generated by `obsidian-mcp` itself is:
1. A one-time ~150MB download of the [`BAAI/bge-small-en-v1.5`](https://huggingface.co/BAAI/bge-small-en-v1.5) embedding model from Hugging Face. After that, search runs offline. Set `OBSIDIAN_MCP_OFFLINE=1` to refuse the download.
2. The MCP transport itself, which carries data **only to the LLM you've chosen** (e.g. `api.anthropic.com`). We never bind to non-loopback addresses.

No telemetry. No analytics. No error reporting. No "anonymous statistics." See [docs/privacy.md](docs/privacy.md) for the full data-flow inventory and verification instructions.

---

## Respects your conventions

- **Round-trip safe.** Every note we modify can be re-parsed and re-serialized with byte-identical output. Comments, scalar styles (`"x"` vs `'x'` vs bare), key order, flow vs block YAML, trailing newlines, BOMs — all preserved. We use `ruamel.yaml` round-trip mode. ([Why this matters](docs/write-safety.md))
- **Wikilinks.** Full grammar: `[[Link]]`, `[[Link|Alias]]`, `[[Link#Heading]]`, `[[Link#^block]]`, `![[embed]]`, `![[image.png|400]]`, intra-note shortcuts. Rename a note → every reference in the vault is rewritten with the alias and subpath preserved verbatim.
- **Frontmatter.** YAML round-trip. Plural-list reserved keys on write (`aliases`, `tags`, `cssclasses`); legacy singular forms tolerated on read.
- **Tags.** Hierarchical (`#research/rag/eval`). Cross-vault rename. Tag-tree refactor workflow built in.
- **Daily notes.** Auto-detects [Periodic Notes](https://github.com/liamcain/obsidian-periodic-notes) → core Daily Notes → heuristic. Supports moment.js path templates.
- **Dataview / Templater / Excalidraw.** Read structure, never execute the JS. `.canvas`, `.base`, `.excalidraw.md` files are read-only by default — use a dedicated tool (post-v1) to mutate them.

The full convention spec is in [docs/conventions.md](docs/conventions.md).

---

## Skill catalog

Each skill is a markdown SKILL.md file installed alongside your client's skills directory. They compose the MCP tools into common workflows.

| Skill | What it does |
| ---  | ---          |
| `/daily-summary`     | Reads last N daily notes, surfaces 3–7 themes, drafts a synthesis note linking back to originals. |
| `/connect-ideas`     | Finds two notes that should be linked but aren't. Explains why and proposes the insertion. |
| `/find-orphans`      | Surfaces orphan notes near a topic; helps integrate them with per-orphan confirmation. |
| `/refactor-tag-tree` | Detects case chaos (`#AI`/`#ai`/`#Ai`), near-duplicates, and singletons; walks you through consolidation. |
| `/build-MOC`         | Interactive Map-of-Content building. Static wikilinks default; Dataview opt-in. |
| `/review-and-link`   | Walks your recent notes / Inbox folder; per-note review with link suggestions. |
| `/prep-for-writing`  | Given a topic, gathers relevant notes + creates a writing scratchpad with quotes and citations. |

Source: [skills/](skills/). Design spec: [docs/skills.md](docs/skills.md).

---

## Compared to ...

- **[Smart Connections](https://github.com/brianpetro/obsidian-smart-connections)**: in-Obsidian UI plugin with embedded LLM chat. Complementary — they own the in-app UX; we own the out-of-app agent surface.
- **[Copilot for Obsidian](https://github.com/logancyang/obsidian-copilot)**: same shape — in-app UI plugin. Complementary.
- **[kepano/obsidian-skills](https://github.com/kepano/obsidian-skills)**: filesystem-direct Claude Skills for `.md` / `.canvas` / `.base` / `obsidian-cli`. We **layer additively** on top — our skills are workflows on top of kepano's file-format primitives, and we detect and defer to kepano's skills when present.
- **[cyanheads/obsidian-mcp-server](https://github.com/cyanheads/obsidian-mcp-server)** (TypeScript, Apache-2.0): closest MCP-tool-depth competitor. They require the Local REST API plugin; we don't (filesystem-direct). They ship dev-internal skills; we ship end-user workflow skills.
- **[MarkusPfundstein/mcp-obsidian](https://github.com/MarkusPfundstein/mcp-obsidian)**: highest stars by default-recommendation inertia. Generic file ops over the REST API plugin; no wikilink/frontmatter/daily-note semantics; no skills.

Full landscape recon in [docs/competitive.md](docs/competitive.md).

---

## Power-user FAQ

**Will this break my notes?** No — that's the single thing we won't do. Every write goes through `safe_write` which (1) refuses to mutate `.canvas` / `.base` / `.excalidraw.md` / files containing Templater execution blocks; (2) verifies the proposed bytes re-parse and re-serialize byte-identically; (3) writes via atomic temp-file rename; (4) backs up the pre-write bytes to `.obsidian-mcp/last-write.bak`. If anything goes sideways, `obsidian-mcp undo` restores the last write. [Protocol details.](docs/write-safety.md)

**Does it touch my Templater?** We read the structure (so the LLM knows the file is a template) but we never execute Templater code, and we refuse to mutate files containing `<%* ... %>` execution blocks unless you pass `force=true`. Same posture for `dataviewjs` fences.

**What about my Excalidraw drawings?** Treated as opaque. We index the frontmatter and any wikilinks in the back-of-note Markdown; we never touch the Excalidraw scene payload below the fence.

**Will it eat my hand-crafted YAML formatting?** No. `ruamel.yaml` round-trip mode preserves comments, scalar styles (`"x"` vs `'x'` vs bare), key order, flow-vs-block sequence style, and trailing newline counts. We verify byte-identity on every write.

**Does it work while Obsidian has the file open?** On Windows the OS file lock will block our write — we'll surface a clear error. On macOS/Linux the write succeeds at the filesystem level, but Obsidian's in-memory buffer may overwrite ours on save (this is a TOCTOU race we currently can't prevent). Best practice for v0.1: close Obsidian (or use it read-only) when running write-capable skills. Detection + opt-in `--strict-locks` refusal is on the v0.2 roadmap.

**Does it run my Dataview queries?** No. We parse them for structure (extracting `link("X")` references for the backlink graph) but we never execute DQL or DataviewJS. Plugin behavior changes; we don't keep up; users get burned.

**What if my vault is 10,000 notes?** Indexing on first run takes ~30s on a modern laptop. Subsequent runs use the cached index in `.obsidian-mcp/`. Search latency is <500ms.

**Can I use this without Obsidian installed?** Yes — your vault is just a folder of Markdown files. We detect Obsidian's config if present (for daily-note pattern detection), but it's optional.

**Does it work with [Obsidian Sync / iCloud / Syncthing]?** Yes. We don't sync; you handle that. We use atomic writes (`os.replace`) so a sync race can't leave a half-written file.

**Does it write to my `.obsidian/` folder?** No. Our state lives in `.obsidian-mcp/` at the vault root, parallel to `.obsidian/`. We READ specific files in `.obsidian/` (`app.json` for link format, `daily-notes.json` and `plugins/periodic-notes/data.json` for periodic-note patterns). We never write there.

---

## CLI reference

```bash
obsidian-mcp serve --vault PATH                  # Start the MCP server (stdio by default)
obsidian-mcp install --client {claude-desktop,cursor} --vault PATH
obsidian-mcp doctor --vault PATH                 # Sanity-check: walk, parse, round-trip, build indexes
obsidian-mcp roundtrip --vault PATH              # Verify every note round-trips byte-identically
obsidian-mcp undo --vault PATH                   # Restore the most recent safe_write backup
obsidian-mcp diff PATH --vault PATH              # Show diff against last-write backup
obsidian-mcp detect-vaults                       # List vaults known to your Obsidian config
```

---

## Roadmap

- **v0.1 (current):** MCP server + 7 Skills + CLI. Cross-platform (macOS, Linux, Windows). Local-only.
- **v0.2:** Watchfiles-based incremental index updates (no manual `reindex` needed). `dry-run` subcommand for every write tool.
- **v0.3:** `.canvas` and `.base` dedicated tools (read + mutate via the format spec).
- **v0.4:** Logseq compatibility (separate `logseq-mcp` sister project, evaluated post-launch).
- **v1.0:** Stable API guarantee for tool signatures. Optional opt-in remote-embedding mode (OpenAI / Voyage / Cohere).

Not on the roadmap: a hosted obsidian-mcp.com, a commercial tier, an Obsidian-plugin counterpart in v1. The 90-hour scope can't absorb a plugin (separate manifest/build/UI/review pipeline), and a commercial tier directly contradicts the local-first posture.

---

## Contributing

Bug reports, feature requests, and PRs are welcome. Good first issues are labeled in the [issue tracker](https://github.com/obsidian-mcp/obsidian-mcp/issues?q=is%3Aopen+label%3A%22good+first+issue%22).

Run the test suite locally:

```bash
git clone https://github.com/obsidian-mcp/obsidian-mcp
cd obsidian-mcp
python -m venv .venv && . .venv/bin/activate  # Windows: .venv\Scripts\activate
pip install -e ".[dev]"
pytest -q
ruff check src tests
```

If your PR touches any code that reads or writes vault content, please add a test against the fixture vault in `tests/fixtures/test-vault/`. The round-trip property test runs on every PR.

---

## License

MIT — see [LICENSE](LICENSE).

Built with [FastMCP](https://github.com/jlowin/fastmcp), [ruamel.yaml](https://yaml.readthedocs.io/), [bm25s](https://github.com/xhluca/bm25s), [sentence-transformers](https://www.sbert.net/), [NetworkX](https://networkx.org/), and [typer](https://typer.tiangolo.com/).