markdown-vault-mcp
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@markdown-vault-mcp search for notes about machine learning"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
markdown-vault-mcp
Python MCP server for programmatic access to markdown-based knowledge vaults
A sister project to mdvault, providing AI assistants with seamless access to your markdown vault through the Model Context Protocol.
Overview
While mdvault provides a Rust CLI and TUI for human interaction with your vault (templates, captures, macros, validation), markdown-vault-mcp exposes your vault to AI assistants through MCP. Together, they form a complete toolkit for managing markdown-based knowledge systems.
flowchart TB
A[AI Assistant<br/>Claude, etc.] -->|MCP| B[markdown-vault-mcp<br/>Python/FastMCP]
B --> C[Markdown Vault<br/>.md files]
B -.->|future| D[mdvault<br/>Rust CLI]
D -.-> CRelated MCP server: Obsidian MCP Server
Features
Browse: List notes and folders in your vault
Read: Access note content and YAML frontmatter metadata
Search: Find notes by content with contextual results
Update: Modify frontmatter, append content, toggle tasks
Navigate: Explore backlinks, outgoing links, orphans, and related notes
Context: Get activity summaries for days, weeks, and notes
Focus: Set and track active project context
Tasks & Projects: Create tasks, projects, and meetings with auto-generated IDs
Reports: Generate activity reports and daily dashboards
Installation
Requires Python 3.13+ and uv.
git clone https://github.com/agustinvalencia/markdown-vault-mcp.git
cd markdown-vault-mcp
uv syncConfiguration
The server needs the MARKDOWN_VAULT_PATH environment variable pointing to your vault root.
Claude Desktop
Add to ~/Library/Application Support/Claude/claude_desktop_config.json:
{
"mcpServers": {
"markdown-vault": {
"command": "uv",
"args": [
"--directory", "/path/to/markdown-vault-mcp",
"run", "mcp-start"
],
"env": {
"MARKDOWN_VAULT_PATH": "/path/to/your/vault"
}
}
}
}Restart Claude Desktop to activate.
Claude Code
Add as a user-scoped MCP server (available in all projects):
claude mcp add markdown-vault \
-s user \
-e MARKDOWN_VAULT_PATH=/path/to/your/vault \
-- uv --directory /path/to/markdown-vault-mcp run mcp-startThis writes to ~/.claude.json. To scope it to a single project instead, use -s project (writes to .mcp.json in the project root).
Restart the Claude Code session (or use /mcp to reload) to activate.
Verifying the connection
Claude Desktop: Open a new conversation and check the MCP icon shows markdown-vault as connected.
Claude Code: Run claude mcp list and confirm markdown-vault shows ✓ Connected.
Available Tools
42 tools organized into 10 categories:
Category | Key Tools |
List |
|
Read |
|
Search |
|
Update |
|
Daily |
|
Zettelkasten |
|
Context |
|
Tasks & Projects |
|
Macros |
|
Management |
|
See docs/tools.md for detailed documentation of each tool.
Usage Examples
Once configured, your AI assistant can interact with your vault:
"What notes do I have about Python?"
I'll search your vault for Python-related notes.
Found 5 notes mentioning Python:
- concepts/python.md
- projects/learning-plan.md
- daily/2024-01-15.md
..."Show me what links to my programming concepts note"
Looking for backlinks to concepts/programming.md...
3 notes link to this:
- concepts/python.md
- concepts/rust.md
- projects/learning-plan.md"Mark the 'Review PR' task as complete in today's daily note"
Updated daily/2024-01-20.md:
- [x] Review PR commentsDevelopment
# Install dependencies
uv sync
# Run the server (for testing)
MARKDOWN_VAULT_PATH=/path/to/vault uv run python -m mdvault_mcp_server
# Run with debug logging
MARKDOWN_VAULT_MCP_DEBUG=true uv run python -m mdvault_mcp_server
# Lint
uv run ruff check src/
# Format
uv run ruff format src/Relationship with mdvault
Compatibility: Requires mdvault v0.3.5+
Feature | mdvault (Rust) | markdown-vault-mcp (Python) |
Purpose | Human CLI/TUI interaction | AI assistant integration |
Tasks/Projects | Yes | Yes (via mdvault CLI) |
Meetings | Yes (v0.3.0+) | Yes (via mdvault CLI) |
Templates | Yes | Yes (via mdvault CLI) |
Captures | Yes (Lua) | Yes (via mdvault CLI) |
Macros | Yes (Lua) | Yes (via mdvault CLI) |
Focus Mode | Yes | Yes (via mdvault CLI) |
Context Queries | Yes | Yes (via mdvault CLI) |
Activity Reports | Yes | Yes (via mdvault CLI) |
Reading | Via CLI commands | MCP tools + CLI |
Search | SQLite index | Direct file search |
Link Graph | SQLite index | Real-time parsing |
Validation | Type schemas | Yes (via mdvault CLI) |
The MCP server delegates complex operations (tasks, projects, meetings, captures, macros) to the mdvault CLI, ensuring consistent behavior between human and AI interactions.
License
MIT License - see LICENSE for details.
Available Tools
48 toolsadd_to_inboxA
Quickly capture a thought, idea, or todo to today's daily note inbox.
Zero friction — just dumps content as a bullet point to the Inbox section. Creates the daily note if it doesn't exist.
Args: content: The thought, idea, or todo to capture.
Returns: Success message or error description.
Inputs: content (required). Returns: result
append_to_daily_noteA
Append content to today's daily note under an optional subsection.
Creates the daily note and its parent directories if they don't exist. The note path matches the configured 'daily_format' (default: 'Journal/YYYY/Daily/YYYY-MM-DD.md').
For timestamped log entries, use log_to_daily_note instead.
Args: content: Content to append subsection: Optional heading title to append under.
Returns: Success message or error description
Inputs: content (required), subsection. Returns: result
append_to_noteA
Append content to a note, optionally within a specific subsection.
Args: note_path: Path to the note relative to vault root content: Content to append subsection: Optional heading title to append under. If not found, creates it at end.
Returns: Success message or error description
Inputs: content (required), note_path (required), subsection. Returns: result
archive_projectA
Archive a completed project.
Moves project and tasks to Projects/_archive/, cancels open tasks, clears focus if set, and logs the event. Only projects with status 'done' can be archived. Areas (kind: area) cannot be archived — they are ongoing.
Args: project_name: The project ID or folder name to archive.
Inputs: project_name (required). Returns: result
cancel_taskA
Cancel a task.
Sets status to 'cancelled' with a timestamp. Logs cancellation to the parent project note automatically.
Args: task_id: Task ID (e.g. "MDV-001") or path to the task file relative to vault root. reason: Optional reason for cancellation (appended to task body).
Inputs: task_id (required), reason. Returns: result
capture_contentB
Capture content into a configured capture location.
Args: name: Name of the capture (e.g., 'inbox', 'log'). text: Main content to capture (passed as 'text' variable). extra_vars: Optional dictionary of additional variables.
Returns: Result of the capture command.
Inputs: name (required), text (required), extra_vars. Returns: result
clear_focusA
Clear the active project focus.
Inputs: no named parameters. Returns: result
complete_taskA
Mark a task as done.
Sets status to 'done' with a completion timestamp. Logs completion to the parent project note automatically.
Args: task_id: Task ID (e.g. "MDV-001") or path to the task file relative to vault root. summary: Optional summary of what was done (appended to task body).
Inputs: task_id (required), summary. Returns: result
create_daily_noteA
Create today's daily note from the configured template.
Uses the vault's daily template to create a fully structured note with all standard frontmatter fields and sections. If the note already exists, returns a message without overwriting.
Args: date: Optional date in YYYY-MM-DD format. Defaults to today. extra_vars: Optional dictionary of additional template variables.
Returns: Result of the creation or message if note already exists.
Inputs: date, extra_vars. Returns: result
create_literature_noteA
Create a new literature note from the template.
Literature notes are stored in Zettel/Literature/ and track reading progress through multi-pass reading (skimming, reading, completed).
Args: title: Full title of the paper/book/article. short_title: Short title for the filename slug (e.g. "attention-is-all-you-need"). authors: Author names, comma-separated (e.g. "Vaswani, Shazeer, Parmar"). year: Year of publication. url: URL or DOI link to the source. source_type: Type of source (article, book, video, podcast, other). extra_vars: Optional dictionary of additional template variables.
Returns: Result of the creation.
Inputs: title (required), short_title (required), url, year, +3 more. Returns: result
create_meetingA
Create a new meeting note.
Meeting notes have auto-generated IDs (MTG-YYYY-MM-DD-NNN) and are stored in the Meetings/ folder. Creation is logged to the daily note.
Args: title: Title of the meeting (e.g. "Team Sync", "Design Review"). attendees: Who's attending (e.g. "Alice, Bob, Charlie"). date: Meeting date in YYYY-MM-DD format. Defaults to today. extra_vars: Optional dictionary of additional variables for the template.
Returns: Result of the meeting creation including the generated meeting ID.
Inputs: title (required), date, attendees, extra_vars. Returns: result
create_monthly_reportA
Create a monthly report note from the configured template.
Creates a structured monthly report in Journal/YYYY/Monthly/YYYY-MM.md. If the note already exists, returns a message without overwriting.
Args: period: Reporting period in YYYY-MM format. Defaults to current month. period_start: Optional custom start date (YYYY-MM-DD) for non-calendar periods. period_end: Optional custom end date (YYYY-MM-DD) for non-calendar periods. extra_vars: Optional dictionary of additional template variables.
Returns: Result of the creation or message if note already exists.
Inputs: period, extra_vars, period_end, period_start. Returns: result
create_projectA
Create a new project or area.
Args: title: Title of the new project or area. context: Project context (e.g. 'work', 'personal'). description: Optional description of the project (max 1024 chars). status: Project status (e.g. 'open', 'in-progress', 'blocked', 'done', 'archived'). kind: Either 'project' (finite goal, default) or 'area' (ongoing responsibility). extra_vars: Optional dictionary of additional variables for the template.
Inputs: title (required), context (required), kind, status, +2 more. Returns: result
create_taskA
Create a new task.
If no project is specified, mdvault automatically uses the active focus context. Context inheritance from the project is handled automatically.
Args: title: Title of the task. description: Optional description of the task (max 1024 chars). project: Optional project name. If omitted, uses the active focus context. due_date: Optional due date (YYYY-MM-DD). priority: Optional priority (e.g. 'low', 'medium', 'high'). status: Optional status (e.g. 'todo', 'doing', 'done'). extra_vars: Optional dictionary of additional variables for the template.
Inputs: title (required), status, project, due_date, +3 more. Returns: result
create_weekly_noteA
Create a weekly note from the configured template.
Uses the vault's weekly template to create a structured note. If the note already exists, returns a message without overwriting.
Args: week: Week identifier in YYYY-WXX format, or a date expression like 'today', 'today + 1w'. Defaults to current week. extra_vars: Optional dictionary of additional template variables.
Returns: Result of the creation or message if note already exists.
Inputs: week, extra_vars. Returns: result
create_zettelA
Create a new zettel (atomic knowledge note).
Zettels are stored in the Zettel/ directory (or as configured by the vault's type definition). Each zettel captures a single atomic insight.
Args: title: Title of the zettel (the atomic insight). short_title: Short slug for the filename (e.g. "attention-mechanism"). source: Optional source reference as a wikilink (e.g. "[[literature-note]]"). body: Optional body text elaborating on the insight. connections: Optional list of related note wikilinks (e.g. ["[[note-1]]", "[[note-2]]"]). extra_vars: Optional dictionary of additional template variables.
Returns: Result of the creation including the file path.
Inputs: title (required), short_title (required), body, source, +2 more. Returns: result
export_area_metricsA
Export area metrics as CSV or JSON for trend analysis.
Dumps daily note metadata for the area's criteria fields over a date range. Useful for plotting trends externally.
Args: area: Area name or ID (e.g. 'health', 'HEA'). format: Output format ('csv' or 'json'). from_date: Start date in YYYY-MM-DD format. Defaults to 30 days ago. to_date: End date in YYYY-MM-DD format. Defaults to today.
Returns: CSV or JSON string with daily values for each criterion field.
Inputs: area (required), format, to_date, from_date. Returns: result
find_backlinksA
Find all notes that link to the specified note.
Args: note_path: Path to the note relative to vault root
Returns: Newline-separated list of notes linking to this note, or message if none
Inputs: note_path (required). Returns: result
find_outgoing_linksA
Find all notes that the specified note links to.
Args: note_path: Path to the note relative to vault root
Returns: Newline-separated list of linked notes, or message if none
Inputs: note_path (required). Returns: result
generate_visual_reportA
Generate a visual PNG dashboard with charts and save it to the vault.
Produces a multi-panel PNG image with task status pie chart, project progress bars, activity timeline, and velocity comparison. The image is saved to assets/dashboards/ in the vault and can be embedded in notes via standard markdown image syntax.
Args: project: Scope to a specific project (ID or folder name). Omit for vault-wide dashboard.
Returns: Success message with path to the generated PNG, or error message.
Inputs: project. Returns: result
get_activity_reportA
Generate a metrics-centric activity report for a time period.
Returns aggregate productivity metrics: activity heatmap, daily note coverage, project progress stats, and actionable sections (overdue tasks, upcoming deadlines, high priority, stale notes). Supports both weekly and monthly periods (context week does not support monthly).
For task-level detail (individual task lists, in-progress tracking, per-day focus), use get_context_week instead.
Args: month: Month in YYYY-MM format (e.g. '2025-01' for January 2025). Cannot be used with 'week'. week: Week in YYYY-Wxx format (e.g. '2025-W05' for week 5 of 2025). Cannot be used with 'month'.
Returns: Activity report for the specified period.
Inputs: week, month. Returns: result
get_area_reportA
Get area health report: criteria vs actuals for a period.
Checks the area's health_criteria against daily note metadata and returns how each standard is tracking.
Args: area: Area name or ID (e.g. 'health', 'HEA'). period: 'week', 'month', or specific like '2026-W11', '2026-03'.
Returns: JSON with area name, period, and criteria results (label, field, actual, target, met).
Inputs: area (required), period. Returns: result
get_context_dayA
Get activity context for a specific day including tasks, notes modified, and logs.
Args: date: Date in YYYY-MM-DD format, or 'today', 'yesterday', or date expression.
Inputs: date. Returns: result
get_context_focusA
Get context for the currently focused project.
Returns the active project with task counts, recent tasks, and activity. Use this to understand what the user is currently working on.
Inputs: no named parameters. Returns: result
get_context_noteA
Get context for a specific note including metadata, sections, activity, and references.
Args: note_path: Path to the note relative to vault root. activity_days: Number of days of activity history to include.
Inputs: note_path (required), activity_days. Returns: result
get_context_weekA
Get task-centric activity context for a specific week.
Returns individual task lists (in-progress, completed, created), per-day focus breakdown, and project log entries. Use this to understand what happened at the task level during a week.
For aggregate metrics (heatmap, coverage, top completed counts), use get_activity_report with a week parameter instead.
Args: week: Week identifier ('current', 'last', YYYY-Wxx), or None for current.
Inputs: week. Returns: result
get_daily_dashboardA
Get the daily dashboard summary (today's tasks, events, etc).
Returns: The output of 'mdv today', summarizing the day.
Inputs: no named parameters. Returns: result
get_dashboard_reportA
Get a structured dashboard report with project metrics, velocity, and activity.
Returns a JSON report containing vault summary (notes/tasks by type and status), per-project breakdowns (task counts, progress %, velocity, recent completions), daily activity data, and actionable task lists (overdue, high_priority, upcoming_deadlines). Use for rich status checks, project reviews, and weekly/monthly reporting.
Args: project: Scope to a specific project (ID or folder name). Omit for vault-wide report. activity_days: Days of activity history to include (default: 30).
Returns: JSON dashboard report or error message.
Inputs: project, activity_days. Returns: result
get_metadataA
Get the frontmatter metadata from a note as JSON.
Args: note_path: Path to the note relative to vault root
Returns: JSON string with metadata or error description
Inputs: note_path (required). Returns: result
get_project_contextA
Get rich context for a project: metadata, sections, tasks, activity, and references.
Returns the full context note output for the project, including recent task activity, backlinks, and outgoing links.
Args: project_name: Name or ID of the project.
Inputs: project_name (required). Returns: result
get_project_progressA
Show progress metrics for a project or all projects.
Args: project_name: Optional project name to get detailed progress for. If omitted, shows summary for all projects.
Inputs: project_name. Returns: result
get_project_statusA
Show detailed status of a project (Kanban view).
Args: project_name: Name or ID of the project.
Inputs: project_name (required). Returns: result
get_task_detailsB
Show details for a specific task.
Args: task_id: The ID of the task.
Inputs: task_id (required). Returns: result
list_foldersA
List subfolders in the vault, optionally scoped to a parent folder.
Skips hidden directories and empty folders.
Args: folder: Parent folder to list subfolders from (relative to vault root). If empty, lists top-level vault folders.
Returns: Newline-separated list of folder paths relative to vault root.
Inputs: folder. Returns: result
list_notesA
List all markdown notes in the vault, optionally scoped to a folder.
Args: folder: Subfolder to list notes from (relative to vault root). If empty, lists all notes in the vault.
Returns: Newline-separated list of note paths relative to vault root.
Inputs: folder. Returns: result
list_projectsA
List all projects with task counts.
Args: status_filter: Filter projects by status (e.g., 'active', 'archived'). kind_filter: Filter by kind ('project' or 'area').
Inputs: kind_filter, status_filter. Returns: result
list_tasksA
List tasks with optional filters.
Args: project_filter: Filter tasks by project name. status_filter: Filter tasks by status ('todo', 'in-progress', 'blocked', 'done', 'cancelled', 'archived').
Inputs: status_filter, project_filter. Returns: result
log_to_daily_noteA
Append a log entry to the 'Logs' section of today's daily note.
Format: - HH:MM: Content
Args: log_message: The log message to append.
Returns: Success message or error description.
Inputs: log_message (required). Returns: result
log_to_noteA
Append a log entry to the 'Logs' section of any note (project, task, etc.).
Format: - [[YYYY-MM-DD]] - HH:MM: Content
Args: note_path: Path to the note relative to vault root. content: The log message to append.
Returns: Success message or error description.
Inputs: content (required), note_path (required). Returns: result
read_noteA
Read a note from the vault.
Args: note_path: Path to the note relative to vault root max_lines: Optional maximum number of lines to return. If omitted, returns the full note.
Returns: Note content (possibly truncated) or error description
Inputs: note_path (required), max_lines. Returns: result
replace_in_noteA
Replace text in a note's body content.
Performs plain string find-and-replace on the note body (not frontmatter). Fails if old_text is not found.
Args: note_path: Path to the note relative to vault root. old_text: The exact text to find. new_text: The replacement text. count: Number of occurrences to replace. 1 = first match only (default), 0 = replace all.
Returns: Success message or error description.
Inputs: new_text (required), old_text (required), note_path (required), count. Returns: result
run_macroB
Run a predefined macro using the mdv CLI.
Args: name: The name of the macro to run (e.g., 'daily-standup', 'new-project') args: Optional list of positional arguments to pass to the macro variables: Optional dictionary of variables to pass to the macro (--var k=v)
Returns: Output of the macro execution or error message.
Inputs: name (required), args, variables. Returns: result
search_notesA
Search notes containing the query text (case-insensitive).
Args: query: Text to search for folder: Optional subfolder to limit search scope context_lines: Number of lines before/after each match to include. When 0 (default), returns only matching file paths. When > 0, returns matches with surrounding context.
Returns: Newline-separated list of matching note paths, or formatted results with context for each match
Inputs: query (required), folder, context_lines. Returns: result
set_focusA
Set the active project focus.
Args: project: The project ID or name to focus on. note: Optional note about what you are working on.
Inputs: project (required), note. Returns: result
update_metadataA
Update frontmatter metadata in a note, preserving existing fields.
Args: note_path: Path to the note relative to vault root metadata_json: JSON string with metadata fields to update/add
Returns: Success message or error description
Inputs: note_path (required), metadata_json (required). Returns: result
update_task_statusA
Update the status of a task checkbox in a note.
Args: note_path: Path to the note relative to vault root task_pattern: Text pattern to identify the task (matches task content) completed: True to mark as completed [x], False to mark as incomplete [ ]
Returns: Success message or error description
Inputs: completed (required), note_path (required), task_pattern (required). Returns: result
validate_noteA
Validate notes against Lua type definitions (frontmatter schema).
Runs mdv validate to check that note frontmatter conforms to the
type definition schemas (required fields, types, enums, defaults).
Args: path: Specific note path to validate (relative to vault root). Omit to validate all notes. note_type: Only validate notes of this type (daily, task, project, etc.). fix: Auto-fix safe issues (missing defaults, enum case normalisation). limit: Maximum number of notes to validate.
Returns: Validation report with per-note errors and fixes applied.
Inputs: fix, path, limit, note_type. Returns: result
vault_lintA
Check vault structural correctness (broken links, schema violations, orphans, etc.).
Runs mdv check and returns an AI-friendly summary of vault health.
Args: category: Optional category to check (broken_references, malformed_wikilinks, schema_violations, structural_consistency, orphaned_notes, db_sync). Omit to run all checks. fix: If True, attempt to auto-fix fixable issues (not yet implemented).
Returns: Vault health report with issues grouped by category.
Inputs: fix, category. Returns: result
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 48 tools
Several tool clusters overlap heavily: get_context_week/get_activity_report/get_dashboard_report all return activity metrics, get_project_status/get_project_progress/get_project_context all describe a project, and vault_lint/validate_note both check schema/structural issues. The daily note append tools (append_to_daily_note/add_to_inbox/log_to_daily_note) are distinguishable only by section conventions, so an agent could easily misselect.
Most tools follow a readable snake_case verb_noun pattern (list_notes, create_task, archive_project), which helps navigation. However, retrieval verbs are inconsistent (list/get/find/search), vault_lint reverses the pattern, and several close concepts use divergent names (get_context_week vs get_activity_report, log_to_daily_note vs append_to_note).
48 tools is a very large surface for an agent to choose from, even for a broad vault-management domain. Many of these tools could be consolidated (the context/report cluster alone has nine overlapping tools), making the set feel heavier than necessary.
The set covers the core note, task, project, and reporting workflows well, with create/list/read/update operations for most main objects. But there is no generic note creation, no delete/rename for notes or tasks, and no update path for task details or project status beyond archive/complete/cancel, leaving notable lifecycle gaps.
Maintenance
Related MCP Connectors
Serve a folder of Markdown notes as an MCP server: hybrid search, reading, and sourced answers.
Hosted MCP server for Obsidian Sync vaults: read, search, edit notes. Not affiliated with Obsidian.
Markdown-based note-taking with a hosted MCP server. Your notes serve you and your AI.
KnowMan MCP server: search, ask, save and read your Knowledge Base from any MCP client.
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceProvides an MCP server that allows AI assistants to interact with Obsidian vaults, enabling reading/writing notes, managing metadata, searching content, and working with daily notes.37MIT
- AlicenseBqualityDmaintenanceAn MCP server that enables AI assistants to access and manage your local Obsidian vault through a standardized protocol.147,721 npm2Apache 2.0
- FlicenseNot gradedqualityCmaintenanceA Python MCP server for accessing and managing Obsidian vaults, providing tools for reading, writing, searching, and organizing notes across multiple vaults.-
- AlicenseAqualityCmaintenanceMCP server for managing a local, domain-agnostic knowledge base using Markdown notes with frontmatter. Enables AI agents to capture, read, search, link, and maintain notes with atomic writes and privacy controls.13MIT