# MCP Vault Bridge [![CI](https://github.com/allexcd/obsidian-mcp/actions/workflows/ci.yml/badge.svg)](https://github.com/allexcd/obsidian-mcp/actions/workflows/ci.yml) [![Release](https://github.com/allexcd/obsidian-mcp/actions/workflows/tag-release.yml/badge.svg)](https://github.com/allexcd/obsidian-mcp/actions/workflows/tag-release.yml) [![License: MIT](https://img.shields.io/github/license/allexcd/obsidian-mcp)](LICENSE) [![Node.js >=20](https://img.shields.io/badge/node-%3E%3D20-brightgreen)](package.json) [![Latest release](https://img.shields.io/github/v/release/allexcd/obsidian-mcp?include_prereleases&sort=semver)](https://github.com/allexcd/obsidian-mcp/releases) Read-only Obsidian vault bridge for MCP clients — connect Claude Desktop and LM Studio to your notes with exclusion-based privacy controls and optional semantic search. ## Security - **Read-only.** No write, delete, shell, or command-execution tools exist. - **Token-gated.** The bridge only accepts requests with the bearer token generated by the plugin. - **Exclusion-based.** Folders, files, and tags can be excluded before connecting any MCP host. - **Always denied.** Hidden folders, `.obsidian`, `.trash`, `.git`, and path-traversal patterns are blocked regardless of exclusions. - **Embeddings off by default.** When enabled, note chunks are sent to your configured embedding endpoint — use a local model (LM Studio, Ollama) to keep everything on-device. - **No telemetry.** Vault content returned by MCP tools may be forwarded to the model by the host. Claude Desktop runs the MCP server locally, but Claude model calls are cloud-side. LM Studio can remain fully local with local chat and embedding models. ## Install ### End users 1. Install **MCP Vault Bridge** from Obsidian Community Plugins, or download the latest `mcp-vault-bridge-X.Y.Z.zip` from the [Releases](https://github.com/allexcd/obsidian-mcp/releases) page. 2. For zip installs, unzip and copy the `mcp-vault-bridge` folder into your vault: ```text Your Vault/.obsidian/plugins/mcp-vault-bridge/ ``` 3. Restart Obsidian (or reload community plugins) and enable **MCP Vault Bridge**. 4. Open the plugin settings, click **Check runtime**, then **Install SQLite runtime**. > Node.js 20+ and npm must be available for the runtime install step. If they are missing the settings screen will say so. > Obsidian installs only `manifest.json`, `main.js`, and `styles.css`. When the plugin is enabled it creates the local `mcp-server.cjs` and runtime `package.json` inside its installed plugin folder. `node_modules` is created only when you click **Install SQLite runtime**. ### From source ```bash npm install npm run build # builds all packages + the community-plugin-shaped plugin folder npm test # runs the test suite ``` To install directly into a local vault for development: ```bash npm run plugin:install -- --vault "/absolute/path/to/Test Vault" ``` ## Connect ### Claude Desktop Open the Claude Desktop MCP config (`Developer → Edit config`) and add: ```json { "mcpServers": { "obsidian-vault": { "command": "node", "args": [ "/ABSOLUTE/PATH/TO/Your Vault/.obsidian/plugins/mcp-vault-bridge/mcp-server.cjs" ], "env": { "OBSIDIAN_MCP_BRIDGE_URL": "http://127.0.0.1:27125", "OBSIDIAN_MCP_TOKEN": "PASTE_TOKEN_FROM_OBSIDIAN_PLUGIN" } } } } ``` Copy the token from the Obsidian plugin settings. Restart Claude Desktop after saving. > **Paths:** use the full absolute path starting with `/` on macOS/Linux. Spaces are fine as-is in JSON — do not escape them with `\`. On Windows, double the backslashes or use forward slashes. ### LM Studio Add the same config to LM Studio's `mcp.json`. Without embeddings, vault search uses SQLite full-text search, which is fast and works well for exact words and phrases. ```json { "mcpServers": { "obsidian-vault": { "command": "node", "args": [ "/ABSOLUTE/PATH/TO/Your Vault/.obsidian/plugins/mcp-vault-bridge/mcp-server.cjs" ], "env": { "OBSIDIAN_MCP_BRIDGE_URL": "http://127.0.0.1:27125", "OBSIDIAN_MCP_TOKEN": "PASTE_TOKEN_FROM_OBSIDIAN_PLUGIN" } } } } ``` ### Optional embeddings Embeddings are optional. Without them, search uses SQLite full-text search: it is local, fast, and good for exact words, titles, tags, and phrases. With embeddings enabled, the MCP server can also do semantic/vector search, so queries like “notes about long-term planning” can find notes that use different wording. The plugin/MCP server does not automatically know which embedding model LM Studio loaded. The model value must match the identifier exposed by LM Studio's embeddings endpoint. If no embedding model is loaded, search still works through SQLite full-text search, but semantic search and `related_notes` are unavailable. For LM Studio, load an embedding model such as `nomic-embed-text-v1.5`, start the local server, then add these env vars to the same MCP config: ```json "env": { "OBSIDIAN_MCP_BRIDGE_URL": "http://127.0.0.1:27125", "OBSIDIAN_MCP_TOKEN": "PASTE_TOKEN_FROM_OBSIDIAN_PLUGIN", "OBSIDIAN_MCP_EMBEDDINGS": "on", "OBSIDIAN_MCP_EMBEDDING_BASE_URL": "http://127.0.0.1:1234/v1", "OBSIDIAN_MCP_EMBEDDING_MODEL": "nomic-embed-text-v1.5" } ``` Claude Desktop works the same way: it launches the local MCP server, and that server can call LM Studio's local embedding endpoint if these env vars are configured. Claude model calls are still cloud-side, but embedding calls stay local when they point to LM Studio. See [LM Studio with embeddings](docs/lm-studio-embeddings.md) for the longer setup guide. ### Example prompts Without embeddings, ask for exact words, paths, tags, folders, and known topics: - “What notes do I have in my vault?” - “Find notes tagged `#project`.” - “Search my vault for `meeting notes`.” - “Read `Projects/Roadmap.md` and summarize it.” - “Show backlinks and outgoing links for `Ideas/Local AI.md`.” With embeddings enabled, you can ask more conceptual questions because the MCP has a dedicated `ask_vault` tool and semantic search can find related ideas even when the exact words differ: - “Search my vault with semantic search for recurring themes.” - “Find notes related to long-term planning, even if they do not use those words.” - “What themes keep repeating across my notes about work and focus?” - “What are the common themes across my notes?” - “Which notes are conceptually similar to `Ideas/Local AI.md`?” - “Find notes that might help me make sense of this project direction.” - “Summarize the main ideas in my vault about learning, memory, and writing.” ## Vault Scope & Exclusions The plugin scans the vault through Obsidian and shows detected folders, files, and tags in its settings. Regular Markdown notes are included by default. | Exclusion type | What it hides | |---|---| | Excluded folders | Every note inside a folder, e.g. `Private` | | Excluded files | A single exact path, e.g. `Inbox/Secret.md` | | Excluded tags | Any note carrying a tag, e.g. `#private` | After changing exclusions, click **Refresh preview** in the plugin settings, then run `refresh_index` from your MCP host so the SQLite index reflects the new scope. When you add or edit notes later, ask your MCP client to refresh the index: > “Refresh the vault index.” This calls `refresh_index`, updates SQLite, and refreshes embeddings too if they are enabled. ## MCP Tools | Tool | Description | |---|---| | `vault_status` | Plugin version, vault name, included note count, scope summary | | `refresh_index` | Rebuild the SQLite index (and embeddings if enabled) | | `index_status` | Index freshness, row counts, embedding state | | `ask_vault` | Default tool for natural vault questions; uses embeddings automatically when available | | `analyze_vault` | Find candidate notes/snippets for themes, patterns, and vault-wide synthesis | | `list_notes` | Paginated list of included notes with metadata | | `search_vault` | Full-text (or semantic) search across the vault | | `read_note` | Full content of a note by path | | `get_note_metadata` | Frontmatter, tags, aliases, links for a note | | `get_note_links` | Outlinks, embeds, and backlinks for a note | | `related_notes` | Notes semantically similar to a given note (requires embeddings) | All tools return JSON text. Note content is marked untrusted so hosts do not treat it as instructions. ## Environment Variables | Variable | Default | Description | |---|---|---| | `OBSIDIAN_MCP_BRIDGE_URL` | `http://127.0.0.1:27125` | Obsidian bridge URL | | `OBSIDIAN_MCP_TOKEN` | — | Required. Bearer token from the plugin settings | | `OBSIDIAN_MCP_DB` | plugin folder `index.sqlite` | Override the SQLite cache path | | `OBSIDIAN_MCP_MAX_RESULTS` | `20` | Default result cap for list/search tools | | `OBSIDIAN_MCP_EMBEDDINGS` | `off` | Set to `on` to enable semantic search | | `OBSIDIAN_MCP_EMBEDDING_BASE_URL` | — | OpenAI-compatible endpoint, e.g. `http://127.0.0.1:1234/v1` | | `OBSIDIAN_MCP_EMBEDDING_API_KEY` | — | Optional API key for the embedding endpoint | | `OBSIDIAN_MCP_EMBEDDING_MODEL` | — | Embedding model name | ## Contributing & Release See [CONTRIBUTING.md](CONTRIBUTING.md) for branch/commit conventions, how to run checks locally, and how to cut a release. The pre-push hook (activated automatically by `npm install`) enforces naming conventions; CI re-checks them on every PR. ## License MIT