Skip to content

Configuration

The config module loads configuration from environment variables and provides a typed dataclass for all settings.

Quick Start

to_vault_settings maps a loaded configuration onto a VaultSettings, and to_vault_instances resolves the constructed collaborators (embedding provider, summarizer, git strategy). Together they feed Vault construction:

import os
from markdown_vault_mcp.config import ProjectConfig
from markdown_vault_mcp.config_sections._assembly import (
    to_vault_instances,
    to_vault_settings,
)
from markdown_vault_mcp.vault import Vault

os.environ["MARKDOWN_VAULT_MCP_SOURCE_DIR"] = "/path/to/vault"
config = ProjectConfig.from_env()
instances = to_vault_instances(config)
settings = to_vault_settings(config, instances=instances)
vault = Vault(
    source_dir=config.source_dir,
    settings=settings,
    embedding_provider=instances.embedding_provider,
    summarizer=instances.summarizer,
    git_strategy=instances.git_strategy,
    on_write=instances.on_write,
)

Migrating from 4.x

to_vault_kwargs has been removed from both markdown_vault_mcp.config and markdown_vault_mcp.config_sections._assembly. Replace Vault(**to_vault_kwargs(config)) with the construction shown above. Resolve instances once and pass it to to_vault_settings so the provider is loaded once and its context limit determines the chunk size.

For overrides formerly applied to the keyword dictionary, use dataclasses.replace on the settings before constructing the vault:

from dataclasses import replace
from pathlib import Path

settings = replace(settings, index_path=Path("/path/to/other-index.db"))

Keep collaborator overrides on the corresponding Vault keyword arguments.

API Reference

ProjectConfig(server=ServerConfig(), server_name=_default_server_name(), source_dir=Path('/data/vault'), read_only=False, write_protect_existing=True, disable_apps_ui=False, index_path=None, state_path=None, embeddings_path=None, indexed_fields=None, required_fields=None, exclude=None, title_field='title', searchable_fields=None, templates_folder='_templates', prompts_folder=None, conventions_file='_conventions.md', okf_mode='auto', okf_write=False, okf_verify='elicit', attachment_extensions=None, max_attachment_size_mb=1.0, max_note_read_bytes=262144, default_search_mode='auto', chunks_per_file=2, snippet_words=200, length_downweight_alpha=0.25, max_chunk_words=400, max_chunk_chars=None, chunk_overlap_words=40, folder_weights=None, fts_weights=None, embedding_provider=None, ollama_host='http://localhost:11434', openai_api_key=None, voyage_api_key=None, voyage_model='voyage-4', ollama_model='nomic-embed-text', ollama_cpu_only=False, openai_base_url='https://api.openai.com/v1', openai_embedding_model='text-embedding-3-small', fastembed_model='BAAI/bge-small-en-v1.5', fastembed_cache_dir=None, embed_context=False, embed_timeout_s=30.0, embedding_batch_size=4, git_repo_url=None, git_token=None, git_username='x-access-token', git_pull_interval_s=600, git_push_delay_s=30.0, git_commit_name='markdown-vault-mcp', git_commit_email='noreply@markdown-vault-mcp', git_commit_name_claim=None, git_commit_email_claim=None, git_lfs=True, file_watcher=True, file_watcher_debounce_s=2.0, file_watcher_root_floor=True, github_webhook_secret=None, gitlab_webhook_signing_token=None, gitlab_webhook_secret_token=None, summarize_provider=None, summarize_openai_api_key=None, summarize_openai_base_url=None, summarize_openai_model='gpt-5-mini', summarize_max_tokens=8192, summarize_max_notes=50, summarize_max_input_chars=200000, summarize_timeout=120.0, transfer=TransferConfig(), jobs=JobsConfig()) dataclass

Domain config for Markdown Vault MCP. Compose — don't inherit.

git property

The git section assembled from the flat git_* fields.

A property rather than a composed field so the config-surface generator documents the flat fields' metadata. Construction runs GitConfig.__post_init__ validation.

indexing property

The indexing section assembled from the flat index/frontmatter fields.

embeddings property

The embeddings section assembled from the flat embedding fields.

search property

The search section assembled from the flat ranking/chunking fields.

summarize property

The summarize section assembled from the flat summarize_* fields.

sync property

The sync section assembled from the flat watcher/webhook fields.

content property

The content section assembled from the flat attachment/folder fields.

A relative prompts_folder is resolved against source_dir here, so direct construction and from_env behave identically.

__post_init__()

Validate composed domain fields. Raise ValueError when invalid.

Runs on EVERY construction path — from_env and a direct ProjectConfig(field=...) alike. That is what makes this the right home for a field invariant: env_float / env_int bounds check only the env-sourced value, never the default, so a direct construction slips past them. They also cannot express an exclusive bound (their minimum / maximum are inclusive, so "must be > 0" lets 0 through) or a cross-field rule (A requires B, mutually-exclusive pairs). All three belong here.

The dataclass is frozen=True: read fields freely, but plain assignment raises. To normalise rather than merely check, use object.__setattr__(self, "name", value).

from_env() classmethod

Load :class:ProjectConfig from MARKDOWN_VAULT_MCP_* env vars.