vault-rag-mcp
Uses Google Gemini embeddings for vectorizing query and document text.
Semantic search across an Obsidian vault, including glossary lookup and note retrieval.
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., "@vault-rag-mcpSearch my vault for notes on react hooks"
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.
vault-rag-mcp
MCP server for semantic search in an Obsidian Second Brain vault, using a self-hosted Qdrant vector store and Google Gemini embeddings.
Architecture
Claude Code <-> vault-rag MCP server (stdio)
|-> Google Gemini gemini-embedding-001 (native 3072d)
|-> Qdrant `vault_chunks` collection (3072d, Cosine distance)Part of a hybrid RAG architecture:
Indexation: n8n (remote) + Google Gemini API
Local queries: This MCP server + Google Gemini API
Web chat: n8n Vault Chat (AI Agent + Gemini native) or Chat Hub (HTTP pipeline)
Bulk index: Script using Gemini
gemini-embedding-001
Same model (gemini-embedding-001, native 3072d) everywhere ensures vector compatibility.
Vectors are stored at native 3072 dimensions (float32) with Cosine distance.
Asymmetric task types: RETRIEVAL_DOCUMENT for indexing, RETRIEVAL_QUERY for search.
Related MCP server: mcp-obsidian-local
Tools
Tool | Description |
| Semantic search across the entire vault (query, limit, para_folder, note_type) |
| Search within glossary definitions (3_Resources/definitions/) |
| Retrieve full content of a note by file path |
Prerequisites
Python >= 3.11
uv package manager
Google API key (for Gemini embeddings)
Qdrant instance with a
vault_chunkscollection (created automatically on first index)
Setup
# Clone and install
cd ~/Projects/vault-rag-mcp
uv sync
# Configure environment
cp .env.example .env
# Edit .env with your Google API key and Qdrant credentialsEnvironment variables
Variable | Description | Default |
| Qdrant instance URL (HTTPS requires the | (required) |
| Qdrant API key | (required) |
| Google AI API key | (required) |
| Gemini embedding model |
|
Usage
As MCP server (Claude Code)
Add to your project's .mcp.json:
{
"mcpServers": {
"vault-rag": {
"command": "uv",
"args": ["run", "--directory", "/path/to/vault-rag-mcp", "vault-rag-mcp"],
"env": {
"QDRANT_URL": "https://your-qdrant-instance.example.com",
"QDRANT_API_KEY": "your-qdrant-api-key",
"GOOGLE_API_KEY": "your-google-api-key",
"EMBEDDING_MODEL": "gemini-embedding-001"
}
}
}
}Restart Claude Code to activate. Then use the tools directly in conversation.
Bulk indexation
Script to index an entire Obsidian vault via Google Gemini:
uv run python scripts/bulk_index.py /path/to/vault [--force]Options:
--force: Re-index all files, ignoring file_hash cache
The script:
Walks the vault, skips
.obsidian/,templates/,.trash/, files > 500 KBParses YAML frontmatter (type, tags, PARA folder)
Chunks by H2 sections, splits oversized chunks (> 2000 chars)
Embeds via Google Gemini in batches of 50 (task_type=RETRIEVAL_DOCUMENT)
Upserts to Qdrant with a SHA256 file_hash payload for incremental re-runs
After initial bulk indexation, incremental updates are handled by n8n via Gemini API.
Project structure
vault-rag-mcp/
├── pyproject.toml # uv + hatch build config
├── .env.example # Environment template
├── src/
│ └── vault_rag_mcp/
│ ├── __init__.py
│ ├── server.py # MCP server (FastMCP, stdio) — 3 tools
│ ├── embeddings.py # Google Gemini embedding client (native 3072d)
│ └── qdrant_store.py # Qdrant client + collection operations
├── scripts/
│ └── bulk_index.py # Bulk indexation via Google Gemini
└── n8n-workflows/ # n8n workflow definitions
├── vault-rag-github-indexation.json
└── vault-rag-chat-hub.jsonQdrant collection
Collection vault_chunks — vectors at 3072 dimensions, Cosine distance. Each point carries:
content— chunk textfile_path— relative path from vault rootchunk_index— position within filepara_folder— PARA folder (1_Projects, 2_Areas, etc.)note_type— frontmatter type (memo, glossary, howto, etc.)file_hash— SHA256 for change detectionmetadata— tags, type, para_folder
Point IDs are deterministic UUID5 values derived from file_path::chunk_index.
Payload indexes: file_path (keyword), para_folder (keyword), note_type (keyword), chunk_index (integer).
Tech stack
MCP SDK:
mcp[cli]withFastMCP(stdio transport)Embeddings: Google Gemini
gemini-embedding-001via thegoogle-genaiSDK (native 3072d, multilingual, 2048 token/text)Vector DB: Qdrant (self-hosted) —
vault_chunkscollection, 3072d Cosine distanceBuild: uv + hatch
Available Tools
3 toolsget_noteA
Retrieve the full content of a specific note by its file path.
Args: file_path: Path relative to vault root (e.g. '3_Resources/definitions/p/powerflex.md')
| Name | Required | Description | Default |
|---|---|---|---|
| file_path | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations provided, so description carries full burden. It states retrieval of content, implying read-only. Missing details on error behavior if file doesn't exist, but for a simple read operation, this is acceptable.
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?
Two sentences: first states purpose, second explains the single parameter. No filler, front-loaded with the main action.
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?
With an output schema present, return values are covered. The description addresses the core functionality and parameter. Minor omission is handling of invalid paths, but overall complete for the tool's simplicity.
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%, but description explains file_path as 'Path relative to vault root' with an example, adding meaning beyond the bare type declaration.
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 clearly states the tool retrieves full content of a specific note by file path. It distinguishes itself from sibling tools like search_glossary and search_vault by focusing on retrieval of a known note.
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?
Usage context is implied: use when you have a file path. No explicit guidance on when not to use or alternatives, but the sibling tools are different enough that the purpose alone suggests appropriate usage.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_glossaryB
Search the glossary (1878 term definitions in 3_Resources/definitions/).
Args: query: Term or concept to look up (works in French and English) limit: Maximum number of results (default 5)
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| query | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries full burden. It mentions the resource location and bilingual functionality but does not disclose behavioral traits like idempotency, side effects, or access requirements. A search tool is likely read-only, but this is not explicitly stated.
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 extremely concise, front-loading the purpose in one sentence, then briefly documenting parameters. Every sentence adds value with no redundancy.
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?
Given the tool's simplicity (2 params, output schema present), the description provides essential context: purpose, resource location, language support, and parameters. It could mention return type or read-only nature, but is largely complete for a search tool.
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%, requiring the description to add meaning. It effectively explains both parameters: 'query' as a term/concept in French/English, and 'limit' as max results with default 5. This compensates for the lack of schema descriptions.
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 clearly states the tool searches a glossary with 1878 term definitions, using a specific verb and resource. It does not explicitly distinguish from sibling tools like search_vault, but the context implies a focused glossary search, making it sufficiently clear.
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?
No guidance is provided on when to use this tool versus alternatives (e.g., search_vault) or when not to use it. The description only states what it does, leaving usage decisions to the agent without explicit context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_vaultA
Search the vault semantically. Returns the most relevant notes.
Args: query: Natural language search query (works in French and English) limit: Maximum number of results (default 10) para_folder: Filter by PARA folder (1_Projects, 2_Areas, 3_Resources, 4_Archives) note_type: Filter by note type (memo, glossary, howto, meeting-note, etc.)
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| query | Yes | ||
| note_type | No | ||
| para_folder | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations provided, so description carries full burden. Describes semantic search and language support (French/English) but does not disclose read-only nature, auth needs, rate limits, or error behavior. Adequate but could be more transparent.
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?
First sentence clearly states purpose, followed by bullet-point parameter details. No redundancy, though the examples in parameter descriptions add length. Efficient overall.
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?
Output schema exists, so return values are covered. Description explains all four parameters and their filtering roles. Lacks mention of edge cases or errors, but is sufficient for a search tool with moderate complexity.
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?
With 0% schema description coverage, the description adds critical meaning: explains 'query' as natural language, 'limit' includes default, 'para_folder' lists possible values, 'note_type' gives examples. This goes far beyond the schema titles and types.
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?
Description clearly states the action ('Search the vault semantically') and outcome ('Returns the most relevant notes'). It distinguishes from siblings 'get_note' and 'search_glossary' by specifying semantic search over the vault vs. specific note retrieval or glossary search.
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?
Implies usage for natural language queries, but does not explicitly state when to use this tool over siblings or when not to use it. No alternatives or exclusions are mentioned.
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.1.0- First observed
get_note - First observed
search_glossary - First observed
search_vault
TDQS
Scored across 3 tools
Each tool has a clearly distinct purpose: retrieving a specific note by path, searching the glossary, and performing semantic search across the vault. No overlap in functionality.
All tool names follow the consistent verb_noun pattern with snake_case: 'get_note', 'search_glossary', 'search_vault'. No deviations.
With 3 tools, the set is on the lower end but appropriate for a read-only RAG server. It covers the essential retrieval operations without being too sparse.
The tool set covers all core retrieval needs (exact note lookup, glossary search, semantic vault search). Minor gaps exist, such as listing available folders or note types, but filters in search_vault mitigate this.
Maintenance
Related MCP Connectors
Personal knowledge base MCP server with semantic search, auto-categorization, metadata extraction
Serve a folder of Markdown notes as an MCP server: hybrid search, reading, and sourced answers.
Markdown-based note-taking with a hosted MCP server. Your notes serve you and your AI.
Related MCP Servers
- AlicenseNot gradedqualityAmaintenanceMCP server that indexes Obsidian notes and enables hybrid search (full-text, fuzzy, semantic) for AI assistants to find and read notes.936 npm102MIT
- FlicenseNot gradedqualityNot gradedmaintenanceLocal MCP server to access Obsidian vault via the obsidian-local-rest-api, with semantic search and project memory using Ollama embeddings.-
- AlicenseNot gradedqualityBmaintenanceSelf-hosted MCP server that provides embedding-powered semantic search with graph context over Obsidian vaults, supporting multiple vaults, local embeddings, and a web dashboard.MIT
- AlicenseNot gradedqualityDmaintenanceA read-only MCP server that enables semantic search of your Obsidian vault using Smart Connections embeddings, with path validation and security.53 npm3MIT