Give any local Markdown folder a semantic-search MCP server. Runs entirely offline.
Turn ~/Desktop/sales/, ~/Desktop/notes/, or any directory full of Markdown files into a searchable knowledge base that Claude Code, Cursor, Cline, and other MCP clients can query with natural-language questions.
- π Multi-vault: one MCP server manages many doc folders, each a separate "vault"
- π Fully local: no API keys, no cloud β embeddings run on your machine
- β‘ Incremental indexing: only re-embed files that changed
- π§ Any embedding model: default is Chinese-optimized
bge-small-zh-v1.5; English / multilingual models work too - π¦ Self-contained: each vault's vector DB lives inside the folder (
.mdrag/), move it anywhere
pip install mdragRequires Python β₯ 3.10.
Let's say Bob has a folder ~/Desktop/sales/ full of meeting notes, proposals, and competitor research in Markdown.
claude mcp add mdrag --scope user -- mdrag serveThis tells Claude Code "there's an MCP server called mdrag β launch it with mdrag serve when needed". You'll only do this once per machine.
mdrag vault add sales ~/Desktop/salesThe first time you run this, a ~100MB embedding model downloads (once), then all .md files under ~/Desktop/sales/ get indexed. A .mdrag/ subfolder is created inside sales/ to hold the vector database.
Open Claude Code in any project. Ask:
"Use the mdrag MCP to search my sales vault for the Q4 pipeline review"
Claude will call mcp__mdrag__search(vault="sales", query="Q4 pipeline review") and return the top matching documents.
No new MCP config needed β just register another vault:
mdrag vault add marketing ~/Desktop/marketing
mdrag vault add notes ~/Documents/notesAll vaults are visible through the same MCP server. Claude calls:
mcp__mdrag__list_vaults() β see all vaults
mcp__mdrag__search(vault="marketing", query="...")
mcp__mdrag__search(vault="notes", query="...")
mdrag serve Start the MCP stdio server
mdrag vault add NAME PATH Register a directory and index it
mdrag vault list Show all vaults
mdrag vault info NAME Show vault details
mdrag vault reindex NAME [--full] Re-index (incremental or full)
mdrag vault remove NAME [--purge] Unregister (and optionally delete .mdrag/)
Common options:
--model MODEL_NAMEonvault addβ pick a different embedding model--no-indexonvault addβ skip initial indexing (useful when first adding, want to index later)--fullonvault reindexβ rebuild from scratch (required after changing the model)
When mdrag serve is running, these tools are available to the AI client:
| Tool | Purpose |
|---|---|
list_vaults() |
List all registered vaults with their stats |
search(vault, query, top_k=5, tags="") |
Semantic search within a vault, optional tag filter |
get_doc(vault, path) |
Read the full content of a document |
list_tags(vault) |
List all frontmatter tags in a vault with counts |
If your Markdown files have YAML frontmatter, mdrag will use it:
---
title: Q4 Pipeline Review
tags: [sales, forecast, 2026-q4]
summary: Overview of deals in play for Q4 2026.
---
# Q4 Pipeline Review
...titleβ used as the result title (falls back to filename)tagsβ searchable via thetagsparameter ofsearchsummaryβ shown in search results
No frontmatter? It still works β mdrag auto-generates a preview from the file body.
| Language | Recommended model | Notes |
|---|---|---|
| Chinese | BAAI/bge-small-zh-v1.5 (default) |
~100MB, CPU-friendly |
| English | BAAI/bge-small-en-v1.5 |
Same family, English |
| Multilingual | paraphrase-multilingual-MiniLM-L12-v2 |
For mixed-language vaults |
| Higher accuracy | BAAI/bge-base-zh-v1.5 or -en |
~400MB, noticeably slower |
Change the model when registering a vault:
mdrag vault add notes ~/Documents/notes --model BAAI/bge-small-en-v1.5After changing the model on an existing vault (edit ~/.mdrag/vaults.yaml), run a full rebuild:
mdrag vault reindex notes --full ββββββββββββββββββββββ ββββββββββββββββββββββββ
β ~/Desktop/sales/ β β ~/.mdrag/ β
β meeting-01.md β β vaults.yaml β β registry
β proposal.md β ββββββββββββββββββββββββ
β .mdrag/ β β LanceDB vector store (per-vault)
β docs.lance/ β
ββββββββββββ¬ββββββββββ
β
β mdrag serve
βΌ
ββββββββββββββββββββββββββββ
β FastMCP stdio server β
β tools: β
β search / get_doc / β
β list_vaults / β
β list_tags β
ββββββββββββ¬ββββββββββββββββ
β MCP protocol (stdio / JSON-RPC)
βΌ
Claude Code / Cursor / Cline
- Vault registry is at
~/.mdrag/vaults.yaml - Each vault's vector database lives inside the vault directory at
.mdrag/β self-contained, portable - Embeddings use
sentence-transformers, stored in LanceDB - MCP server is built on FastMCP
mdrag vault reindex salesIt's incremental β only files with changed mtime are re-embedded.
Yes. Add to cron (Linux/macOS):
0 * * * * /path/to/mdrag vault reindex sales
Or use launchd on macOS / Task Scheduler on Windows.
Not yet. Convert to Markdown first (e.g. with pandoc) and point mdrag at the result.
If you're in China, set a HuggingFace mirror:
export HF_ENDPOINT=https://hf-mirror.com
mdrag vault add sales ~/Desktop/sales- Vault registry:
~/.mdrag/vaults.yaml - Each vault's vectors:
<vault_path>/.mdrag/docs.lance/
Yes β the .mdrag/ folder is self-contained. Sync the whole vault directory (via Dropbox, rsync, git-lfs, whatever) and mdrag vault add <name> <path> on the other machine. No re-indexing needed as long as the embedding model matches.
claude mcp add mdrag --scope user -- mdrag serveOr manually in ~/.mcp.json:
{
"mcpServers": {
"mdrag": {
"command": "mdrag",
"args": ["serve"]
}
}
}Add the same stdio command to your client's MCP configuration. The command is mdrag serve β it communicates over stdio following the MCP protocol.
git clone https://github.com/andyleimc-source/mdrag
cd mdrag
python -m venv .venv
.venv/bin/pip install -e .[dev]
.venv/bin/pytestTry the example vault shipped in the repo:
mdrag vault add demo ./examples/sample-vault
mdrag vault listMIT β do whatever you want with it.