Skip to main content

OmniDB — MCP-native agent memory & retrieval server

A local-first, single-binary-feel agent memory and retrieval server over SQLite, exposed to AI agents through the Model Context Protocol. This is the revised v1 that came out of the August 2026 research + adversarial review (see ../OmniDB Vault/): an MCP memory/retrieval server, not a database.

  • Substrate: SQLite in WAL mode (synchronous=NORMAL, busy_timeout=5000) — one directory on disk, copyable as a unit (omnidb.db + WAL sidecars + vector index file). The single-file mandate was dropped.
  • Retrieval: BM25 (FTS5, porter tokenization) fused with dense vector search via Reciprocal Rank Fusion, then a gentle recency/frequency rerank. Hybrid retrieval runs in-process; SQLite table-valued functions (VECTOR_SIM / MEMORY_RECALL) need a native extension and are the documented upgrade path for the future Go/Rust port.
  • Vectors: hnswlib (M=16, efC=200) inner-product on L2-normalized vectors == cosine, persisted as a sidecar file; exact brute-force fallback always available. Deletions are mark-deleted.
  • Memory model: plain relational tables (episodic | semantic | procedural) — no bespoke LSM, no fixed decay religion (weights are config). Consolidation distills episodic → semantic via a configurable LLM, with an offline stub when none is set.

Quickstart

pip install -e ".[hnsw,semantic,dev]"   # hnsw/semantic extras optional; falls back gracefully
pytest
omnidb-server serve                     # MCP stdio server on $OMNIDB_HOME (default ~/.omnidb)
python -m omnidb_server serve           # equivalent
python -m omnidb_server stats

Claude Desktop / any MCP client

See examples/claude-desktop-config.example.json — includes the env vars for real (fastembed) semantics and a working HF_HOME override. Minimal version:

{
  "mcpServers": {
    "omnidb": {
      "command": "python",
      "args": ["-m", "omnidb_server", "serve"]
    }
  }
}

Tools

Tool Purpose
remember(content, kind, metadata, links) persist a memory (episodic/semantic/procedural), optional graph links
recall(query, k, kind, k_fetch) hybrid BM25+dense recall with recency/frequency rerank; pool floors at k
update_memory(memory_id, content, metadata) edit content (re-embeds + reindexes via FTS trigger) and/or merge metadata
search(sql) read-only SELECT/WITH escape hatch against SQLite
related(memory_id, max_hops, label) undirected graph walk (recursive CTE, cycle-safe, hops clamped 1-8)
forget(memory_id) / forget_many(ids) soft delete one / many
consolidate(hours) episodic → semantic distillation
stats() counts, edges, embedder/index info, dead-ratio, all file sizes

Error messages carry OMN-* codes from the original spec's taxonomy ([OMN-020] read-only violation, [OMN-021] not found, [OMN-006] dimension mismatch, [OMN-011] timeout, ...).

Configuration

Precedence: CLI flags > environment > omnidb.toml > defaults. The TOML file is looked up in the CWD and the data directory (field names mirror the config dataclass):

half_life_hours = 168
rrf_k = 60
k_fetch = 50
persist_every_ops = 64      # vector-sidecar fsync debouncing
dead_compact_ratio = 0.2    # hnsw tombstone ratio triggering rebuild-on-open

Operations

omnidb-server compact --home D:/path/to/data   # force full vector-index rebuild
python -m omnidb_server stats                  # includes pending_compaction, reconciled_at, WAL size
omnidb-server check                            # FTS integrity, index drift, orphan edges, WAL size
omnidb-server purge [--vacuum]                 # hard-delete soft-deleted rows; --vacuum reclaims space
omnidb-server export D:/backup/memories.jsonl  # dump all memories + edges to JSONL
omnidb-server import D:/backup/memories.jsonl  # restore from a JSONL dump

Configuration (environment)

