markdown-vault-mcp
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
| OLLAMA_HOST | No | Ollama server URL (not MARKDOWN_VAULT_MCP_-prefixed) | http://localhost:11434 |
| OPENAI_API_KEY | No | OpenAI API key for the OpenAI embedding provider | |
| OPENAI_BASE_URL | No | OpenAI-compatible API base URL for embeddings (alternative) | https://api.openai.com/v1 |
| FASTMCP_LOG_LEVEL | No | Log level for FastMCP internals | INFO |
| OPENAI_EMBEDDING_MODEL | No | OpenAI-compatible embedding model name (alternative) | text-embedding-3-small |
| MARKDOWN_VAULT_MCP_EXCLUDE | No | Comma-separated glob patterns to exclude from scanning | |
| MARKDOWN_VAULT_MCP_GIT_LFS | No | Enable Git LFS | true |
| FASTMCP_ENABLE_RICH_LOGGING | No | Rich key=value text by default; set to 'false' for one-JSON-object-per-record output | true |
| MARKDOWN_VAULT_MCP_BASE_URL | No | Public base URL of the server (e.g. https://mcp.example.com) | |
| MARKDOWN_VAULT_MCP_GIT_TOKEN | No | Token/password for HTTPS auth (GIT_ASKPASS) | |
| MARKDOWN_VAULT_MCP_HTTP_PATH | No | HTTP endpoint path for streamable HTTP transport | /mcp |
| MARKDOWN_VAULT_MCP_READ_ONLY | No | Set to 'false' to enable write operations | true |
| MARKDOWN_VAULT_MCP_APP_DOMAIN | No | Override the Claude app domain used for MCP Apps iframe sandboxing | |
| MARKDOWN_VAULT_MCP_INDEX_PATH | No | Path to the SQLite FTS5 index file; set for persistence across restarts | in-memory |
| MARKDOWN_VAULT_MCP_SOURCE_DIR | Yes | Path to the markdown vault directory | |
| MARKDOWN_VAULT_MCP_STATE_PATH | No | Path to the change-tracking state file | {SOURCE_DIR}/.markdown_vault_mcp/state.json |
| MARKDOWN_VAULT_MCP_SERVER_NAME | No | MCP server name shown to clients | markdown-vault-mcp |
| MARKDOWN_VAULT_MCP_BEARER_TOKEN | No | Static bearer token; any non-empty string enables auth | |
| MARKDOWN_VAULT_MCP_FILE_WATCHER | No | Enable filesystem-event watcher for external changes | true |
| MARKDOWN_VAULT_MCP_GIT_REPO_URL | No | HTTPS remote URL for managed mode; enables clone/remote validation on startup | |
| MARKDOWN_VAULT_MCP_GIT_USERNAME | No | Username for HTTPS auth prompts | x-access-token |
| MARKDOWN_VAULT_MCP_INSTRUCTIONS | No | System-level instructions injected into LLM context; defaults to a description that reflects read-only vs read-write state | |
| MARKDOWN_VAULT_MCP_KV_STORE_URL | No | Unified key-value backend for HTTP session persistence | file:///data/state |
| MARKDOWN_VAULT_MCP_OLLAMA_MODEL | No | Ollama embedding model name | nomic-embed-text |
| MARKDOWN_VAULT_MCP_OIDC_AUDIENCE | No | Expected JWT audience claim | |
| MARKDOWN_VAULT_MCP_SNIPPET_WORDS | No | Width of the snippet window (words) in search results | 200 |
| MARKDOWN_VAULT_MCP_INDEXED_FIELDS | No | Comma-separated frontmatter fields to promote to the tag index for structured filtering | |
| MARKDOWN_VAULT_MCP_OIDC_CLIENT_ID | No | OIDC client ID registered with your provider | |
| MARKDOWN_VAULT_MCP_PROMPTS_FOLDER | No | Path to a directory of .md prompt files that extend or override built-in prompts | |
| MARKDOWN_VAULT_MCP_BUILD_TIMEOUT_S | No | Maximum seconds a relational/FTS-backed tool or resource waits for the index to become queryable during a cold-start background build | 60 |
| MARKDOWN_VAULT_MCP_CHUNKS_PER_FILE | No | Maximum chunks returned per document in search results | 2 |
| MARKDOWN_VAULT_MCP_DRAIN_TIMEOUT_S | No | Maximum seconds an index-querying read tool waits for the IndexWriter to drain | 60 |
| MARKDOWN_VAULT_MCP_EMBEDDINGS_PATH | No | Path to the numpy embeddings file; required to enable semantic search | disabled |
| MARKDOWN_VAULT_MCP_EVENT_STORE_URL | No | Legacy alias for KV_STORE_URL; honoured only when KV_STORE_URL is unset | |
| MARKDOWN_VAULT_MCP_FASTEMBED_MODEL | No | FastEmbed model name | BAAI/bge-small-en-v1.5 |
| MARKDOWN_VAULT_MCP_GIT_COMMIT_NAME | No | Git committer name for auto-commits | markdown-vault-mcp |
| MARKDOWN_VAULT_MCP_MAX_CHUNK_CHARS | No | Character cap the chunker enforces alongside MAX_CHUNK_WORDS | |
| MARKDOWN_VAULT_MCP_MAX_CHUNK_WORDS | No | Word cap per chunk | 400 |
| MARKDOWN_VAULT_MCP_OIDC_CONFIG_URL | No | OIDC discovery endpoint | |
| MARKDOWN_VAULT_MCP_OLLAMA_CPU_ONLY | No | Force Ollama to use CPU only | false |
| MARKDOWN_VAULT_MCP_OPENAI_BASE_URL | No | OpenAI-compatible API base URL for embeddings | |
| MARKDOWN_VAULT_MCP_REQUIRED_FIELDS | No | Comma-separated frontmatter fields required on every document | |
| MARKDOWN_VAULT_MCP_GIT_COMMIT_EMAIL | No | Git committer email for auto-commits | noreply@markdown-vault-mcp |
| MARKDOWN_VAULT_MCP_GIT_PUSH_DELAY_S | No | Seconds of write-idle time before pushing | 30 |
| MARKDOWN_VAULT_MCP_TEMPLATES_FOLDER | No | Relative folder path where note templates live | _templates |
| MARKDOWN_VAULT_MCP_EMBEDDING_PROVIDER | No | Embedding provider: openai, ollama, or fastembed | auto-detect |
| MARKDOWN_VAULT_MCP_OIDC_CLIENT_SECRET | No | OIDC client secret | |
| MARKDOWN_VAULT_MCP_TRANSFER_TTL_MAX_S | No | Maximum permitted TTL for transfer links | 86400 |
| MARKDOWN_VAULT_MCP_FASTEMBED_CACHE_DIR | No | FastEmbed model cache directory | |
| MARKDOWN_VAULT_MCP_GIT_PULL_INTERVAL_S | No | Seconds between git fetch + ff-only update attempts | 600 |
| MARKDOWN_VAULT_MCP_MAX_NOTE_READ_BYTES | No | Maximum bytes returned by full-document read() for .md files | 262144 |
| MARKDOWN_VAULT_MCP_OIDC_JWT_SIGNING_KEY | No | JWT signing key; required on Linux/Docker | |
| MARKDOWN_VAULT_MCP_OIDC_REQUIRED_SCOPES | No | Comma-separated required scopes | openid |
| MARKDOWN_VAULT_MCP_ATTACHMENT_EXTENSIONS | No | Comma-separated allowed extensions without dot; use '*' to allow all non-.md files | |
| MARKDOWN_VAULT_MCP_GITHUB_WEBHOOK_SECRET | No | Shared secret for GitHub push-event webhook | |
| MARKDOWN_VAULT_MCP_GIT_COMMIT_NAME_CLAIM | No | OIDC claim key to use as the commit author name | |
| MARKDOWN_VAULT_MCP_GIT_COMMIT_EMAIL_CLAIM | No | OIDC claim key to use as the commit author e-mail | |
| MARKDOWN_VAULT_MCP_MAX_ATTACHMENT_SIZE_MB | No | Maximum attachment size in MB returned by read() / accepted by write() | 1.0 |
| MARKDOWN_VAULT_MCP_OPENAI_EMBEDDING_MODEL | No | OpenAI-compatible embedding model name | text-embedding-3-small |
| MARKDOWN_VAULT_MCP_TRANSFER_TTL_DEFAULT_S | No | Default token lifetime (seconds) for transfer links | 3600 |
| MARKDOWN_VAULT_MCP_FILE_WATCHER_DEBOUNCE_S | No | Seconds of quiet after the last event before triggering reindex | 2.0 |
| MARKDOWN_VAULT_MCP_LENGTH_DOWNWEIGHT_ALPHA | No | Down-weights longer chunks in ranking | 0.25 |
| MARKDOWN_VAULT_MCP_OIDC_VERIFY_ACCESS_TOKEN | No | Set 'true' to verify the upstream access token as a JWT | |
| MARKDOWN_VAULT_MCP_TRANSFER_MAX_UPLOAD_BYTES | No | Per-upload size cap for transfer links | 104857600 |
Capabilities
Features and capabilities supported by this server
| Capability | Details |
|---|---|
| tools | {
"listChanged": true
} |
| logging | {} |
| prompts | {
"listChanged": false
} |
| resources | {
"subscribe": false,
"listChanged": false
} |
| extensions | {
"io.modelcontextprotocol/ui": {}
} |
| experimental | {} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| searchA | Find documents matching a query using full-text or semantic search. Search the vault. Default mode is "keyword" (FTS5/BM25). Pass mode="hybrid" when 'stats' shows semantic_search_available=True — hybrid fuses keyword and vector results for best quality. Use mode="semantic" for pure vector similarity. The 'content' field in each result is a snippet by default, not the full document. Use read(path, section=heading) to retrieve the full text of a specific section. |
| readA | Read the full content of a document or attachment by path. For .md documents: returns content (the full raw file including frontmatter), plus the parsed frontmatter, title, and folder. For attachments (pdf, png, etc.): returns base64-encoded binary content and MIME type. Use 'list_documents(include_attachments=True)' to discover attachment paths. Use 'stats' to see allowed extensions. Do not guess paths — look them up first via 'search' or 'list_documents'. To recover the full text of a specific section returned by 'search', pass section=heading (the value from the result's 'heading' field). Context cost: every byte returned counts against the LLM's
context budget. Reads above |
| list_documentsA | List documents (and optionally attachments) in the vault. Use this to enumerate documents when you need a complete listing, not ranked search results. For finding documents by content, use 'search'. Does NOT include body content — call 'read' for full text. |
| list_foldersA | List all folder paths that contain documents. Call this to discover valid folder names before filtering 'search' or 'list_documents' by folder. The root folder (top-level documents) is represented as an empty string "". |
| list_tagsA | List all distinct values for a frontmatter field across the vault. Use this to discover valid filter values before calling 'search' with the 'filters' argument. Only fields listed in indexed_frontmatter_fields (see 'stats') are indexed — querying other fields returns an empty list. |
| statsA | Get an overview of the vault's size, capabilities, and configuration. Call this at the start of a session to understand what the vault contains and what search modes are available. The 'semantic_search_available' field tells you whether mode="semantic" or mode="hybrid" can be used in 'search'. |
| get_similarA | Find notes most semantically similar to the given document. Uses stored embedding vectors — no re-embedding needed. The reference document is excluded from results. Requires semantic search to be configured (check 'stats' for semantic_search_available). Returns an empty list if embeddings are not configured (check 'embeddings_status') or the document has no stored vectors (call 'build_embeddings' to embed missing chunks). |
| get_tocA | Heading outline for a single note or a whole folder subtree. If 'path' ends in '.md' it is a note: returns a flat ordered list of {heading, level} (the title as a synthetic H1). Otherwise 'path' is a folder: returns {path, notes, truncated} where 'notes' is an ordered list of {path, title, headings} aggregating every note under the subtree. Mirrors the 'toc://vault/{path}' resource, adding the max_level / max_notes controls below. |
| get_recentA | Get the most recently modified notes in the vault. Returns notes ordered by file modification time (most recent first). Useful for surfacing recently changed content without a search query — for example to summarize recent activity or resume work on recently edited notes. |
| get_contextA | Get a consolidated context dossier for a document. Replaces separate calls to 'get_backlinks', 'get_outlinks', and 'get_similar' when you need more than one. Returns everything useful about a note in one call: its metadata, backlinks (documents that link to it), outlinks (documents it links to), semantically similar notes, other notes in the same folder, and indexed frontmatter tags. Use this instead of making 4-5 separate tool calls when you need a full picture of a note's place in the vault. |
| get_backlinksA | Find all documents that link TO the given document (backlinks). Use this to discover which notes reference a particular document. For a full picture of a note's place in the vault (backlinks, outlinks, similar notes, folder peers), use 'get_context' instead of calling this separately. Call 'get_backlinks' directly when you only need the inbound link list. Backlinks reveal implicit relationships that search alone cannot surface — they show what other authors considered relevant to this document. |
| get_outlinksA | Find all links FROM the given document to other documents (outlinks). Use this to see what a document references. For a full picture of a note's place in the vault, use 'get_context' instead of calling this separately. Call 'get_outlinks' directly when you only need the outbound link list. Each result includes an 'exists' flag — False means the link is broken (the target is missing from the vault). |
| get_broken_linksA | Find all links that point to non-existent documents (broken links). Use this to audit link health across the vault. Call this when 'stats' shows broken_link_count > 0, or after a 'rename' that did not use update_links=True, to see what links were left pointing to the old path. A broken link means the target path does not match any indexed document — the referenced note may have been deleted, renamed, or never created. |
| get_orphan_notesA | Return all notes with no inbound or outbound links. WARNING: returns ALL orphans with no limit — check 'stats' for orphan_count before calling on large vaults. An orphan note has no backlinks (no other note links to it) and no outlinks (it links to nothing). Call this when 'stats' shows orphan_count > 0. Useful for finding isolated notes that may need to be connected to the rest of the vault or removed. |
| get_most_linkedA | Return the documents with the most inbound links, ranked by backlink count. Useful for discovering hub notes — frequently-referenced notes that are likely key concepts in the vault. For the specific documents that link to a particular note, use 'get_backlinks' instead. |
| get_connection_pathA | Find the shortest connection path between two notes in the link graph. Treats links as undirected — a link from A to B or B to A both count as a connection. Uses BFS; max_depth is clamped to [1, 10]. Useful for discovering how two seemingly unrelated notes are connected through the vault's link structure (the "six degrees of separation" for your notes). |
| embeddings_statusA | Check the embedding provider configuration and vector index status. Use this to diagnose why semantic search is unavailable. Embeddings are built automatically on startup when configured, so chunk_count should normally match the FTS chunk count from 'stats'. If it is lower, call 'build_embeddings' (without force) to embed the missing chunks. Use 'build_embeddings' with force=True only to rebuild from scratch after changing the embedding model. Returns: Dict with the following fields: |
| get_index_statusA | Return background-build state of the FTS index. Use this when Returns: Dict with the following fields: |
| reindexA | Submit an incremental reindex job to the writer. Only needed when files are modified outside this server — for example, by a text editor, a sync tool, or another process writing directly to the vault directory. Do NOT call this after using 'write', 'edit', 'delete', or 'rename' — those tools update the index immediately as part of the operation. To rebuild all embeddings from scratch (e.g. after changing the embedding model), use 'build_embeddings' with force=True. Returns:
Dict with |
| build_embeddingsA | Rebuild vector embeddings for semantic and hybrid search. Embeddings are built automatically on startup, so this is normally not needed. Use force=True to rebuild from scratch after changing the embedding model. Without force, the vector index converges to the FTS chunk set: missing or changed documents are embedded, orphaned vectors are removed, unchanged chunks are untouched. |
| get_historyA | List commits that touched a note or the whole vault. Only available for git-backed vaults. Use 'stats' to check whether git is configured, or call this and handle the error. |
| get_diffA | Return the diff of a note between a reference point and HEAD. Only available for git-backed vaults. Exactly one of 'since_sha' or 'since_timestamp' must be provided. Use 'get_history' first to find commit SHAs. |
| browse_vaultA | Open a visual vault explorer UI for the user — not for reading vault content. Displays an interactive visual panel (MCP Apps) to the user so they can
browse the file tree, explore the link graph, or view a note's relationships.
Do NOT call this to retrieve or inspect vault content programmatically — use
Only call this when the user explicitly asks to open the visual vault browser or explorer (e.g. "show me the vault browser", "open the graph view"). |
| show_contextA | Open a visual context card UI for the user — not for reading note relationships. Displays an interactive context panel (MCP Apps) to the user showing a
note's backlinks, outlinks, similar notes, tags, and frontmatter visually.
Do NOT call this to retrieve note relationship data programmatically — use
Only call this when the user explicitly asks to open the visual context card or explorer (e.g. "show me the context card for this note"). |
| get_server_infoA | Report wrapper and upstream version info for markdown-vault-mcp. Returns server_name, server_version, core_version (fastmcp-pvl-core), and (when configured) an upstream version block. Useful for verifying a deployment matches the expected build. |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
| summarize | Summarize a vault document with structured coverage of main topics and key points. |
| related | Find related notes and suggest cross-references. Read-only — does not modify any documents. |
| compare | Compare two vault notes: agreements, contradictions, and unique information in each. |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
| vault_config | Vault configuration: source path, read-only mode, indexed frontmatter fields, exclude patterns, allowed attachment extensions. For counts and search capabilities, use stats://vault. Index freshness is reported in _meta.index_stale. |
| vault_stats | Vault statistics — document count, chunk count, capabilities. Index freshness is reported in _meta.index_stale. |
| vault_tags | All tags grouped by indexed field. Index freshness is reported in _meta.index_stale. |
| vault_folders | All folder paths in the vault. Index freshness is reported in _meta.index_stale. |
| vault_recent | 20 most recently modified notes. Index freshness is reported in _meta.index_stale. |
| vault_app | Interactive vault explorer with context card, graph, and browser views. |
Latest Blog Posts
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/pvliesdonk/markdown-vault-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server