vault-mcp
# vault-mcp
Markdown + SQLite knowledge store with bidirectional `[[wikilinks]]`, exposed as an MCP server. Designed for AI agents to maintain an interconnected knowledge base.
## Installation
```bash
uvx vault-mcp # run directly without install
pip install vault-mcp # core (keyword search only)
pip install "vault-mcp[semantic]" # + embedding-based semantic search
```
## Running the MCP Server
```bash
# Start with default settings (vault in ./vault)
vault-mcp
# Custom vault directory
VAULT_DIR=/path/to/notes vault-mcp
# With semantic search enabled
VAULT_DIR=./vault VAULT_EMBEDDING_MODEL=jinaai/jina-embeddings-v5-text-nano vault-mcp
```
### Environment Variables
| Variable | Default | Description |
|----------|---------|-------------|
| `VAULT_DIR` | `./vault` | Root directory for markdown files |
| `VAULT_EMBEDDING_MODEL` | *(none)* | Sentence-transformers model name. Enables semantic search when set |
## Client Configuration
### Claude Code
```bash
claude mcp add vault -- vault-mcp
```
Or `.mcp.json`:
```json
{
"mcpServers": {
"vault": {
"type": "stdio",
"command": "vault-mcp",
"env": { "VAULT_DIR": "./vault" }
}
}
}
```
### Cursor / Windsurf / Other MCP Clients
Add to your MCP settings:
```json
{
"vault": {
"command": "vault-mcp",
"env": { "VAULT_DIR": "./vault" }
}
}
```
### Python Library (no MCP)
```python
from vault_mcp import MarkdownVault, create_vault_tools
vault = MarkdownVault("./my-vault")
vault.write("skill/debugging", {"type": "skill", "confidence": "pattern"}, "# Debugging\n\n...")
# Or get all 11 tools as a dict of callables
tools = create_vault_tools(vault)
result = tools["vault_search"](query="debugging", mode="keyword")
```
## Note Format
Each note is a `.md` file with YAML frontmatter, organized in type-based folders:
```
vault/
skill/
timeout-diagnosis.md
concept/
connection-pooling.md
episodic/
2024-01-15-incident.md
```
```markdown
---
type: skill
tags: [database, timeout]
confidence: pattern
status: active
---
# Timeout Diagnosis
Description of the skill...
## Evidence
- [[episodic/2024-01-15-incident]]: First observed during outage
## Related
- [[concept/connection-pooling]]
```
### Frontmatter Fields
| Field | Required | Values |
|-------|----------|--------|
| `type` | Yes | `skill`, `episodic`, `concept`, `failure-pattern`, `system-knowledge` |
| `confidence` | Yes | `fact`, `pattern`, `heuristic` |
| `tags` | No | Free-form string list |
| `status` | Auto | `active`, `superseded`, `archived` |
## Tools
### Write & Edit
| Tool | Description |
|------|-------------|
| `vault_write(path, frontmatter, body)` | Create or overwrite a note |
| `vault_write_batch(entries)` | Write multiple notes atomically |
| `vault_edit(path, operation, params)` | Incremental edit (4 operations below) |
| `vault_delete(path)` | Delete a note |
| `vault_rename(old_path, new_path)` | Rename + auto-rewrite all backlinks |
#### Edit Operations
| Operation | Params | Use |
|-----------|--------|-----|
| `replace_string` | `{"old": "...", "new": "..."}` | Inline corrections |
| `set_frontmatter` | `{"confidence": "fact"}` | Update metadata |
| `replace_section` | `{"heading": "## Evidence", "body": "..."}` | Rewrite a section |
| `append_section` | `{"heading": "## Evidence", "content": "..."}` | Append to a section |
### Read & Browse
| Tool | Description |
|------|-------------|
| `vault_read(path)` | Read frontmatter + body |
| `vault_list(path, depth, type_filter)` | Browse directory |
### Search & Discovery
| Tool | Description |
|------|-------------|
| `vault_search(query, filters, mode, limit)` | FTS5 / semantic / hybrid search |
| `vault_backlinks(path)` | Who links to this note |
| `vault_traverse(start, depth, direction)` | BFS graph traversal with directed edges |
| `vault_lint()` | Find dead links + orphan notes |
## Validation
Every write/edit automatically checks and returns warnings:
- Required frontmatter fields (`type`, `confidence`)
- Valid enum values
- H1 heading present in body
- All `[[wikilinks]]` resolve to existing notes
The write succeeds regardless — warnings are informational for the agent to decide whether to fix.
## Architecture
```
.md files (source of truth, git-trackable)
│
▼
.vault.db (SQLite index, auto-rebuilt if deleted)
├── notes — YAML frontmatter metadata
├── notes_fts — FTS5 full-text search
├── links — [[wikilink]] directed graph
├── tags — tag index
└── notes_vec — embedding vectors (optional)
```
## License
MIT
TDQS
Scored across 11 tools
Tools are mostly distinct with clear purposes, but vault_backlinks and vault_traverse (backward direction) both return incoming links, which could cause misselection. However, descriptions clarify the difference: backlinks is a direct lookup, while traverse explores the graph with depth.
All tools share the vault_ prefix, and most follow a verb pattern (write, read, edit, delete, list, search, lint, traverse). However, vault_backlinks and vault_write_batch deviate from the verb-only convention, making the set slightly inconsistent.
11 tools cover a complete note management workflow: CRUD, batch, search, list, lint, and graph exploration. The number is well-scoped, neither overwhelming nor thin.
The tool set provides full coverage of the vault lifecycle: create, read, update, delete, rename, batch operations, search, and health/link analysis. There are no obvious dead ends or missing core operations.