Variable Default Meaning
OMNIDB_HOME ~/.omnidb data directory
OMNIDB_EMBEDDER auto auto/hashing are offline-safe (never download); fastembed opts into real semantics ([semantic] extra, ~100MB model on first run). Embedder identity is pinned per database.
OMNIDB_INDEX auto auto | hnsw | brute
OMNIDB_HALF_LIFE_HOURS 168 recency half-life for rerank
OMNIDB_RECENCY_WEIGHT / OMNIDB_FREQ_WEIGHT 0.15 / 0.05 rerank weights (RRF base is weight-free)
OMNIDB_K_FETCH 50 candidates fetched per leg before fusion
OMNIDB_RRF_K 60 RRF smoothing constant
OMNIDB_MAX_SEARCH_ROWS 500 row cap for the search tool
OMNIDB_LLM_BASE_URL / _MODEL / _API_KEY unset OpenAI-compatible endpoint used by consolidate; stub when unset. With one configured, a failed call consumes nothing (episodes stay retryable)

Benchmarking

python bench/baseline.py   # writes bench/results.md

Measures hnswlib (M=16, efC=200) recall@10 vs exact brute force across an ef sweep at 384/768 dims on clustered synthetic data (1k/10k/100k), plus the SQ8 experiment. Findings so far: at 768-dim/10k, SQ8+rerank (0.947) beats raw HNSW at ef=128 (0.837); at 100k the clustered-synthetic distribution is strongly pessimistic for graph ANN (tight clusters create hub structure), where quantized scoring + f32 rerank stays robust (0.90) but at full-scan cost (~120ms). Treat as a floor, not a forecast — re-run against your real corpus before drawing conclusions.

Encryption at rest

OmniDB is local-first and writes only to OMNIDB_HOME; it phones home to no one. For data-at-rest protection we recommend OS-level disk encryption (BitLocker / FileVault / LUKS) — that covers the stolen-disk threat model without adding a dependency or a key you must manage.

A SQLCipher swap is documented but deliberately not bundled: encrypting the SQLite file would require pysqlcipher3, whose Windows wheels for Python 3.14 are effectively unobtainable, so shipping it as an extra would break installs rather than protect them. If your threat model needs per-file encryption beyond full-disk, compile SQLCipher and point this package's connection at it — the store layer is plain sqlite3 DB-API and needs no code changes.

Limitations (v1, deliberate)

  • Single-writer process per home directory (SQLite WAL semantics). The vector sidecar is last-writer-wins: run one server per home; startup reconciliation after a crash between the DB and the index file is deferred.
  • The Python sqlite3 module cannot register virtual tables, so SQL++-style TVFs arrive with the native port; until then hybrid queries go through the tools.
  • Hashing embedder matches surface forms, not paraphrases — install fastembed for real semantics. Embedder identity is pinned per database; switching requires a fresh home.
  • No QPS targets: this serves one agent session locally. Gates are interactive latency, cold start, and RAM at scale (re-baselined empirically at true embedding dimensions, not SIFT-128 folklore).

Metadata

Release files for omnidb-server 0.1.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for omnidb-server 0.1.2
File Size Uploaded Provenance
omnidb_server-0.1.2.tar.gz 92.1 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for omnidb-server 0.1.2
File Interpreter ABI Platform
omnidb_server-0.1.2-py3-none-any.whl Python 3 none any Details

Total release size: 191.9 kB

Release files / omnidb_server-0.1.2.tar.gz

Download URL omnidb_server-0.1.2.tar.gz
Size 92.1 kB
Tags Source
SHA-256 checksum
How to use checksums
6c857ed167234324b754b0bdf0fa4e2c7676702f345220c5635ee57266444a0b
BLAKE2b-256 checksum
How to use checksums
7ee6ae9188945ae1728f215b493c0b97e098b722999869454194fbf6e2e288c4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.4

Release files / omnidb_server-0.1.2-py3-none-any.whl

Download URL omnidb_server-0.1.2-py3-none-any.whl
Size 99.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
2ac77c8a5a8ec5ff994e4458bcac960ade418fa748d64e5d5dc125e016e1162c
BLAKE2b-256 checksum
How to use checksums
f960435b79f3c307ab0f46d8ec9a8e26ba4cac83bb4c88f11d7a44f4cf8eb076
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.4

Security for omnidb-server 0.1.2

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page