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 |
Instructions
Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.
This server publishes no instructions, or was last inspected before Glama recorded them.
Capabilities
Features and capabilities supported by this server
Protocol revision2025-11-25
| Capability | Details |
|---|---|
| tools | {
"listChanged": true
} |
| logging | {} |
| prompts | {
"listChanged": true
} |
| resources | {
"subscribe": false,
"listChanged": true
} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| searchA | Search notes by keyword and meaning; returns notes ranked by score, each with its best-matching sections as snippets. Use list_documents for a complete listing and read for a path you already know. |
| readA | Return a note's text, frontmatter and etag, or an attachment's bytes as base64. Look paths up with search or list_documents first rather than guessing them. |
| list_documentsA | List notes, and optionally attachments, with path, title and frontmatter but no body text. Use search to find notes by what they say. |
| list_foldersA | List every folder that holds notes; Pass one as the folder argument of search, list_documents and the other folder-scoped tools. |
| list_tagsA | List the distinct values one indexed frontmatter field takes across the vault. Use the values in the filters argument of search. |
| statsA | Report the vault's size, link health and capabilities: the search modes it serves and the frontmatter fields search can filter on. |
| get_similarA | Find the notes closest in meaning to a given note; returns them ranked by similarity with their closest sections, the note itself excluded. Needs semantic_search_available from stats. A note whose embeddings are not built yet has no similar notes. |
| get_tocA | Return the heading outline of a note, or of every note under a folder. For a note: a list of {heading, level}, the title first as level 1. For a folder: {path, notes, truncated}, each note with its path, title and headings. |
| get_recentA | List the most recently modified notes, newest first. Use it to pick up recent activity without a search query. |
| get_contextA | Return a note's metadata, backlinks, outlinks, similar notes, folder neighbours, indexed tags and applicable conventions in one call. Use it instead of get_backlinks, get_outlinks and get_similar when you need more than one of them. |
| get_conventionsA | Return the vault owner's authoring conventions for a note or folder, vault root first and the most specific last. |
| okf_validateA | Audit how far the vault conforms to the Open Knowledge Format, with example paths per rule; works on a vault not yet declared as a bundle. |
| query_documentsA | Page through all matching indexed notes with an exact total. Queries with text rank by keyword score then path; blank queries rank by modification time descending then path. Pages are live views, so concurrent writes can move notes between pages. Use read to retrieve full note content. |
| count_documentsA | Count every matching indexed note without fetching content. The exact total is independent of search result caps and counts each note once. |
| aggregate_documentsA | Group every matching indexed note into bounded frequency buckets. Counts cover the whole population. Multi-value tag buckets can sum above
total; missing counts notes without a tag value. UTC months use YYYY-MM.
Buckets rank by count descending then |
| search_pathsA | Discover note paths with direct matches before optional typo matches. Returns metadata without bodies. Exact paths rank first, then case-insensitive literal prefix matches, followed by other literal matches and approximate matches. Coverage describes the approximate scan; truncated independently describes omitted results. Use read with a returned path to retrieve its content. |
| get_backlinksA | List the notes that link to a note. Use get_context when you also need its outlinks or similar notes. |
| get_outlinksA | List the links in a note, each with an exists flag that is false when the target is missing. Use get_context when you also need its backlinks or similar notes. |
| get_broken_linksA | List the links whose target is missing from the vault, each with the note that holds it. stats reports broken_link_count; a rename without update_links leaves such links behind. Links to attachments are not checked. |
| get_orphan_notesA | List every note with no links in or out, with no limit on the count. stats reports orphan_count; check it first on a large vault. |
| get_most_linkedA | List the notes with the most backlinks, most first. Use get_backlinks for the notes that link to one of them. |
| get_connection_pathA | Find the shortest chain of links between two notes, following links in either direction. |
| embeddings_statusA | Check embedding provider and vector-index status. |
| get_index_statusA | Report FTS index readiness, progress, and last build error. |
| writeA | Create a note or attachment, or replace one whole; returns its path and whether it was created. Use edit for targeted changes and append to add to the end. Parent folders are created as needed. |
| editA | Replace text in an existing note, chosen by an exact old_text, by a range of lines, or by an old_text within a range of lines. Read the note first for its current text. When old_text has no
exact match, a unique match after normalising Unicode, dashes, quotes and
whitespace is used and reported as match_type |
| appendA | Add text to the end of an existing note without reading it first. Prefer it over edit when the change only adds at the end, such as a log entry. The text starts on a new line; begin it with a blank line or a heading to start a paragraph or section. |
| deleteA | Permanently delete a note or attachment; only git history can bring it back. |
| renameA | Rename or move a note or attachment; with update_links, links to it in other notes follow it. For a note, always pass update_links=True. Parent folders are created as needed. |
| move_folderA | Move a folder and everything under it to a new location, rewriting every link into it across the vault: rename for a whole folder. Notes whose links could not be rewritten are listed in failed_links. |
| fetchA | Download a URL on the server and save it in the vault as a note or attachment; returns its path, size and final_url. The bytes never pass through the conversation, so use it for large files and then pass the path to other tools. |
| okf_convert_linksA | Rewrite wikilinks as bundle-root-absolute Markdown links, the Open Knowledge Format's recommended style; returns counts of links converted and skipped. A wikilink whose target is not in the vault stays as it is. Running it again changes nothing already converted. |
| okf_generate_indexA | Write a folder's Open Knowledge Format index.md: a link to each note directly in it with its description, and one to each subfolder's index.md, replacing the old listing and keeping its frontmatter. Subfolders without an index.md get one too. |
| okf_seed_logA | Create a folder's Open Knowledge Format log.md from the git history of the notes under it, one dated section per day, newest first. It never replaces an existing log.md. It covers the 100 most recent commits. A vault without git history gets an empty log. |
| get_historyA | List the commits that touched a note, an attachment, a folder or the whole vault, newest first. A vault without git history returns no commits. |
| get_diffA | Return how a note or attachment changed from an earlier commit to now, as one unified diff or one per commit. Pass exactly one of since_sha and since_timestamp; find commits with get_history. A vault without git history returns an empty diff. |
| browse_vaultA | Open an interactive vault explorer for the user to look through: the file tree, the link graph or one note's relationships. It shows the vault to the user and returns nothing to read; use search, read, list_documents or get_context for content. |
| vault_contextB | Return the full NoteContext for a note (app-only). Called by the SPA context card view via |
| show_contextA | Open an interactive card for the user showing a note's backlinks, outlinks, similar notes, tags and frontmatter. It shows the note to the user and returns only counts; use get_context for the data. |
| vault_graph_neighborhoodA | Return the link neighborhood of a note as a node/edge graph (app-only). Called by the SPA graph view via |
| vault_graph_hubsA | Return the most-linked notes and their connections as a graph (app-only). Called by the SPA graph view for the hub overview. Not visible to the LLM. |
| vault_listB | List folders and notes in a vault directory (app-only). Called by the SPA browser view via |
| vault_readA | Read a note's full content for preview rendering (app-only). Called by the SPA browser view via |
| vault_searchB | Search the vault (app-only). Called by the SPA browser search bar via |
| get_server_infoA | Report the version information of markdown-vault-mcp; returns server_name, server_version, core_version, the MCP protocol revisions supported and the revision and client of this connection, and, when configured, the upstream service's version. Use it when asked which version or build is running or which protocol revision is in use. |
| reindexA | Bring the search index up to date with files changed outside this server, such as by an editor or a sync tool; returns counts of added, modified, deleted and unchanged notes. Writes through this server's tools update the index themselves, so do not call it after them. |
| build_embeddingsA | Bring the vector index behind semantic and hybrid search up to date with the notes; returns the number of chunks embedded. Embeddings are built automatically, so it is needed only after reindex with force, after a failed build (last_build_embeddings_error in get_index_status), or with force to rebuild them all. |
| get_job_resultA | Get the status of a background job started by a long-running tool on this server; returns status (working, completed or failed) with the result or error once it finishes. Job records expire, so fetch a finished job's result promptly. On this server, background jobs come from slow summarize, reindex, and build_embeddings calls. |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
| summarize | Summarize a vault document with structured coverage of main topics and key points. |
| research | Search the vault for a topic and save what the best matches say as a new research note. |
| discuss | Review a vault note and edit it: factual corrections, clarity, structure and completeness, shown to you first. |
| related | Find related notes and suggest cross-references. Read-only: changes no documents. |
| compare | Compare two vault notes: agreements, contradictions, and unique information in each. |
| propose-links | Propose links between closely related notes that aren't connected yet, and add the ones you approve. |
| create_from_template | Create a new note from one of the vault's templates. |
| summarize-subtree | Summarize a folder or a set of notes with your own model, in batches that keep note bodies out of the conversation. |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
| vault_config | The vault's settings: read-only mode, indexed fields, exclusions, OKF state. |
| vault_stats | Vault statistics: note, chunk and link counts and search capabilities. |
| vault_tags | Every value of every indexed frontmatter field, grouped by field. |
| vault_folders | Every folder in the vault that holds notes. |
| vault_recent | The 20 most recently modified notes. |
| _app_shell |
TDQS
Scored across 48 tools
There is real overlap in the note-querying family: search, query_documents, search_paths, list_documents, count_documents and aggregate_documents all answer 'find notes', and only careful reading of the descriptions separates them. Similarly get_context is explicitly a superset of get_backlinks/get_outlinks/get_similar, and the app-only vault_* tools duplicate read/search/list_documents for the SPA. The descriptions do a lot of work to disambiguate ('use X instead when...'), which keeps it from scoring lower.
Most names are snake_case, but the verb conventions are mixed: bare verbs (read, search, write, edit, append, delete, fetch, stats, reindex), get_/list_ prefixed tools, plus okf_*, vault_* and embeddings_status as noun-style names. The okf_ and vault_ prefixes are meaningful groupings, so it stays readable, but there is no single predictable pattern.
48 tools (roughly 41 LLM-visible once the app-only vault_* and context-card tools are excluded) is heavy for a markdown vault server, and several of them are narrow variants of one another (count_documents, aggregate_documents, search_paths, query_documents). The surface feels like it accumulated features rather than being scoped deliberately.
Coverage is genuinely broad: CRUD (read/write/edit/append/rename/delete/move_folder), link analysis (backlinks, outlinks, broken links, orphans, hubs, connection paths), git history/diff, indexing, embeddings, OKF tooling and fetch. Minor gaps remain — no folder deletion, no dedicated frontmatter-edit tool, and attachment discovery is only implicit — but nothing that blocks typical workflows.