Give Claude Code persistent memory with a Markdown vault.
An MCP server that turns any folder of Markdown files into a searchable, structured knowledge base. Claude Code can list, read, write, edit, search, and summarize your vault — across sessions, across machines.
- 7 tools exposed via MCP:
vault_list,vault_read,vault_write,vault_edit,vault_summary,vault_search,vault_reindex - Semantic search powered by ChromaDB + sentence-transformers — ask questions in natural language, get relevant chunks back instead of full files
- Metadata parsing — extracts status, dates, and custom fields from
**Key:** Valuepatterns in your Markdown - Multilingual — search and metadata work in English and Spanish out of the box
- Incremental indexing — only re-embeds files that changed since last startup
Markdown is the only format that is simultaneously human-readable, version-controllable, and LLM-friendly. No database to manage, no migration scripts. Your vault is just files — back them up with git, sync them with Nextcloud, edit them in Obsidian.
┌─────────────────────┐ ┌──────────────────────┐
│ Claude Code │────>│ vault-mcp-server │
│ (any machine) │<────│ (FastMCP + HTTP) │
└─────────────────────┘ └──────┬───────────────┘
│
┌────────▼────────┐
│ Markdown Vault │
│ (any folder) │
└────────┬────────┘
│
┌────────▼────────┐
│ ChromaDB │
│ (semantic index)│
└─────────────────┘
git clone https://github.com/thebackpackdevorg/vault-mcp-server.git
cd vault-mcp-serverEdit docker-compose.yml to point to your Markdown folder:
volumes:
- /path/to/your/markdown-vault:/vaultdocker compose up -dThe server starts on port 8091 with Streamable HTTP transport.
claude mcp add vault http://localhost:8091/mcp -t httpOr add to ~/.claude/settings.json:
{
"mcpServers": {
"vault": {
"type": "http",
"url": "http://localhost:8091/mcp"
}
}
}You: "What do I have documented about Docker networking?"
Claude: *calls vault_search("Docker networking")* → returns relevant chunks
You: "Update the status in homeserver-backlog.md to Done"
Claude: *calls vault_edit("homeserver/homeserver-backlog.md", "**Status:** Active", "**Status:** Done")*
To access the vault from other machines, expose it through a reverse proxy. The server supports an optional OAuth layer for authentication when deployed remotely.
- Create a Cloudflare Tunnel pointing to
localhost:8091 - Add a Cloudflare Access policy with a Service Token
- Configure Claude Code on remote machines:
{
"mcpServers": {
"vault": {
"type": "http",
"url": "https://vault.yourdomain.com/mcp",
"headers": {
"CF-Access-Client-Id": "${VAULT_CF_CLIENT_ID}",
"CF-Access-Client-Secret": "${VAULT_CF_CLIENT_SECRET}"
}
}
}
}Set OAUTH_ISSUER_URL and optionally OAUTH_PIN in your environment to enable the built-in OAuth 2.1 provider with a PIN-based approval page.
If you're deploying behind Cloudflare (or any proxy that buffers SSE), you may hit a silent failure where Claude Code connects but never gets responses.
The fix: This server uses Streamable HTTP (not SSE). Make sure your proxy passes through the Accept: application/json, text/event-stream header correctly. The server includes a middleware that injects this header if missing.
| Tool | Description |
|---|---|
vault_list |
List files with optional domain/status filters |
vault_read |
Read a file with parsed metadata, sections, and cross-references |
vault_write |
Create or overwrite a file |
vault_edit |
String replacement edit (like Claude's Edit tool) |
vault_summary |
Dashboard: file counts by domain, active projects, recent changes |
vault_search |
Semantic search — returns relevant chunks, not full files |
vault_reindex |
Force full re-index after external changes |
vault:
path: "/vault"
server:
host: "0.0.0.0"
port: 8080
search:
chroma_path: "/app/chroma_data"
model: "paraphrase-multilingual-MiniLM-L12-v2"| Variable | Default | Description |
|---|---|---|
VAULT_PATH |
/vault |
Path to your Markdown vault inside the container |
SERVER_HOST |
0.0.0.0 |
Bind address |
SERVER_PORT |
8080 |
Internal port |
CHROMA_PATH |
/app/chroma_data |
ChromaDB storage path |
EMBEDDING_MODEL |
paraphrase-multilingual-MiniLM-L12-v2 |
Sentence-transformers model |
OAUTH_ISSUER_URL |
(empty) | Set to enable OAuth (e.g. https://vault.yourdomain.com) |
OAUTH_PIN |
(empty) | Optional PIN for the OAuth approval page |
The server parses **Key:** Value patterns in the first 15 lines of each file:
# My Project
**Status:** Active
**Created:** 2026-01-15
**Last Updated:** 2026-03-01Recognized status values: Active, Pending, Paused, Done (and Spanish equivalents).
- Python 3.12 + FastMCP
- ChromaDB for vector storage
- sentence-transformers (
paraphrase-multilingual-MiniLM-L12-v2) for embeddings - Docker +
uvfor fast builds
MIT