vault-mcp
Turn any folder into a searchable knowledge base for AI, exposed via MCP.
README
vault-mcp
Turn any folder into a searchable knowledge base for AI, exposed via MCP.
Point it at a directory. It embeds everything — markdown, PDFs, images, audio, video. Search it from Claude Desktop, Claude Code, or any MCP client.
Why this exists
Existing RAG tools either want to be the source of truth (duplicating your files into their own store) or only handle markdown. vault-mcp treats your folder as the single source of truth. The embedding index is derived state — delete it and rebuild from scratch in seconds. Git handles versioning. Your AI assistant modifies files directly. vault-mcp just makes them searchable.
Built for personal knowledge vaults, project documentation, research archives — anywhere you have a folder of mixed-format files and want semantic search over all of it.
Features
- Multi-format extraction — Markdown, PDF, DOCX, PPTX, images (OCR), audio/video (Whisper transcription)
- Heading-aware markdown chunking — Splits by headings, preserves breadcrumb context (
# Strategy > ## Vision > ### North Star), merges small sections, splits large ones - Chunk-level deduplication — Only re-embeds chunks that actually changed. Edit one paragraph in a 40KB doc? One API call, not 80
- File rename detection — Moved a file? Zero re-embedding. Matched by content hash
- 3-tier skip hierarchy — mtime unchanged → skip entirely. Content unchanged → skip extraction. Chunk unchanged → skip embedding
- Live watching — Watchdog-based file monitor with 2s debounce. Changes appear in search within seconds
- Remote MCP transport — Streamable HTTP (default), SSE, or stdio. Connect from anywhere
- SQLite + sqlite-vec — Single-file database, no external services. ~50MB RAM footprint
Quickstart
pip install vault-mcp
Set your OpenAI API key (used for text-embedding-3-small embeddings):
export OPENAI_API_KEY=sk-...
Index a folder and start the server:
export VAULT_PATH=/path/to/your/folder
# First-time index
vault-mcp reindex
# Start MCP server (streamable-http on port 8100)
vault-mcp serve --watch
Connect from Claude Desktop
Add to claude_desktop_config.json:
{
"mcpServers": {
"vault": {
"url": "http://localhost:8100/mcp"
}
}
}
For a remote server with authentication (see Remote Deployment):
{
"mcpServers": {
"vault": {
"type": "http",
"url": "https://your-server/mcp",
"headers": {
"Authorization": "Bearer YOUR_TOKEN"
}
}
}
}
Connect from Claude Code
Add to .mcp.json or settings:
{
"mcpServers": {
"vault": {
"url": "http://your-server:8100/mcp"
}
}
}
Connect via stdio (local only)
{
"mcpServers": {
"vault": {
"command": "vault-mcp",
"args": ["serve", "--transport", "stdio", "--watch"],
"env": {
"VAULT_PATH": "/path/to/your/folder",
"OPENAI_API_KEY": "sk-..."
}
}
}
}
MCP Tools
| Tool | Purpose |
|---|---|
search |
Semantic search over the vault |
reindex |
Re-embed changed files |
stats |
Index statistics |
write |
Write a file and optionally git commit |
Webhooks
vault-mcp can receive webhooks from external services and write captures directly to the vault.
| Endpoint | Method | Description |
|---|---|---|
/webhook/voicenotes |
POST | Receive VoiceNotes transcriptions |
VoiceNotes webhook
Handles recording.created, recording.updated, and recording.deleted events. Writes transcriptions to captures/inbox/YYYY/MM/YYYY-MM-DD-{slug}.md with frontmatter. The file watcher auto-indexes new files within seconds.
Auth: Set WEBHOOK_SECRET env var. Pass as query param: /webhook/voicenotes?secret=xxx (VoiceNotes doesn't support custom headers). If WEBHOOK_SECRET is unset, all requests are accepted.
Example:
curl -X POST 'http://localhost:8100/webhook/voicenotes?secret=xxx' \
-H 'Content-Type: application/json' \
-d '{"event":"recording.created","timestamp":"2026-03-01T10:00:00Z","data":{"id":"abc-123","title":"Morning thoughts","transcript":"Need to ship the onboarding flow this week."}}'
search(query, top_k?, path_filter?)
Semantic search over your vault.
query: "north star vision"
top_k: 5
path_filter: "strategy/" # optional — scope to subdirectory
Returns matching chunks with text, file path, heading breadcrumb, and relevance score.
reindex(path?)
Re-embed changed files. Without a path, indexes the full vault (skipping unchanged files). With a path, force-reindexes that file or directory.
stats()
Returns indexed file count, chunk count, last index time, vault path, and embedding model.
write(path, content, commit_message?)
Write a file to the vault and optionally git commit. The caller handles classification and frontmatter — vault-mcp just writes bytes and commits.
path: "captures/saturn/2026/03/ai-architecture-insight.md"
content: "---\nplanet: saturn\nsource: slack\n---\n\nBreakthrough on embedding context..."
commit_message: "capture(saturn): AI architecture insight from Slack" # optional
Returns { status, path, relative_path, committed?, commit_hash? }. Path traversal outside the vault is rejected. No git push — that's handled separately.
CLI
# Index the vault (only changed files)
vault-mcp reindex
# Force re-embed everything
vault-mcp reindex --force
# Index a specific subdirectory
vault-mcp reindex captures/
# Start MCP server
vault-mcp serve # streamable-http on 0.0.0.0:8100
vault-mcp serve --transport stdio # stdio for local MCP
vault-mcp serve --port 9000 # custom port
vault-mcp serve --watch # watch for file changes
# Check index stats
vault-mcp stats
How it works
Your Folder (git-backed)
│
├── .md, .pdf, .docx, .png, .mp4, ...
│
▼
Extractor
│ Markdown → passthrough
│ PDF/DOCX → Kreuzberg
│ Images → Kreuzberg OCR (Tesseract)
│ Audio/Video → OpenAI Whisper
│
▼
Chunker
│ Markdown → heading-aware splitting (512 token chunks)
│ Everything else → paragraph grouping
│ Overlap: last 1-2 sentences between chunks
│
▼
Embedder
│ OpenAI text-embedding-3-small (1536 dims)
│ Batched, with retry/backoff
│ Chunk-level dedup via SHA-256 hash
│
▼
SQLite + sqlite-vec
│ chunks: text, embedding, file_path, heading_path
│ files: path, mtime, content_hash
│
▼
MCP Server (FastMCP)
search / reindex / stats
Remote Deployment
vault-mcp has no built-in authentication. For remote access, run it behind nginx with bearer token auth:
- Bind to localhost only and use streamable-http transport (the default):
vault-mcp serve --watch --host 127.0.0.1 --port 8100
- Add nginx reverse proxy with bearer token validation:
server {
listen 443 ssl;
server_name vault-mcp.example.com;
# SSL certs (e.g. Let's Encrypt)
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
location / {
if ($http_authorization != "Bearer YOUR_SECRET_TOKEN") {
return 401 "Unauthorized";
}
proxy_pass http://127.0.0.1:8100;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
}
}
- Optional: systemd user service for auto-restart:
# ~/.config/systemd/user/vault-mcp.service
[Unit]
Description=vault-mcp
After=network.target
[Service]
Type=simple
WorkingDirectory=/path/to/vault-mcp
Environment=OPENAI_API_KEY=sk-...
Environment=VAULT_PATH=/path/to/your/vault
ExecStart=/path/to/vault-mcp serve --watch --host 127.0.0.1 --port 8100
Restart=on-failure
[Install]
WantedBy=default.target
systemctl --user enable --now vault-mcp
Configuration
| Environment Variable | Default | Description |
|---|---|---|
OPENAI_API_KEY |
(required) | OpenAI API key for embeddings |
VAULT_PATH |
. (current dir) |
Path to the folder to index |
VAULT_DB_PATH |
~/.vault-mcp/index.db |
SQLite database location |
WEBHOOK_SECRET |
(optional) | Shared secret for webhook auth (query param) |
Supported Formats
| Format | Method | Notes |
|---|---|---|
.md, .txt, .yaml, .json, .toml |
Direct read | Markdown gets heading-aware chunking |
.pdf, .docx, .pptx, .xlsx, .odt, .rtf, .epub, .html |
Kreuzberg | Async extraction |
.png, .jpg, .gif, .bmp, .tiff, .webp |
Kreuzberg OCR | Tesseract backend |
.mp3, .mp4, .m4a, .wav, .ogg, .flac, .webm, .avi, .mkv, .mov |
OpenAI Whisper | Time-windowed chunks |
Dependencies
- FastMCP — MCP server framework
- Kreuzberg — Document/image text extraction
- OpenAI — Embeddings + Whisper transcription
- sqlite-vec — Vector search in SQLite
- watchdog — Filesystem monitoring
- tiktoken — Token counting
License
MIT
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。