Developer Documentation
Overview
MentisDB is a standalone Rust crate available on crates.io. Add it to your project:
mentisdb = "0.9.1"The crate provides the full memory engine, skill registry, storage adapter interface, agent registry, and optional HTTP server stack (MCP + REST + dashboard) behind the server feature flag.
Full API Reference
The complete, generated API documentation is hosted on docs.rs:
docs.rs/mentisdb
Full rustdoc for all public types, traits, functions, and modules. Includes MentisDb, Thought, ThoughtInput, ThoughtQuery, StorageAdapter, SkillRegistry, BinaryStorageAdapter, and the HTTP server.
MCP Server
MentisDB ships a built-in MCP (Model Context Protocol) HTTP server. Enable it with the server feature. All MentisDB operations are exposed as MCP tools over JSON-RPC 2.0 via HTTP, making it compatible with any MCP-capable AI tool. The canonical onboarding path is not a separate URL: it happens during the MCP initialize call via startup instructions plus the embedded resource mentisdb://skill/core exposed through resources/list and resources/read.
Default HTTP endpoint: http://127.0.0.1:9471 — HTTPS endpoint: https://127.0.0.1:9473.
All 37 MCP Tools
| Tool | Description | Key Parameters |
|---|---|---|
mentisdb_bootstrap | Create a chain if needed and write one bootstrap checkpoint when it is empty | chain_key,content,concepts,importance |
mentisdb_append | Append a durable semantic thought with optional tags, concepts, refs, scope, and signature metadata | chain_key,thought_type,content,agent_id,tags,concepts,scope,importance,confidence |
mentisdb_append_retrospective | Append a guided retrospective memory to prevent future agents from repeating a hard failure | chain_key,content,concepts,refs,importance |
mentisdb_search | Search thoughts by semantic filters, identity filters, time bounds, and scoring thresholds | chain_key,text,thought_types,roles,agent_ids,since,until,min_importance,min_confidence |
mentisdb_lexical_search | Return flat ranked lexical matches with explainable term and field provenance | chain_key,text,thought_types,limit,offset |
mentisdb_ranked_search | Return flat ranked results with lexical, graph-aware, or heuristic score breakdowns. Supports point-in-time queries and memory scope filtering | chain_key,text,as_of,scope,enable_reranking,rerank_k,concepts_any,roles,limit |
mentisdb_context_bundles | Return seed-anchored grouped support context beneath the best lexical seeds | chain_key,text,as_of,scope,graph,limit |
mentisdb_list_chains | List known chains with version, storage adapter, counts, and storage location | chain_key |
mentisdb_merge_chains | Merge all thoughts from a source chain into a target chain, then permanently delete the source | source_chain_key,target_chain_key |
mentisdb_branch_from | Create a new chain diverging from a thought on an existing chain. Searches on the branch transparently include ancestor results | source_chain_key,branch_chain_key,branch_thought_id |
mentisdb_list_agents | List the distinct agent identities participating in one chain | chain_key |
mentisdb_get_agent | Return one full agent registry record including status, aliases, description, keys, and per-chain activity metadata | agent_id,chain_key |
mentisdb_list_agent_registry | Return the full per-chain agent registry | chain_key |
mentisdb_upsert_agent | Create or update a registry record before or after an agent writes thoughts | agent_id,display_name,agent_owner,description,status,chain_key |
mentisdb_set_agent_description | Set or clear the description stored for one registered agent | agent_id,description,chain_key |
mentisdb_add_agent_alias | Add a historical or alternate alias to a registered agent | agent_id,alias,chain_key |
mentisdb_add_agent_key | Add or replace one public verification key on a registered agent | agent_id,key_id,algorithm,public_key_bytes,chain_key |
mentisdb_revoke_agent_key | Revoke one previously registered public key | agent_id,key_id,chain_key |
mentisdb_disable_agent | Disable one agent by marking its registry status as revoked | agent_id,chain_key |
mentisdb_recent_context | Render recent thoughts into a prompt snippet for session resumption | chain_key,last_n |
mentisdb_memory_markdown | Export a MEMORY.md-style Markdown view of the full chain or a filtered subset | chain_key,agent_ids,thought_types,roles,since,until,limit |
mentisdb_import_memory_markdown | Import a MEMORY.md-formatted Markdown document into a target chain | markdown,default_agent_id,chain_key |
mentisdb_get_thought | Return one stored thought by stable id, chain index, or content hash | thought_id,thought_index,thought_hash,chain_key |
mentisdb_get_genesis_thought | Return the first thought ever recorded in the chain, if any | chain_key |
mentisdb_traverse_thoughts | Traverse the chain forward or backward in append order from a chosen anchor, in chunks, with optional filters | chain_key,anchor_id,anchor_index,anchor_hash,direction,chunk_size,thought_types,roles,since,until |
mentisdb_skill_md | Return the official embedded MENTISDB_SKILL.md Markdown file | (none) |
mentisdb_list_skills | List versioned skill summaries from the skill registry | chain_key |
mentisdb_skill_manifest | Return the versioned skill-registry manifest including searchable fields and supported formats | (none) |
mentisdb_upload_skill | Upload a new immutable skill version from Markdown or JSON | agent_id,skill_id,content,format,signing_key_id,skill_signature,chain_key |
mentisdb_search_skill | Search skills by indexed metadata such as ids, names, tags, triggers, uploader identity, status, format, schema version, and time window | chain_key,text,skill_ids,names,statuses,since,until,limit |
mentisdb_read_skill | Read one stored skill as Markdown or JSON. Responses include trust warnings for untrusted or malicious skill content | skill_id,version_id,format,chain_key |
mentisdb_skill_versions | List immutable uploaded versions for one skill | skill_id,chain_key |
mentisdb_deprecate_skill | Mark a skill as deprecated while preserving all prior versions | skill_id,reason,chain_key |
mentisdb_revoke_skill | Mark a skill as revoked while preserving audit history | skill_id,reason,chain_key |
mentisdb_head | Return head metadata, the latest thought at the current chain tip, and integrity state | chain_key |
mentisdb_register_webhook | Register a webhook to receive HTTP POST notifications when thoughts are appended. Delivery is fire-and-forget with exponential backoff retries (up to 5 attempts) | chain_key,url,event_types |
mentisdb_list_webhooks | List all registered webhooks | chain_key |
mentisdb_delete_webhook | Remove a webhook registration by its UUID | webhook_id,chain_key |
JSON-RPC Request/Response Example
MCP uses JSON-RPC 2.0 over HTTP. Send a POST to the MCP endpoint:
POST / HTTP/1.1
Host: 127.0.0.1:9471
Content-Type: application/json
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "mentisdb_append",
"arguments": {
"chain_key": "default",
"agent_id": "assistant",
"thought_type": "Insight",
"content": "Memory deduplication triggers when Jaccard similarity exceeds threshold",
"importance": 0.7,
"confidence": 0.9,
"tags": ["feature:dedup"],
"concepts": ["memory-dedup", "jaccard-similarity"]
}
}
}
// Response:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"content": [
{
"type": "text",
"text": "Thought appended: a1b2c3... (index 42)"
}
]
}
}MCP HTTP Ports
The MCP server listens on two ports:
http://127.0.0.1:9471— HTTP (unencrypted), suitable for local developmenthttps://127.0.0.1:9473— HTTPS (TLS), recommended for production
The daemon binary (mentisdb) starts the MCP server automatically. For embedding in your own Axum app, see the docs.rs API reference for server module details.
REST API
The same daemon also serves a REST API alongside MCP. Key endpoints:
| Method | Path | Description |
|---|---|---|
POST | /v1/thoughts | Append a new thought to a chain. Supports scope parameter for memory scope tagging |
POST | /v1/search | Search/query thoughts. Supports as_of for point-in-time queries and scope for scope filtering |
POST | /v1/lexical-search | Ranked lexical search with scores and matched-term diagnostics |
POST | /v1/ranked-search | Canonical flat ranked retrieval with lexical + vector + graph-aware score breakdowns (hybrid when managed sidecars are available). Supports as_of, scope, enable_reranking, and rerank_k parameters |
POST | /v1/context-bundles | Seed-anchored grouped support context for agent reasoning and dashboard inspection. Supports as_of and scope parameters |
GET | /v1/chains | List available chain keys |
POST | /v1/chains/branch | Create a branch chain diverging from a thought on an existing chain |
POST | /v1/agents | List agents in a chain or inspect the registry |
GET | /mentisdb_skill_md | Compatibility fallback for clients that cannot use MCP resources; MCP-native clients should read mentisdb://skill/core after initialize |
POST | /v1/skills/upload | Upload a skill version |
POST | /v1/skills/read | Read a skill (latest or specific version) |
POST | /v1/recent-context | Render a compact resumption prompt for recent, important context |
POST | /v1/memory-markdown | Export a chain as MentisDB-flavored MEMORY.md markdown |
POST | /v1/head | Return current chain head metadata and the latest thought |
GET | /health | Liveness health check |
POST | /v1/bootstrap | Bootstrap a chain with an initial memory |
POST | /v1/retrospectives | Append a guided retrospective thought |
POST | /v1/thought | Retrieve a single thought by ID, hash, or index |
POST | /v1/thoughts/genesis | Retrieve the first thought in a chain |
POST | /v1/thoughts/traverse | Traverse thoughts in append order with filtering and pagination |
POST | /v1/import-markdown | Import MEMORY.md-formatted markdown into a chain |
GET | /v1/skills | List uploaded skill summaries |
GET | /v1/skills/manifest | Return the skill registry manifest with searchable fields |
POST | /v1/skills/search | Search the versioned skill registry by indexed fields |
POST | /v1/skills/versions | List immutable versions for a stored skill |
POST | /v1/skills/deprecate | Mark a stored skill as deprecated |
POST | /v1/skills/revoke | Mark a stored skill as revoked |
POST | /v1/agent | Get a single agent record by ID |
POST | /v1/agent-registry | List the full agent registry for a chain |
POST | /v1/agents/upsert | Create or update an agent record |
POST | /v1/agents/description | Set or clear an agent's description |
POST | /v1/agents/aliases | Add an alias to an agent |
POST | /v1/agents/keys | Add a verification key to an agent |
POST | /v1/agents/keys/revoke | Revoke a verification key from an agent |
POST | /v1/agents/disable | Disable (revoke) an agent |
POST | /v1/vectors/rebuild | Rebuild vector sidecar indexes for a chain |
POST | /v1/chains/merge | Merge all thoughts from a source chain into a target, then delete the source |
For MCP-native agents, prefer the streamable HTTP root at POST / and let the agent bootstrap itself from the initialize instructions and resource catalog.
For direct crate users, 0.8.0 keeps vector sidecars additive and rebuildable, but ranked search now blends lexical, graph, and managed-sidecar vector signals automatically when sidecars are enabled. The append-only chain remains canonical; sidecars are derived acceleration state.
The daemon now applies persisted managed-vector settings whenever it opens a chain. By default each chain gets the built-in local-text provider (local-text-v1), and ranked search across REST, MCP, and dashboard surfaces upgrades to hybrid scoring when that sidecar is available.
REST Example: POST /v1/thoughts (Append Thought)
POST /v1/thoughts HTTP/1.1
Host: 127.0.0.1:9471
Content-Type: application/json
{
"chain_key": "default",
"agent_id": "assistant",
"thought_type": "Insight",
"content": "Memory deduplication triggers when Jaccard similarity exceeds threshold",
"importance": 0.7,
"confidence": 0.9,
"tags": ["feature:dedup"],
"concepts": ["memory-dedup", "jaccard-similarity"],
"scope": "user",
"relations": [
{ "kind": "ContinuesFrom", "target_id": "<uuid-of-prior-turn>" }
]
}
// Response:
{
"thought": {
"id": "a1b2c3d4-...",
"index": 42,
"hash": "9f14...",
"thought_type": "Insight",
"content": "Memory deduplication triggers when Jaccard similarity exceeds threshold",
"agent_id": "assistant",
"importance": 0.7,
"confidence": 0.9,
"tags": ["feature:dedup"],
"concepts": ["memory-dedup", "jaccard-similarity"],
"created_at": "2026-04-14T12:00:00Z"
}
}REST Example: POST /v1/ranked-search
POST /v1/ranked-search HTTP/1.1
Host: 127.0.0.1:9471
Content-Type: application/json
{
"chain_key": "default",
"text": "how does memory deduplication work",
"scope": "user",
"limit": 10,
"enable_reranking": true,
"rerank_k": 50
}
// Response:
{
"results": [
{
"thought": {
"id": "a1b2c3d4-...",
"thought_type": "Insight",
"content": "Memory deduplication triggers when Jaccard similarity exceeds threshold",
"importance": 0.7
},
"score": 4.82,
"lexical_score": 1.2,
"vector_score": 3.1,
"session_cohesion": 0.4,
"rank": 1
}
],
"total": 1,
"query_time_ms": 12
}REST Example: POST /v1/context-bundles
POST /v1/context-bundles HTTP/1.1
Host: 127.0.0.1:9471
Content-Type: application/json
{
"chain_key": "default",
"text": "memory deduplication decision",
"scope": "user",
"limit": 5
}
// Response:
{
"bundles": [
{
"seed": {
"id": "a1b2c3d4-...",
"thought_type": "Decision",
"content": "Enable dedup at 0.85 Jaccard threshold",
"score": 5.1
},
"supporting": [
{
"id": "b2c3d4e5-...",
"thought_type": "LessonLearned",
"content": "Previous attempts at 0.95 threshold produced too many false negatives",
"chain_key": "default"
}
],
"children": []
}
]
}REST Example: POST /v1/webhooks/register
POST /v1/webhooks/register HTTP/1.1
Host: 127.0.0.1:9471
Content-Type: application/json
{
"chain_key": "default",
"url": "https://myapp.example.com/mentisdb-webhook",
"event_types": ["thought.append", "thought.relation.added"]
}
// Response:
{
"webhook": {
"id": "wh_abc123",
"chain_key": "default",
"url": "https://myapp.example.com/mentisdb-webhook",
"event_types": ["thought.append", "thought.relation.added"],
"created_at": "2026-04-14T12:00:00Z",
"status": "active"
}
}0.8.0 Search & Storage Improvements
MentisDB 0.8.0 introduces five major improvements to the search and storage pipeline: Porter stemming, tiered vector-lexical fusion, importance weighting, bincode hashing, and managed sidecar entries with auto_sync.
Porter Stemming (Normalizer v2)
The lexical tokenizer now applies English Porter stemming. Words like preferences → prefer and running → run now match in lexical search. Existing chains auto-reindex on first open — no manual migration step required.
Tiered Vector-Lexical Fusion
Ranked search scoring replaces the flat addition model with a tiered boost that respects the relationship between lexical and vector signals:
- Lexical = 0 and vector > 0:
vector × 60— full boost for semantic-only hits - 0 < lexical < 1.0 and vector > 0:
vector × (1 + 20 × fraction)— partial boost proportional to lexical overlap - Lexical ≥ 1.0: vector as-is — no boost, lexical dominates
Failed logins are rate-limited per-IP to prevent brute-force enumeration; the dashboard is always served over TLS so the PIN is never transmitted in the clear on a local network.
Automatic Thesaurus in Ranked Search (0.9.9)
The static thesaurus (~900 headwords + 300+ lemmas) now applies <strong>automatically by default</strong> to every ranked search query (REST <code>POST /v1/ranked-search</code>, MCP <code>mentisdb_ranked_search</code>, dashboard, and CLI). No client changes or extra parameters are required. With full embeddings this delivered the target LoCoMo-10P $R@10 = 72.6%. The expansion happens server-side via <code>apply_thesaurus_if_text</code> before BM25 scoring.
Benchmarking
MentisDB ships with two benchmark styles:
- Criterion microbenchmarks for in-process append, query, traversal, import, and skill-registry hot paths
- HTTP concurrency benchmarks for live
mentisdbwrite/read waves under concurrent client load
Run the full benchmark suite with:
make benchThis currently runs cargo bench and saves stdout to /tmp/mentisdb_bench_results.txt.
Durable vs Buffered Write Mode
Benchmark write-heavy changes in both persistence modes. They now behave differently enough that one run is not representative of the other:
MENTISDB_BENCH_AUTO_FLUSH=true— durable mode. Appends are queued to the bounded background writer and the request only returns after the writer flushes them. Concurrent appends may share a short group-commit window.MENTISDB_BENCH_AUTO_FLUSH=false— buffered mode. Appends are queued and acknowledged before the worker flushes them, trading durability for higher write throughput.
MENTISDB_BENCH_AUTO_FLUSH=true cargo bench --bench http_concurrency
MENTISDB_BENCH_AUTO_FLUSH=false cargo bench --bench http_concurrencyCriterion Baselines
Criterion benchmarks such as thought_chain and skill_registry automatically compare the current run against the saved baseline in target/criterion/. That is why the output includes messages like Performance has improved, Performance has regressed, or No change in performance detected.
time: [low mid high]— lower is betterthrpt: [low mid high]— higher is betterchange— percentage delta versus the saved baselinep < 0.05— the change is statistically meaningful
If you have changed the benchmark harness itself or want a fresh comparison, clear the old Criterion baseline before trusting the regression/improvement messages.
HTTP Concurrency Baselines
The custom http_concurrency benchmark now persists its own baselines under target/http_concurrency/ and prints delta tables on later runs. This means you no longer need to manually compare the Markdown output tables by eye.
MENTISDB_BENCH_AUTO_FLUSH=true MENTISDB_BENCH_BASELINE=durable cargo bench --bench http_concurrency
MENTISDB_BENCH_AUTO_FLUSH=false MENTISDB_BENCH_BASELINE=buffered cargo bench --bench http_concurrencyUseful environment variables:
MENTISDB_BENCH_CONCURRENCY— comma-separated client counts such as100,1000,10000MENTISDB_BENCH_AUTO_FLUSH—truefor durable group commit,falsefor buffered throughput modeMENTISDB_BENCH_BASELINE— names the saved baseline file so you can keep separate durable, buffered, nightly, or branch-specific histories
How to Read the HTTP Table
wall_ms— total time for the whole wavereq/s— throughputp50_ms,p95_ms,p99_ms— median and tail latencyerrors— non-2xx responses or transport failures
For write-path work, focus on the Write — POST /v1/thoughts table at high concurrency. Read-path changes should primarily move the Read — POST /v1/head table and the query/traversal Criterion benches.
What to Benchmark After Storage Changes
cargo bench --bench thought_chain append_single -- --noplot— strict append latencycargo bench --bench thought_chain query_by_tag -- --noplot— indexed query pathcargo bench --bench thought_chain traverse_filtered_miss_10 -- --noplot— full-scan traversal miss pathcargo bench --bench http_concurrency— live daemon concurrency behavior
A useful workflow is to measure a clean baseline on master, apply the storage change, rerun the same focused benches, and only then trust the wider make bench output.
Contributing
MentisDB is open source under the MIT license.
git clone https://github.com/cloudllm-ai/mentisdbRun the test suite:
cargo testRun benchmarks:
make bench