Local-first MCP server that exposes a Markdown vault through MCP.
Project description
Datacron
Local MCP server to query and maintain a Markdown vault from Claude Desktop or Claude Code, without sending the whole vault into the context.
Français | English
Datacron indexes a folder of Markdown notes, exposes a local MCP server, then returns the
relevant notes or chunks to the client instead of a full dump. The vault stays an ordinary
Markdown folder: Datacron only adds a .datacron/ sidecar for the index, logs, internal
ULIDs, history, and the operation journal.
What is in place
| Surface | Current state |
|---|---|
| Vault reading | list_notes, get_note, resources datacron://vault/map, vault/info, policy/active |
| Search | SQLite FTS5/BM25, FR↔EN query expansion, temporal re-rank, ripgrep via search_regex |
| Local graph | Wikilinks and backlinks via get_backlinks |
| Writing | 5 confined, reversible tools, disabled by default without DATACRON_WRITE_PATHS |
| Index | datacron index incremental, datacron reindex full, automatic repair on read |
| Evaluation | datacron eval over the real MCP pipeline: recall@k, MRR, nDCG, freshness, latency, and payload tokens |
| Guided setup | datacron setup: init + index + MCP registration in one command |
| Clients | Auto-detect and register via datacron setup --client all: Claude Desktop, Claude Code, Cursor, Gemini CLI, Codex CLI, Windsurf, VS Code |
| Distribution | Windows installer (Datacron-Setup.exe), standalone executable (PyInstaller) with no Python required, or installation from source |
Local measurement of the tool/impl pipeline actually received by the agent, 19 questions,
8k-token / 20-result configuration, July 17, 2026:
recall@5 0.89
recall@10 0.95
recall@20 0.95
MRR 0.73
nDCG@10 0.79
latency p50 57 ms
latency p95 276 ms
payload tokens 90567
The tool now matches the raw store at recall@5 (0.89): the previous gap came from globally
comparing scores produced by separate AND and OR queries, not from the response budget or a
BM25 limitation. Repair-on-read throttling brings its own p50 down to 0.009 ms; the first
full sweep of the session remains visible in p95. The golden set does not yet contain a
forbidden_paths case and the vault has no indexed supersedes relationship.
Installation
Windows: one double-click installer
The easiest way on Windows: download Datacron-Setup.exe from the
latest Release, double-click it,
and pick your vault. No Python, no terminal, no administrator rights; Datacron registers
itself with your AI clients automatically. Full guide:
Windows installation.
From source
From a clone of the repository:
python -m pip install -e ".[dev]"
Or, to install only the application:
python -m pip install -e .
Runtime prerequisites:
- Python 3.11+
ripgrepavailable on thePATHforsearch_regex- a folder of Markdown notes
- Claude Desktop or another stdio MCP client
Quick start
The easy path - one command detects your AI clients, initializes the vault, indexes it, and registers Datacron everywhere:
datacron setup # interactive; add --yes for all defaults
See the installation guide for options (--client, --scope, writing,
durability). Or step by step:
datacron init /path/to/vault
datacron index --vault /path/to/vault
datacron status --vault /path/to/vault
datacron mcp install --client claude-desktop --vault /path/to/vault
Restart the client (e.g. Claude Desktop) after installation.
To run the server manually:
datacron mcp serve --vault /path/to/vault
The direct script entry used by the installer is also available:
datacron-mcp
datacron-mcp reads the vault from DATACRON_VAULT_ROOT.
Configuration
datacron init creates .datacron/VAULT.yaml. That file can carry vault-local
configuration, notably query expansion:
query_expansion:
supervision: [monitoring]
sauvegarde: [backup]
restauration: [restore]
chiffrement: [encryption]
sécurité: [security]
validité: [validity]
certificat: [certificate]
Useful environment variables:
| Variable | Default | Role |
|---|---|---|
DATACRON_VAULT_ROOT |
current directory or --vault |
vault served by the server |
DATACRON_READ_PATHS |
empty | read allowlist; the Claude Desktop installer sets it to the vault |
DATACRON_WRITE_PATHS |
empty | write allowlist; empty = write tools disabled |
DATACRON_MAX_RESULT_COUNT |
20 |
maximum number of results returned |
DATACRON_MAX_RESULT_TOKENS |
8000 |
token budget for search results |
DATACRON_REPAIR_MIN_INTERVAL_SECONDS |
30 |
minimum interval between repair-on-read sweeps; 0 = every read |
DATACRON_GET_NOTE_MAX_TOKENS |
25000 |
budget for get_note(format="full") |
DATACRON_CHUNK_MAX_TOKENS |
1024 |
target maximum chunk size |
DATACRON_RIPGREP_PATH |
rg |
ripgrep binary |
Path lists use the OS separator (: on Unix, ; on Windows).
Writing
Writes are deliberately OFF by default. Without DATACRON_WRITE_PATHS, write tools return a
clear error and create no file.
To enable writing to a specific subfolder:
$env:DATACRON_VAULT_ROOT = "G:\_DATA"
$env:DATACRON_READ_PATHS = "G:\_DATA"
$env:DATACRON_WRITE_PATHS = "G:\_DATA\_memory"
datacron mcp serve --vault G:\_DATA
Available write tools:
create_note_ai: creates a typed Markdown note, without overwrite.append_journal: adds an entry under a heading of an existing note.set_frontmatter: updates lifecycle fields without modifying the Markdown body.patch_note_section: replaces the content under an existing heading with CAS control.revert_note: restores the exact bytes of a version kept in history.
Guarantees:
- strict confinement within
DATACRON_WRITE_PATHS - atomic overwrite via temporary file +
os.replace - content-addressed history before modifying an existing note
reconcile()after write to make the note immediately searchable- local audit log
Concurrent multi-machine mode is not supported for writes: keep a single-writer rule on the vault.
MCP Tools
Reading
| Tool | Description |
|---|---|
list_notes |
returns a paginated list, filterable by folder and tags, with ULID, title, tags, aliases, and dates |
get_note |
reads a note by ULID, chunk id, or relative path, as paginated content, chunk, or heading outline |
search_text |
runs a BM25 search on the FTS5 index with ranked snippets and stale notes demoted by default |
search_regex |
runs a regex search via ripgrep and resolves the found lines to indexed chunks |
get_backlinks |
returns chunks whose wikilinks target a ULID or a resolved alias |
Writing
| Tool | Description |
|---|---|
create_note_ai |
creates a new typed _memory note, confined to allowed paths, without overwrite and with a durable journal |
append_journal |
adds a Markdown entry under a heading, with confinement, exact history, and atomic write |
set_frontmatter |
updates only the lifecycle fields and the updated date, preserving the Markdown body |
patch_note_section |
replaces the content of an existing heading with CAS, exact history, and preservation of other sections |
revert_note |
restores a note from its content-addressed history; the operation stays durable, reversible, and audited |
Operational
| Tool | Description |
|---|---|
get_health |
returns the real state of index freshness, integrity, checksum, durability, and invariants |
get_note_history |
lists the committed operation metadata of a note without reading historical content or modifying the journal |
audit_query |
queries operation metadata by period, tool, or note without modifying the journal or the vault |
Advisory (experimental)
| Tool | Description |
|---|---|
contradiction_scan |
live, deterministic, bounded scan of contradictions/refinements between sections; proposes and confirms an explicit CAS call read-only, without ever writing automatically |
MCP resources:
datacron://vault/mapdatacron://vault/infodatacron://policy/active
Search
search_text combines several signals:
- FTS5/BM25 for the base lexical score
- FR↔EN query expansion configured in
VAULT.yaml - conservative temporal re-rank:
- a note referenced in another note's
supersedesis strongly demoted confidence: lowandconfidence: needs_verificationapply a light penaltyinclude_superseded=truebrings historical notes back up
- a note referenced in another note's
search_regex stays literal: it applies neither query expansion nor temporal re-rank.
Privacy and security
- Datacron does no telemetry.
- Datacron calls no cloud LLM.
- The MCP client, for example Claude Desktop, may send the chunks that Datacron returns to its provider. Datacron does not send it the full vault.
- Content returned to clients is wrapped in
<vault_content>...</vault_content>. - Results are bounded by count and by token budget.
- Filesystem access is confined by
DATACRON_READ_PATHSandDATACRON_WRITE_PATHS. - MCP operations are audited in the local logs.
CLI commands
datacron setup # guided path: init + index + client config
datacron setup --yes # all defaults, no prompts
datacron init /path/to/vault
datacron status --vault /path/to/vault
datacron index --vault /path/to/vault
datacron reindex --vault /path/to/vault
datacron scrub-init --vault /path/to/vault
datacron scrub --vault /path/to/vault
datacron eval --questions examples/eval-questions.example.yaml --vault /path/to/vault
datacron eval --questions local/golden.yaml --vault /path/to/vault --save-baseline
datacron eval --questions local/golden.yaml --vault /path/to/vault --compare --json
datacron mcp serve --vault /path/to/vault
datacron mcp install --client claude-desktop --vault /path/to/vault
Current limitations
- No vector search / embeddings: the spike is ruled out on the current golden because tool-level recall@5 at 0.89 matches the BM25 store. Re-evaluate if an expanded golden falls below 0.85 with the same evaluation.
- No autonomous agent: the MCP client orchestrates.
- No GUI.
- No concurrent multi-machine writes.
- Client detection in
datacron setupis best-effort (a config directory or a binary on thePATH); an install in a non-standard location may be missed and can then be configured by hand.
Documentation
Full index: docs/en/index.md | Index français.
To get started:
Technical references:
- Vault conventions (SPEC)
- Architecture and public surface
- Settled decisions v2.1
- Security boundary
- Integrity scrubber
- Operational health and durability
- Freshness contract
Development
python -m pip install -e ".[dev]"
ruff check .
ruff format --check .
mypy
pytest
License
Copyright 2026 Julien Bombled.
Licensed under the Apache License, Version 2.0.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file datacron-2026.718.3.tar.gz.
File metadata
- Download URL: datacron-2026.718.3.tar.gz
- Upload date:
- Size: 164.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
669d4559c0d15d8b24ce3422b8cd85f4cc66e73849d97269d2b7427746f4f0a7
|
|
| MD5 |
23986b5012b97aced6a6686657f7a79a
|
|
| BLAKE2b-256 |
6c2ec9eeec55ae9ba0fa50d6e3b8093a433e638e691ffc7dceaf529607a4bd7b
|
Provenance
The following attestation bundles were made for datacron-2026.718.3.tar.gz:
Publisher:
publish-pypi.yml on VBlackJack/Datacron
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
datacron-2026.718.3.tar.gz -
Subject digest:
669d4559c0d15d8b24ce3422b8cd85f4cc66e73849d97269d2b7427746f4f0a7 - Sigstore transparency entry: 2194790272
- Sigstore integration time:
-
Permalink:
VBlackJack/Datacron@4951ff827fc6c00022534e29b8fec11fc919f3fd -
Branch / Tag:
refs/tags/v2026.0718.03 - Owner: https://github.com/VBlackJack
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@4951ff827fc6c00022534e29b8fec11fc919f3fd -
Trigger Event:
push
-
Statement type:
File details
Details for the file datacron-2026.718.3-py3-none-any.whl.
File metadata
- Download URL: datacron-2026.718.3-py3-none-any.whl
- Upload date:
- Size: 203.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8aad1d3170fd72a9c9a52648311d5e252eff3301d223321fb69e0cee936dae22
|
|
| MD5 |
290a9a28795bd1ab836a752ee2af6252
|
|
| BLAKE2b-256 |
335e86174ba3775a521d631fb74dd8aebfb18d1e6b468ab262aefb20999b037d
|
Provenance
The following attestation bundles were made for datacron-2026.718.3-py3-none-any.whl:
Publisher:
publish-pypi.yml on VBlackJack/Datacron
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
datacron-2026.718.3-py3-none-any.whl -
Subject digest:
8aad1d3170fd72a9c9a52648311d5e252eff3301d223321fb69e0cee936dae22 - Sigstore transparency entry: 2194790274
- Sigstore integration time:
-
Permalink:
VBlackJack/Datacron@4951ff827fc6c00022534e29b8fec11fc919f3fd -
Branch / Tag:
refs/tags/v2026.0718.03 - Owner: https://github.com/VBlackJack
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@4951ff827fc6c00022534e29b8fec11fc919f3fd -
Trigger Event:
push
-
Statement type: