obsidian-rag
Enables semantic search and retrieval over an Obsidian vault, with tools to search notes, read note contents, and monitor vault status.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@obsidian-ragfind notes about the new product launch"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Obsidian RAG Assistant
A local-first retrieval system that semantically searches an Obsidian Markdown vault from the command line or through read-only MCP tools for Claude.
Features
Recursively scans Markdown notes while ignoring
.obsidian,.git,.trash, and hidden folders.Parses headings, YAML front matter, tags, and Obsidian wiki-links.
Uses heading-aware structural chunking with an 800-character body limit and paragraph boundaries.
Generates local 384-dimensional embeddings with Ollama and
all-minilm:22m.Stores text, vectors, and source metadata in persistent local ChromaDB.
Performs dense semantic vector search with file and heading citations.
Incrementally synchronizes new, changed, and deleted notes without creating duplicates.
Exposes read-only
search_notes,read_note, andvault_statusMCP tools.
Current retrieval is dense semantic search only. BM25, hybrid search, overlap, semantic chunking, and reranking are not implemented yet.
Related MCP server: obsidian_mcp
Architecture
flowchart LR
subgraph Indexing
A[Obsidian vault] --> B[Recursive scanner]
B --> C[Markdown parser]
C --> D[Heading-aware chunks]
D --> E[Ollama MiniLM embeddings]
E --> F[(Persistent ChromaDB)]
end
subgraph Retrieval
G[Natural-language question] --> H[Query embedding]
H --> I[Vector similarity search]
F --> I
I --> J[Top-k cited passages]
end
subgraph Generation
J --> K[MCP]
K --> L[Claude]
endMCP does not perform RAG. It exposes the already-working retrieval functions to Claude, which uses the returned evidence to generate an answer.
Requirements
Quick start
git clone https://github.com/Amanaakash/Obsidian-RAG-with-Claude-mcp.git
cd Obsidian-RAG-with-Claude-mcp
uv sync --locked
ollama pull all-minilm:22mOllama normally starts with its desktop application. If it is not running, start it with ollama serve. Do not start a second server if port 11434 is already in use.
Index and search the included sample notes:
uv run obsidian-rag index --vault sample_vault
uv run obsidian-rag search "What is reciprocal rank fusion?"Every result includes its relative source path, heading hierarchy, vector distance, and retrieved text. Distance is a relative ranking signal, not a confidence percentage.
Use a real Obsidian vault
Choose a separate database directory for each vault:
uv run obsidian-rag index --vault "/absolute/path/to/ObsidianVault" --db ".rag_data/my_vault"
uv run obsidian-rag search "How do I evaluate retrieval quality?" --db ".rag_data/my_vault"Re-run index after changing the vault. Unchanged notes are skipped, changed notes are replaced, new notes are added, and deleted notes are removed from the index.
Changing the embedding model changes the vector dimensions and semantic space. Use a new database directory or rebuild the existing generated index after switching models.
Claude through MCP
The MCP server reads configuration exclusively from environment variables:
Variable | Required | Default | Purpose |
| Yes | — | Absolute path to the Obsidian vault |
| Yes | — | Absolute path to the persistent Chroma directory |
| No |
| Ollama embedding model |
| No |
| Chroma collection name |
| No |
| Ollama server address |
Claude Desktop
Merge an obsidian-rag entry into Claude Desktop's MCP configuration. Keep any existing server entries.
{
"mcpServers": {
"obsidian-rag": {
"command": "uv",
"args": [
"--directory",
"/absolute/path/to/Obsidian-RAG-with-Claude-mcp",
"run",
"obsidian-rag-mcp"
],
"env": {
"OBSIDIAN_RAG_VAULT": "/absolute/path/to/ObsidianVault",
"OBSIDIAN_RAG_DB": "/absolute/path/to/Obsidian-RAG-with-Claude-mcp/.rag_data/my_vault",
"OBSIDIAN_RAG_MODEL": "all-minilm:22m",
"OBSIDIAN_RAG_COLLECTION": "obsidian_notes"
}
}
}
}On Windows, Claude Desktop stores this file at %APPDATA%\Claude\claude_desktop_config.json. Completely quit and reopen Claude Desktop after changing it.
Claude Code
Register the same stdio server in user scope:
claude mcp add --scope user obsidian-rag -e "OBSIDIAN_RAG_VAULT=/absolute/path/to/ObsidianVault" -e "OBSIDIAN_RAG_DB=/absolute/path/to/Obsidian-RAG-with-Claude-mcp/.rag_data/my_vault" -e "OBSIDIAN_RAG_MODEL=all-minilm:22m" -e "OBSIDIAN_RAG_COLLECTION=obsidian_notes" -- uv --directory /absolute/path/to/Obsidian-RAG-with-Claude-mcp run obsidian-rag-mcpEach MCP process starts a non-blocking incremental refresh. A cross-process file lock prevents Claude Desktop and Claude Code from writing to Chroma at the same time.
Privacy and safety
Vault scanning, embeddings, and Chroma storage run locally.
The MCP server is read-only and cannot create, edit, or delete notes.
read_noterejects absolute paths, traversal, hidden directories, non-Markdown files, and symlink escapes.Passages returned by
search_notesorread_noteare sent to Claude when Claude invokes those tools.Do not commit
.env,.mcp.json, real vault notes, or.rag_dataindexes.Review third-party MCP server permissions before granting access to a private vault.
Limitations
Dense semantic retrieval only; no BM25, hybrid fusion, or reranker.
Chunk limits are character-based rather than tokenizer-based.
No chunk overlap is currently used.
Heading-aware structural chunking is not LLM-based semantic chunking.
Tags and links are stored as metadata but do not affect ranking.
Only Markdown is indexed; PDFs, images, Canvas files, and attachments are ignored.
Retrieval distance is not a calibrated relevance or correctness probability.
Development
uv sync --locked --all-groups
uv run pytest -q
uv build
uv run obsidian-rag --helpAutomated tests use fake embedders and do not require Ollama, Claude, or a real vault. See CONTRIBUTING.md before opening a pull request.
Security and license
Report security issues privately as described in SECURITY.md. This project is available under the MIT License.
Available Tools
3 toolsread_noteA
Read one Markdown note or an exact heading using a safe relative path.
| Name | Required | Description | Default |
|---|---|---|---|
| source | Yes | ||
| heading | No | ||
| max_chars | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the burden of behavioral disclosure. It adds useful constraints: the path is 'safe' and 'relative', and the heading must be 'exact'. However, it does not explain max_chars truncation behavior or error handling when a note or heading is missing.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, front-loaded sentence with no filler. Every phrase adds information: read action, Markdown notes, exact heading support, and the safe relative path constraint.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The definition is adequate for a simple read tool and an output schema is present, so return values need not be described. However, it lacks explicit guidance on when to use read_note versus search_notes and leaves max_chars behavior unstated, creating minor but real gaps.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate. It adds meaning for source ('relative path') and heading ('exact heading'), which the raw schema does not provide. It does not describe max_chars, though the parameter name and default hint at character limiting.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb 'Read' with a clear resource ('one Markdown note') and scope ('using a safe relative path' / 'exact heading'). It distinguishes itself from siblings: read_note is for direct content access by path, search_notes is for discovery, and vault_status is for vault-level information.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description clearly implies this tool should be used when the agent already knows the note path and wants to read its content or a specific heading. It does not explicitly name sibling alternatives or state when not to use it, so it falls just short of a full 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_notesB
Semantically search indexed Obsidian notes and return cited passages.
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | ||
| top_k | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the burden of behavioral disclosure. It adds useful traits: 'semantically' indicates non-keyword matching, 'indexed' signals a prerequisite, and 'cited passages' suggests the response shape. However, it does not explicitly state read-only behavior, failure modes, or dependence on the index freshness.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, front-loaded sentence with no wasted words. It delivers the core action, resource, and result in a compact, readable form.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple two-parameter tool with an output schema, the description conveys the core function but misses important context: no usage differentiation from siblings, no parameter semantics, and no safety/side-effect disclosure. It is minimally adequate but leaves gaps for an agent to navigate reliably.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description must compensate for undocumented parameters. It does not explain the format or scope of 'query' beyond implying semantic search, nor does it describe how 'top_k' affects results or any bounds. The parameter names are self-evident but the description adds little meaning beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('search'), a clear resource ('indexed Obsidian notes'), and the output ('cited passages'). It clearly differentiates itself from siblings read_note and vault_status by its search and retrieval focus.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives no guidance on when to use this tool versus read_note or vault_status. It does not mention conditions, exclusions, or alternatives, leaving the agent to infer when a semantic search is appropriate.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
vault_statusA
Check local index availability, chunk count, and refresh state.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden. 'Check' strongly implies a read-only operation, and listing the three status aspects adds useful transparency. However, it does not explicitly state that no side effects occur, and 'refresh state' is slightly ambiguous—it could mean the status of a refresh rather than triggering a refresh.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single, compact sentence leads with the verb and lists the key status dimensions without filler. Every word earns its place, and the structure is easy to parse quickly.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
This is a simple zero-parameter status tool with an output schema available to describe return values. The description sufficiently captures the purpose and key aspects for an agent to select and invoke the tool correctly; no additional context is needed.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters, so the description has nothing to add about parameter meaning. Per the baseline for zero-parameter tools, a score of 4 is appropriate because no parameter documentation burden exists.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('Check') and identifies the exact resource and aspects it covers: local index availability, chunk count, and refresh state. It is clearly distinguishable from siblings search_notes and read_note, which are search/read operations rather than status checks.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no explicit guidance on when to use this tool versus the sibling tools, nor any mention of when a status check is appropriate. The context implies a health-check use case, but the description itself provides no direct usage guidance or exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
3 tool updates
v0.2.0- First observed
read_note - First observed
search_notes - First observed
vault_status
TDQS
Scored across 3 tools
Each tool targets a distinct operation: semantic search, direct note reading, and vault/index status. There is no overlap or ambiguity between them.
search_notes and read_note follow a clear verb_noun pattern, but vault_status is a noun phrase rather than get_vault_status or check_vault_status. This is a minor deviation from an otherwise consistent snake_case convention.
Three tools is appropriate for a focused RAG server covering search, retrieval, and system status. No tool feels redundant or missing enough to bloat the surface.
The core read/search/status workflow is well covered for a read-only Obsidian RAG server. A possible minor gap is the lack of an explicit refresh/reindex action, though the status tool reports refresh state.
Maintenance
Related MCP Connectors
Search and reason over your Obsidian-style Markdown vault, right from ChatGPT.
Search your Obsidian vault to quickly find notes by title or keyword, summarize related content, a…
Search your Glasp web and Kindle highlights, notes, and AI memories from any MCP client. Read-only.
Search, read, and safely update Markdown notes in your connected Phasoric knowledge vaults.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceProvides Claude with read, search, and write access to an Obsidian vault through MCP tools.5,145 npmApache 2.0
- FlicenseNot gradedqualityCmaintenanceEnables reading, writing, searching, and managing Obsidian vault notes through MCP tools and prompts, allowing AI agents to interact with local knowledge bases.-
- AlicenseNot gradedqualityDmaintenanceEnables Claude to read, write, search, and manage an Obsidian vault with tools for notes, tags, folders, and full-text search.6 npmMIT
- AlicenseNot gradedqualityAmaintenanceEnables Claude to read, search, and analyze your entire knowledge vault locally via MCP tools like search, drafting, and linting.103 npm4MIT