# Obsidian Mcp

> Fast MCP server for local Obsidian vault usage by AI Agents

- **Type:** MCP server
- **Install:** `agentstack add mcp-lstpsche-obsidian-mcp`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [lstpsche](https://agentstack.voostack.com/s/lstpsche)
- **Installs:** 0
- **Category:** [Productivity](https://agentstack.voostack.com/c/productivity)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [lstpsche](https://github.com/lstpsche)
- **Source:** https://github.com/lstpsche/obsidian-mcp

## Install

```sh
agentstack add mcp-lstpsche-obsidian-mcp
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# obsidian-mcp

[](https://github.com/lstpsche/obsidian-mcp/actions/workflows/ci.yml)
[](https://crates.io/crates/obsidian-mcp)
[](LICENSE)

A high-performance [MCP](https://modelcontextprotocol.io) server that gives AI agents full read/write access to [Obsidian](https://obsidian.md) vaults. Written in Rust. Ships as a single binary.

**No Obsidian plugins. No REST API. No Obsidian running. Just your vault on disk.**

## Why?

Existing solutions for AI + Obsidian require the Obsidian app to be running with a community plugin ([obsidian-local-rest-api](https://github.com/coddingtonbear/obsidian-local-rest-api)) and an MCP wrapper ([mcp-obsidian](https://github.com/MarkusPfundstein/mcp-obsidian)) on top. That's fragile, slow, and limited to what the REST API exposes.

obsidian-mcp talks directly to the filesystem. It understands the Obsidian format natively — wikilinks, frontmatter, tags, block references, periodic notes, the full graph. It builds fast in-memory indices on startup and keeps them synced via a filesystem watcher. The result is a single dependency-free binary that works whether Obsidian is open or not.

## Quick Start

```sh
# Install
cargo install obsidian-mcp

# Run (stdio — for MCP clients that launch the process)
obsidian-mcp /path/to/your/vault

# Run (HTTP — shared server for multiple agents)
obsidian-mcp --http /path/to/your/vault
```

Add to your MCP client config (Cursor, Claude Desktop, etc.) and you're done — 18 tools are available immediately.

## What It Can Do

| Category | Capabilities |
|----------|-------------|
| **Navigate** | List files, tree view, vault stats |
| **Read & write** | Create, read, overwrite, append, prepend, move, delete notes |
| **Patch** | Edit individual heading sections, block references, or frontmatter fields without touching the rest of the note |
| **Search** | BM25 full-text (Tantivy) with stemming, fuzzy matching, and per-field filtering. Semantic search via local embeddings. Regex. Tag and frontmatter queries. |
| **Graph** | Backlinks, outgoing links, broken link detection, orphan discovery |
| **Frontmatter** | Get/set/remove fields, query notes by metadata |
| **Periodic notes** | Daily, weekly, monthly, quarterly, yearly — with Obsidian-compatible date formats and template expansion |

All indices (metadata, BM25, embeddings) update in real time via a filesystem watcher.

## Installation

### From crates.io

```sh
cargo install obsidian-mcp
```

For **semantic search local compatibility mode** (`OBSIDIAN_SEMANTIC_MODE=local`), build with embeddings:

```sh
cargo install obsidian-mcp --features embeddings
```

The `embeddings` feature adds ~60 MB to the binary (ONNX Runtime). In daemon mode, model/runtime cache is shared under semantic home; local mode keeps in-process embedding support in the MCP binary.

On Windows, local embeddings builds require a recent MSVC Build Tools toolset for ONNX Runtime. MSVC 14.44+ is known to work; older VS 2019-era 14.2x toolsets may fail to link with `__std_find_trivial_8`. Use `--features embeddings-api` instead if you want semantic search through an external `/v1/embeddings` server without bundling ONNX Runtime.

For **API embedding backend** (OpenAI, Ollama, vLLM, LM Studio, or any `/v1/embeddings`-compatible endpoint):

```sh
cargo install obsidian-mcp --features embeddings-api
```

This adds no model weight to the binary — embeddings are computed by an external server. Both features can be compiled simultaneously; `OBSIDIAN_EMBEDDING_PROVIDER` selects which runs.

#### API backend examples

```sh
# OpenAI
OBSIDIAN_EMBEDDINGS=true
OBSIDIAN_EMBEDDING_PROVIDER=api
OBSIDIAN_EMBEDDING_API_KEY=sk-...
OBSIDIAN_EMBEDDING_API_MODEL=text-embedding-3-small

# Ollama (local, no auth)
OBSIDIAN_EMBEDDINGS=true
OBSIDIAN_EMBEDDING_PROVIDER=api
OBSIDIAN_EMBEDDING_API_BASE=http://localhost:11434/v1
OBSIDIAN_EMBEDDING_API_MODEL=nomic-embed-text
OBSIDIAN_EMBEDDING_API_KEY=unused

# vLLM / LM Studio
OBSIDIAN_EMBEDDINGS=true
OBSIDIAN_EMBEDDING_PROVIDER=api
OBSIDIAN_EMBEDDING_API_BASE=http://localhost:8000/v1
OBSIDIAN_EMBEDDING_API_MODEL=BAAI/bge-small-en-v1.5
OBSIDIAN_EMBEDDING_API_KEY=unused

# OpenRouter (25+ embedding models from multiple providers)
OBSIDIAN_EMBEDDINGS=true
OBSIDIAN_EMBEDDING_PROVIDER=api
OBSIDIAN_EMBEDDING_API_BASE=https://openrouter.ai/api/v1
OBSIDIAN_EMBEDDING_API_MODEL=openai/text-embedding-3-small
OBSIDIAN_EMBEDDING_API_KEY=sk-or-v1-...
```

### Pre-built binaries

Grab the latest from [GitHub Releases](https://github.com/lstpsche/obsidian-mcp/releases/latest):

| Platform | Archive |
|----------|---------|
| Linux x86_64 | `obsidian-mcp--x86_64-unknown-linux-gnu.tar.gz` |
| Linux ARM64 | `obsidian-mcp--aarch64-unknown-linux-gnu.tar.gz` |
| macOS Intel | `obsidian-mcp--x86_64-apple-darwin.tar.gz` |
| macOS Apple Silicon | `obsidian-mcp--aarch64-apple-darwin.tar.gz` |
| Windows x86_64 | `obsidian-mcp--x86_64-pc-windows-msvc.zip` |

Semantic daemon release assets are also published per target:

- `obsidian-semanticd--.tar.gz` (Unix)
- `obsidian-semanticd--.zip` (Windows)

### Install from source (edge)

If you have the repo cloned, you can install the latest `main` build locally:

```sh
./bin/install-edge
```

This pulls the latest `main` and runs `cargo install --path . --features embeddings`.

## Semantic Runtime Compatibility

Current semantic daemon API version: `1` (`DAEMON_API_VERSION` in `src/daemon/protocol.rs`).

| Component | Compatibility contract | Enforcement |
|----------|-------------------------|-------------|
| `obsidian-mcp` | Daemon API version must match exactly | MCP daemon `health` handshake validates `min_api_version`/`max_api_version` against current API version and fails fast on mismatch |
| `obsidian-semantic-search-plugin` | Daemon API version must match exactly | Plugin bootstrap performs daemon `health` handshake and surfaces explicit incompatibility notices |

Release asset compatibility expectations:

- Daemon auto-install clients expect release assets named `obsidian-semanticd--.{tar.gz|zip}` plus `checksums.sha256`.
- Plugin releases should publish `main.js`, `manifest.json`, and optional `styles.css` as GitHub release assets.

Upgrade guidance:

- Prefer upgrading `obsidian-mcp`, `obsidian-semanticd`, and `obsidian-semantic-search-plugin` together.
- If versions are skewed, startup/handshake fails with explicit API incompatibility errors rather than silent fallback.

## Transport Modes

obsidian-mcp supports two transports. Both are always compiled in — choose the one that fits your workflow.

### stdio (default)

The standard MCP transport. The AI client spawns the process and communicates over stdin/stdout.

**Use when:** your MCP client manages the server process (Cursor, Claude Desktop, most MCP clients).

```sh
obsidian-mcp /path/to/vault
```

Each client connection spawns its own process. Simple, zero-config, works everywhere.

### Streamable HTTP

A persistent HTTP server that multiple clients can connect to simultaneously.

**Use when:** you run multiple headless agents (`cursor agent -p`, parallel Claude sessions, etc.) against the same vault and want to share a single server process instead of spawning one per agent.

```sh
# Foreground (for development / process managers like launchd, systemd)
obsidian-mcp --http /path/to/vault

# Background (ad-hoc daemonize — spawns child, parent exits)
obsidian-mcp serve /path/to/vault
```

The `serve` command daemonizes the server and redirects logs to a platform-specific file:
- **macOS:** `~/Library/Logs/obsidian-mcp.log`
- **Linux:** `$XDG_STATE_HOME/obsidian-mcp/obsidian-mcp.log`
- **Windows:** `%LOCALAPPDATA%/obsidian-mcp/obsidian-mcp.log`

Default: `http://127.0.0.1:37842`. MCP tools are served at `/mcp`, health check at `/health`.

Benefits over stdio for multi-agent setups:
- **Shared index** — one in-memory BM25/embedding index instead of N copies
- **Lower resource usage** — single filesystem watcher, single process
- **Process independence** — server stays up when agents come and go
- **Standard observability** — HTTP health checks, logging, standard networking

Configure the address:

```sh
obsidian-mcp --http --port 9000 --host 0.0.0.0 /path/to/vault
# or via env vars
OBSIDIAN_TRANSPORT=http OBSIDIAN_HTTP_PORT=9000 obsidian-mcp /path/to/vault
```

### Server Management

```sh
obsidian-mcp serve /path/to/vault    # Start HTTP server in background
obsidian-mcp stop                    # Stop running server (default port)
obsidian-mcp stop --port 9000        # Stop server on specific port
obsidian-mcp restart /path/to/vault  # Stop + start (picks up new binary after upgrade)
```

`serve` and `restart` wait for the server to pass a `/health` check before reporting success (up to 15s). If the server fails during startup, the exit code and log path are reported.

## Client Setup

### Cursor (stdio)

`~/.cursor/mcp.json`:

```json
{
  "mcpServers": {
    "obsidian": {
      "command": "obsidian-mcp",
      "args": ["/path/to/your/vault"]
    }
  }
}
```

### Cursor (HTTP — shared server)

Start the server once:

```sh
obsidian-mcp serve /path/to/your/vault
```

Then point Cursor at it:

```json
{
  "mcpServers": {
    "obsidian": {
      "url": "http://127.0.0.1:37842/mcp"
    }
  }
}
```

All Cursor agents (IDE, CLI, headless) share the same server.

### Claude Desktop

```json
{
  "mcpServers": {
    "obsidian": {
      "command": "obsidian-mcp",
      "env": {
        "OBSIDIAN_VAULT_PATH": "/path/to/your/vault",
        "OBSIDIAN_EMBEDDINGS": "true"
      }
    }
  }
}
```

Config file location:
- macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
- Windows: `%APPDATA%\Claude\claude_desktop_config.json`

### Any MCP client

obsidian-mcp supports both **stdio** and **Streamable HTTP** MCP transports. Any MCP-compatible client can connect via either method. Pass the vault path as the first argument or via `OBSIDIAN_VAULT_PATH`.

## Running as a Service

For always-on HTTP mode, use your OS process manager with `--http` (not `serve`). This lets the process manager handle restarts, logging, and lifecycle — `serve` daemonizes itself, which conflicts with process managers that expect to own the child process.

### macOS (launchd)

Create `~/Library/LaunchAgents/com.obsidian-mcp.plist`:

```xml

  Label
  com.obsidian-mcp

  ProgramArguments
  
    /Users/YOU/.cargo/bin/obsidian-mcp
    --http
  

  EnvironmentVariables
  
    OBSIDIAN_VAULT_PATH
    /path/to/your/vault
    
  

  RunAtLoad
  

  KeepAlive
  

  StandardOutPath
  /Users/YOU/Library/Logs/obsidian-mcp/launchd.out.log

  StandardErrorPath
  /Users/YOU/Library/Logs/obsidian-mcp/launchd.err.log

```

> **Important:** launchd does not source your shell profile (`~/.zshrc`, `~/.bashrc`). All environment variables must be defined in the plist's `EnvironmentVariables` section.

```sh
# Load
launchctl load ~/Library/LaunchAgents/com.obsidian-mcp.plist

# Unload (stop)
launchctl unload ~/Library/LaunchAgents/com.obsidian-mcp.plist

# Restart (after upgrade)
launchctl unload ~/Library/LaunchAgents/com.obsidian-mcp.plist && \
  launchctl load ~/Library/LaunchAgents/com.obsidian-mcp.plist
```

### Linux (systemd)

Create `~/.config/systemd/user/obsidian-mcp.service`:

```ini
[Unit]
Description=obsidian-mcp MCP server
After=network.target

[Service]
ExecStart=%h/.cargo/bin/obsidian-mcp --http
Environment=OBSIDIAN_VAULT_PATH=/path/to/your/vault
# Add embedding env vars if needed:
# Environment=OBSIDIAN_EMBEDDINGS=true
# Environment=OBSIDIAN_EMBEDDING_PROVIDER=api
# Environment=OBSIDIAN_EMBEDDING_API_KEY=sk-...
# Environment=OBSIDIAN_EMBEDDING_API_BASE=https://api.openai.com/v1
# Environment=OBSIDIAN_EMBEDDING_API_MODEL=text-embedding-3-small
Restart=on-failure
RestartSec=5

[Install]
WantedBy=default.target
```

```sh
systemctl --user daemon-reload
systemctl --user enable --now obsidian-mcp

# Check status
systemctl --user status obsidian-mcp

# Restart (after upgrade)
systemctl --user restart obsidian-mcp

# View logs
journalctl --user -u obsidian-mcp -f
```

## Upgrading

```sh
# Install new version
cargo install obsidian-mcp --force
# With features:
cargo install obsidian-mcp --features embeddings,embeddings-api --force

# Restart the running server to pick up the new binary
obsidian-mcp restart /path/to/vault

# Or if using a process manager:
launchctl unload ~/Library/LaunchAgents/com.obsidian-mcp.plist && \
  launchctl load ~/Library/LaunchAgents/com.obsidian-mcp.plist
# systemd: systemctl --user restart obsidian-mcp
```

> `cargo install --force` replaces the binary on disk but does **not** restart any running server. You must restart manually — otherwise the old version continues serving.

## Search

Three tiers, each suited to different needs.

### BM25 Full-Text — `search_text`

On by default. Powered by [Tantivy](https://github.com/quickwit-oss/tantivy), rebuilt in-memory on startup (
All 18 tools (click to expand)

### Navigation

| Tool | Parameters | Description |
|------|-----------|-------------|
| `vault_list` | `path?`, `recursive?`, `glob?`, `format?`, `max_depth?` | List files (`format: "list"`) or tree view (`format: "tree"`) |
| `vault_info` | — | Aggregate vault statistics |

### Note CRUD

| Tool | Parameters | Description |
|------|-----------|-------------|
| `note_read` | `path` | Read full note content |
| `note_create` | `path`, `content?`, `frontmatter?` | Create a new note |
| `note_write` | `path`, `content` | Overwrite note content |
| `note_insert` | `path`, `content`, `position?` | Insert at end (`"end"`, default) or beginning (`"beginning"`) |
| `note_patch` | `path`, `operation`, `target_type`, `target`, `content` | Patch a heading section, block ref, or frontmatter field |
| `note_delete` | `path`, `confirm` | Delete a note (requires `confirm: true`) |
| `note_move` | `from`, `to` | Move or rename a note |

For `note_patch` heading targets, bare heading text such as `"Log"` is canonical. ATX marker-prefixed targets such as `"## Log"` are also accepted, so headings copied from `note_inspect` with `view: "targets"` can be used directly.

### Search

| Tool | Parameters | Description |
|------|-----------|-------------|
| `search_text` | `query`, `fuzzy?`, `fields?`, `context_length?`, `max_results?` | BM25 full-text search with stemming |
| `search_semantic` | `query`, `top_k?`, `include_content?`, `lexical_prefetch?`, `alpha?` | Semantic similarity search |
| `search_regex` | `pattern`, `context_length?`, `max_results?` | Regex pattern search |
| `search_metadata` | `type`, `tag?`, `include_nested?`, `field?`, `value?`, `operator?` | Find by tag (`type: "tag"`) or frontmatter (`type: "frontmatter"`) |

### Introspection & Frontmatter

| Tool | Parameters | Description |
|------|-----------|-------------|
| `note_inspect` | `path`, `view?` | Metadata (`"metadata"`, default) or patchable targets (`"targets"`) |
| `frontmatter` | `action`, `path`, `key?`, `value?` | Get (`"get"`), set (`"set"`), or remove (`"remove"`) frontmatter fields |

### Graph & Links

| Tool | Parameters | Description |
|------|-----------|-------------|
| `wikilinks` | `query`, `path?` | Backlinks, outgoing, broken, or orphans (`query: "backlinks"/"outgoing"/"broken"/"orphans"`) |

### Periodic Notes

| Tool | Parameters | Description |
|------|-----------|-------------|
| `periodic` | `action`, `period`, `date?`, `content?`, `limit?` | Get, create, or list periodic notes (`action: "get"/"create"/"list"`) |

### Utility

| Tool | Parameters | Description |
|------|-----------|-------------|
| `open_in_obsidian` | `path`, `new_leaf?` | Open note in Obsidian via `obsidian://` URI |

## Tool Filtering

Control which tools are exposed via the `OBSIDIAN_TOOLS` environment variable or per-session `X-Obsidian-Tools` HTTP header.

| Value | Effect |
|-------|--------|
| `full` (or unset) | All 18 tools |
| `core` | 14 tools — drops `search_semantic`, `search_regex`, `periodic`, `open_in_obsidian` |
| `read` | 10 tools — read-only (no c

…

## Source & license

This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [lstpsche](https://github.com/lstpsche)
- **Source:** [lstpsche/obsidian-mcp](https://github.com/lstpsche/obsidian-mcp)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/mcp-lstpsche-obsidian-mcp
- Seller: https://agentstack.voostack.com/s/lstpsche
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
