Skip to main content
Glama
pvliesdonk

markdown-vault-mcp

by pvliesdonk

Server Configuration

Describes the environment variables required to run the server.

NameRequiredDescriptionDefault
OLLAMA_HOSTNoOllama server URL (not MARKDOWN_VAULT_MCP_-prefixed)http://localhost:11434
OPENAI_API_KEYNoOpenAI API key for the OpenAI embedding provider
OPENAI_BASE_URLNoOpenAI-compatible API base URL for embeddings (alternative)https://api.openai.com/v1
FASTMCP_LOG_LEVELNoLog level for FastMCP internalsINFO
OPENAI_EMBEDDING_MODELNoOpenAI-compatible embedding model name (alternative)text-embedding-3-small
MARKDOWN_VAULT_MCP_EXCLUDENoComma-separated glob patterns to exclude from scanning
MARKDOWN_VAULT_MCP_GIT_LFSNoEnable Git LFStrue
FASTMCP_ENABLE_RICH_LOGGINGNoRich key=value text by default; set to 'false' for one-JSON-object-per-record outputtrue
MARKDOWN_VAULT_MCP_BASE_URLNoPublic base URL of the server (e.g. https://mcp.example.com)
MARKDOWN_VAULT_MCP_GIT_TOKENNoToken/password for HTTPS auth (GIT_ASKPASS)
MARKDOWN_VAULT_MCP_HTTP_PATHNoHTTP endpoint path for streamable HTTP transport/mcp
MARKDOWN_VAULT_MCP_READ_ONLYNoSet to 'false' to enable write operationstrue
MARKDOWN_VAULT_MCP_APP_DOMAINNoOverride the Claude app domain used for MCP Apps iframe sandboxing
MARKDOWN_VAULT_MCP_INDEX_PATHNoPath to the SQLite FTS5 index file; set for persistence across restartsin-memory
MARKDOWN_VAULT_MCP_SOURCE_DIRYesPath to the markdown vault directory
MARKDOWN_VAULT_MCP_STATE_PATHNoPath to the change-tracking state file{SOURCE_DIR}/.markdown_vault_mcp/state.json
MARKDOWN_VAULT_MCP_SERVER_NAMENoMCP server name shown to clientsmarkdown-vault-mcp
MARKDOWN_VAULT_MCP_BEARER_TOKENNoStatic bearer token; any non-empty string enables auth
MARKDOWN_VAULT_MCP_FILE_WATCHERNoEnable filesystem-event watcher for external changestrue
MARKDOWN_VAULT_MCP_GIT_REPO_URLNoHTTPS remote URL for managed mode; enables clone/remote validation on startup
MARKDOWN_VAULT_MCP_GIT_USERNAMENoUsername for HTTPS auth promptsx-access-token
MARKDOWN_VAULT_MCP_INSTRUCTIONSNoSystem-level instructions injected into LLM context; defaults to a description that reflects read-only vs read-write state
MARKDOWN_VAULT_MCP_KV_STORE_URLNoUnified key-value backend for HTTP session persistencefile:///data/state
MARKDOWN_VAULT_MCP_OLLAMA_MODELNoOllama embedding model namenomic-embed-text
MARKDOWN_VAULT_MCP_OIDC_AUDIENCENoExpected JWT audience claim
MARKDOWN_VAULT_MCP_SNIPPET_WORDSNoWidth of the snippet window (words) in search results200
MARKDOWN_VAULT_MCP_INDEXED_FIELDSNoComma-separated frontmatter fields to promote to the tag index for structured filtering
MARKDOWN_VAULT_MCP_OIDC_CLIENT_IDNoOIDC client ID registered with your provider
MARKDOWN_VAULT_MCP_PROMPTS_FOLDERNoPath to a directory of .md prompt files that extend or override built-in prompts
MARKDOWN_VAULT_MCP_BUILD_TIMEOUT_SNoMaximum seconds a relational/FTS-backed tool or resource waits for the index to become queryable during a cold-start background build60
MARKDOWN_VAULT_MCP_CHUNKS_PER_FILENoMaximum chunks returned per document in search results2
MARKDOWN_VAULT_MCP_DRAIN_TIMEOUT_SNoMaximum seconds an index-querying read tool waits for the IndexWriter to drain60
MARKDOWN_VAULT_MCP_EMBEDDINGS_PATHNoPath to the numpy embeddings file; required to enable semantic searchdisabled
MARKDOWN_VAULT_MCP_EVENT_STORE_URLNoLegacy alias for KV_STORE_URL; honoured only when KV_STORE_URL is unset
MARKDOWN_VAULT_MCP_FASTEMBED_MODELNoFastEmbed model nameBAAI/bge-small-en-v1.5
MARKDOWN_VAULT_MCP_GIT_COMMIT_NAMENoGit committer name for auto-commitsmarkdown-vault-mcp
MARKDOWN_VAULT_MCP_MAX_CHUNK_CHARSNoCharacter cap the chunker enforces alongside MAX_CHUNK_WORDS
MARKDOWN_VAULT_MCP_MAX_CHUNK_WORDSNoWord cap per chunk400
MARKDOWN_VAULT_MCP_OIDC_CONFIG_URLNoOIDC discovery endpoint
MARKDOWN_VAULT_MCP_OLLAMA_CPU_ONLYNoForce Ollama to use CPU onlyfalse
MARKDOWN_VAULT_MCP_OPENAI_BASE_URLNoOpenAI-compatible API base URL for embeddings
MARKDOWN_VAULT_MCP_REQUIRED_FIELDSNoComma-separated frontmatter fields required on every document
MARKDOWN_VAULT_MCP_GIT_COMMIT_EMAILNoGit committer email for auto-commitsnoreply@markdown-vault-mcp
MARKDOWN_VAULT_MCP_GIT_PUSH_DELAY_SNoSeconds of write-idle time before pushing30
MARKDOWN_VAULT_MCP_TEMPLATES_FOLDERNoRelative folder path where note templates live_templates
MARKDOWN_VAULT_MCP_EMBEDDING_PROVIDERNoEmbedding provider: openai, ollama, or fastembedauto-detect
MARKDOWN_VAULT_MCP_OIDC_CLIENT_SECRETNoOIDC client secret
MARKDOWN_VAULT_MCP_TRANSFER_TTL_MAX_SNoMaximum permitted TTL for transfer links86400
MARKDOWN_VAULT_MCP_FASTEMBED_CACHE_DIRNoFastEmbed model cache directory
MARKDOWN_VAULT_MCP_GIT_PULL_INTERVAL_SNoSeconds between git fetch + ff-only update attempts600
MARKDOWN_VAULT_MCP_MAX_NOTE_READ_BYTESNoMaximum bytes returned by full-document read() for .md files262144
MARKDOWN_VAULT_MCP_OIDC_JWT_SIGNING_KEYNoJWT signing key; required on Linux/Docker
MARKDOWN_VAULT_MCP_OIDC_REQUIRED_SCOPESNoComma-separated required scopesopenid
MARKDOWN_VAULT_MCP_ATTACHMENT_EXTENSIONSNoComma-separated allowed extensions without dot; use '*' to allow all non-.md files
MARKDOWN_VAULT_MCP_GITHUB_WEBHOOK_SECRETNoShared secret for GitHub push-event webhook
MARKDOWN_VAULT_MCP_GIT_COMMIT_NAME_CLAIMNoOIDC claim key to use as the commit author name
MARKDOWN_VAULT_MCP_GIT_COMMIT_EMAIL_CLAIMNoOIDC claim key to use as the commit author e-mail
MARKDOWN_VAULT_MCP_MAX_ATTACHMENT_SIZE_MBNoMaximum attachment size in MB returned by read() / accepted by write()1.0
MARKDOWN_VAULT_MCP_OPENAI_EMBEDDING_MODELNoOpenAI-compatible embedding model nametext-embedding-3-small
MARKDOWN_VAULT_MCP_TRANSFER_TTL_DEFAULT_SNoDefault token lifetime (seconds) for transfer links3600
MARKDOWN_VAULT_MCP_FILE_WATCHER_DEBOUNCE_SNoSeconds of quiet after the last event before triggering reindex2.0
MARKDOWN_VAULT_MCP_LENGTH_DOWNWEIGHT_ALPHANoDown-weights longer chunks in ranking0.25
MARKDOWN_VAULT_MCP_OIDC_VERIFY_ACCESS_TOKENNoSet 'true' to verify the upstream access token as a JWT
MARKDOWN_VAULT_MCP_TRANSFER_MAX_UPLOAD_BYTESNoPer-upload size cap for transfer links104857600

Capabilities

Features and capabilities supported by this server

CapabilityDetails
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

NameDescription
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 MARKDOWN_VAULT_MCP_MAX_NOTE_READ_BYTES (default 256 KB for .md) or MARKDOWN_VAULT_MCP_MAX_ATTACHMENT_SIZE_MB (default 1 MB for binaries) raise ValueError. For partial markdown reads, pass section=heading (use the heading field from a search() result).

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:

- available (bool): True if semantic search can be used in 'search'.
- provider (str | None): Provider class name when configured
  (e.g. "OllamaProvider"), or null if not configured.
- chunk_count (int): Number of chunks currently in the vector index.
- path (str | None): Vector index file path when persisted, or null.
get_index_statusA

Return background-build state of the FTS index.

Use this when initialize returned but bucket-3/4 calls block longer than expected or surface IndexUnavailableError — the status field distinguishes "still building" from "build failed," and the error field carries the exception message from the last background-build attempt that captured one. error may be populated when status is "queryable" (a successful build followed by a later failed rebuild leaves the captured diagnostic in place until the next successful build clears it) and is always None when status is "building".

Returns: Dict with the following fields:

- status (str): ``"queryable"``, ``"building"``, or
  ``"failed"``.
- documents_indexed (int): Count of documents committed to
  the FTS index right now (rises during ``"building"``).
  ``0`` both for an empty index and when the count could not
  be read — see ``documents_indexed_error`` to tell them apart.
- documents_indexed_error (str | None): ``None`` on a normal
  read; the SQLite error message when the document count
  could not be read (e.g. a locked or closed database), in
  which case ``documents_indexed`` is ``0``.
- error (str | None): ``None`` unless the background build
  raised.
- skipped_files (list[dict]): Files dropped from the index for a
  surfaced deterministic reason. Each entry is
  ``{"path", "category", "detail"}`` where ``category`` is one of
  ``"parse_error"``, ``"encoding_error"``,
  ``"missing_frontmatter"``, or ``"internal_error"`` (an
  unexpected indexer error, vs a content problem). Empty when
  nothing was skipped.
  Distinguishes a parse-dropped note from an unsynced one without
  reading container logs. Exclude-pattern and transient-I/O skips
  are intentionally not listed.
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 status: "queued". The reindex runs asynchronously on the writer thread. Poll get_index_status for completion:

- ``status == "queryable"`` AND ``queue_depth == 0`` AND
  ``in_flight is None`` → reindex completed.
- ``last_reindex_error`` not ``None`` → the most recent async
  reindex failed on the writer thread; the value is the
  stringified exception.  Operators can re-run ``reindex`` to
  retry; a subsequent successful run clears the field.
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 search to find notes, read for note content, list_documents to enumerate files, and get_context for a note's relationships instead.

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 get_context instead, which returns the full structured data.

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

NameDescription
summarizeSummarize a vault document with structured coverage of main topics and key points.
relatedFind related notes and suggest cross-references. Read-only — does not modify any documents.
compareCompare two vault notes: agreements, contradictions, and unique information in each.

Resources

Contextual data attached and managed by the client

NameDescription
vault_configVault 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_statsVault statistics — document count, chunk count, capabilities. Index freshness is reported in _meta.index_stale.
vault_tagsAll tags grouped by indexed field. Index freshness is reported in _meta.index_stale.
vault_foldersAll folder paths in the vault. Index freshness is reported in _meta.index_stale.
vault_recent20 most recently modified notes. Index freshness is reported in _meta.index_stale.
vault_appInteractive vault explorer with context card, graph, and browser views.

Latest Blog Posts

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