markdown-vault-mcp¶
A generic markdown collection MCP server with FTS5 full-text search, semantic vector search, frontmatter-aware indexing, incremental reindexing, and non-markdown attachment support.
Point it at a directory of Markdown files — an Obsidian vault, a docs folder, a Zettelkasten, a PARA vault — and it exposes search, read, write, and edit tools over the Model Context Protocol.
Features¶
- Full-text search — SQLite FTS5 with BM25 scoring, porter stemming
- Semantic search — cosine similarity over embedding vectors (FastEmbed, Ollama, or OpenAI)
- Hybrid search — Reciprocal Rank Fusion combining FTS5 and vector results
- Frontmatter-aware — indexes YAML frontmatter fields, supports required field enforcement
- Incremental reindexing — hash-based change detection, only re-processes modified files
- Write operations — create, edit, delete, rename documents with automatic index updates
- Attachment support — read, write, delete, and list non-markdown files (PDFs, images, etc.)
- Git integration — optional auto-commit and push on every write via
GIT_ASKPASS - OIDC authentication — optional token-based auth for HTTP deployments
- MCP tools — search, read, write, edit, delete, rename, link graph analysis, and admin operations
- MCP resources — vault configuration, statistics, tags, folders, document outlines, similar notes, and recent notes
- MCP prompts — summarize, research, discuss, create from template, compare, and find related notes
- MCP Apps — four browser-based views (Context Card, Graph Explorer, Vault Browser, Note Preview) for clients supporting the MCP Apps protocol
What you can do with it¶
A few flows the server enables with an LLM on top — none of these require a bespoke prompt:
- "Fetch
and summarize into a Resource note." Claude composesfetch+search+write. - "Research
and create a set of interlinked notes." Claude composes web tools +writewith wikilinks. See the Research workflows guide for the full loop. - "Summarize today's conversations into Inbox notes." Claude.ai composes
conversation_search+recent_chats+write; thepara-capture-chatsprompt is the one-click version. - Find missing links. The
propose-linksbuiltin prompt scans recently-modified notes and proposes meaningful connections.
See MCP Prompts for the codified workflows and the ambient-pattern reference.
Quick Start¶
As a library¶
from pathlib import Path
from markdown_vault_mcp import Collection
collection = Collection(source_dir=Path("/path/to/vault"))
results = collection.search("query text", limit=10)
As an MCP server¶
export MARKDOWN_VAULT_MCP_SOURCE_DIR=/path/to/vault
markdown-vault-mcp serve
With Docker Compose¶
cp examples/obsidian-readonly.env .env
# Edit .env to set MARKDOWN_VAULT_MCP_SOURCE_DIR
docker compose up -d
As a Claude Code plugin¶
/plugin marketplace add pvliesdonk/claude-plugins
/plugin install markdown-vault-mcp@pvliesdonk
See Installation for all installation methods (PyPI, uv, Docker, Linux packages, Claude Code plugin) and Configuration for all available options.
Architecture¶
The library is fully synchronous — no asyncio in core modules. The MCP server layer uses asyncio.to_thread() to bridge to the async FastMCP framework.
┌──────────────┐
│ MCP Server │ ← FastMCP, asyncio.to_thread()
├──────────────┤
│ Collection │ ← Thin facade / public API
├──────────────┤
│ Scanner │ ← File discovery, frontmatter parsing, chunking
│ FTS Index │ ← SQLite FTS5, BM25 scoring
│ Vector Index │ ← numpy embeddings, cosine similarity
│ Tracker │ ← Hash-based change detection
│ Providers │ ← Embedding provider ABC + implementations
│ Git │ ← Auto-commit/push strategy
├──────────────┤
│ Config │ ← Environment variable loading
└──────────────┘