mushroomdb

MCP serverDatabases & data

Embedded graph database for agents: declare association rules once, edges maintain themselves.

Unavailable. This server has no hosted endpoint yet, so ahel can't serve it.

Add to setup to save this item as a reference. ahel cannot run it, and signing in will not install it.

Getting started

  1. Save this item in Your setup as a reference.
  2. Read the source or reference documentation for its setup requirements. Saving it here does not connect it to your AI.
  3. Check this page for availability before trying to install it through ahel.

From the project's README

As published by matthewsherlin/mushroomdb in README.md.

The graph that stays true — and knows who's allowed to see it.

mushroomdb is the data layer for agents that reason over entities. It is an embedded Rust graph database in which a relationship is a schema declaration: write a rule once, and every write derives, maintains and retracts the matching edges, each one carrying the rule, the score and the values that produced it. An agent reaches it over MCP — fifteen tools on an entity store — or you embed it as a Rust library, a Python module, or a sidecar beside your own service. Four questions are what it exists for: why are these two related (explain_association, answered with the evidence rather than an assertion), what did that look like then (edges_at, the edges a node had at any past commit), what would this change do (what_if, computed without writing anything), and who may see it (query with a role, so one graph answers differently per caller). Local-first: a directory on disk, no account, no endpoint, no model call in the write path unless you enable embeddings.

ingest-git stays supported as a data source: commits, pull requests, files and authors become entities with rule-derived relationships, which is what makes a ticket↔commit link a rule rather than a script.

Deprecated in 0.6.4: the code-graph door — the explore, map, context, impact, owners, why and sync tools, the three grep/edit hooks, and the plugin's coding-assistant positioning. It still works and is still tested; it is removed in 0.7. See Deprecations.

Pre-1.0 alpha — APIs and formats may change between minor versions.

Docs · Changelog · Issues

Quick start

npx mushroomdb install --db ./memory

One command writes the /mushroom skill, an MCP server listing the fifteen-tool association surface, and the session hooks. Then a worked flow, four tool calls:

upsert_entity  →  create_rule  →  find_similar  →  explain_association
  (store)           (link)           (recall)          (explain)

Full tool reference: docs/site/mcp.md.

  • Live, not a snapshot. One SET on a property re-derives the matching edges — added, scored and retracted — before the write closes. The SET in the GIF above is that one write.
  • Retracts instead of going stale. A property drifting out of a rule's predicate doesn't leave a stale edge behind; the engine retracts it in the same write that caused the drift.
  • Explains any link. explain_association names the rule, the score, and the values the two entities actually share, so "why are these two related?" has an answer your assistant can quote instead of a guess.
  • Knows who's allowed to see it. Pass a role or a mask with a query and the same graph answers differently per caller; write statements are rejected on masked queries.
  • Answers what it said last week. edges_at returns the edges a node had at a past commit; mushroomdb asof ./db --commit 5 --query "…" replays the WAL to that commit, derived edges included.

Where it fits

What it is

  • An embedded, single-binary graph database with a rule engine that maintains edges for you.
  • A 27-tool MCP server — fifteen listed on an entity store, three on a store built by ingest-git — plus a /mushroom skill and a Claude Code plugin.
  • Safe for several processes at once: one writer at a time behind an advisory LOCK file, any number of readers, and every handle picks up a peer's commits by refresh() rather than reopening — so a running serve, an editor hook, a git hook and a CLI command can share one store. docs/site/concurrency.md
  • Local-first: your data stays on disk, no cloud service, no model call in the write path unless you enable embeddings.

What it isn't

  • Not a hosted memory service — there is no account, no endpoint, nothing to sign up for.
  • Not a vector database. Vector predicates and HNSW are built in; bring your own embeddings.
  • Not a Postgres replacement. Single writer, no interactive transactions, memory-first storage.

Deprecations

What "deprecated" means here. It still works in 0.6.4, it is still tested on every release, and nothing is removed. It is no longer promoted — not on this page, not in the skill's task rules, not in the plugin's description — its documentation page opens with a notice, and an install that turns one of the hooks on prints a deprecation line. It is removed in 0.7. The migration is nothing to do, unless you relied on the specific thing named below.

DeprecatedIf you relied on it
The tools explore, map, context, impact, owners, why, syncPin mushroomdb@0.6.x. Nothing on the entity surface replaces them: they answer from a repository graph, which 0.7 stops shipping tools for. ingest-git and query keep answering the same facts as Cypher.
The hooks --intercept-grep, --impact-before-edit, --enrich-grepRe-run install without the flag; the hook comes out the way any other manifest entry does. Nothing replaces them.
The plugin's coding-assistant positioningThe plugin is not going away. Its description and skill now lead with entity memory.
Code-suite benchmark runspython3 benchmarks/agent-tasks/run.py --suite code still runs. No further runs are committed; the committed summaries stay as the record.

Why, measured. Across 240 cells — arms stock / installed / invoked / cli × 3 reps × 20 tasks over two repositories — the invoked graph arm scored 0.924 against stock's 0.927 (paired difference -0.0035 [-0.0112, 0.0017]) and cost $0.2713 against $0.2267 (+0.04463 [+0.01312, +0.07471], about +20%), and the two installed-but-not-invoked arms made 0 graph calls in 120 sessions: results/20260910T000418Z. An agent holding grep neither needs a graph for those questions nor chooses one. What the engine is for is measured separately, on the association suite, and reported under Benchmarks.


The differentiator

Most graph databases require you to create edges manually or run a batch similarity script after each load. mushroomdb makes edge creation a schema declaration. A rule like "connect every Person to every Org whose skills list overlaps theirs by at least 50%" is written once:

db.create_rule(RuleDef {
    name: "skill_fit".into(),
    src_label: "Person".into(),
    dst_label: "Org".into(),
    predicate: Predicate::Overlap { field: "skills".into(), min: 0.5 },
    edge_type: "FIT".into(),
    weight_prop: Some("score".into()),
    max_edges: Some(5), // keep the 5 best-matching Orgs per Person (top-k per source)
}).expect("rule");

After that, every insert_node and set_prop evaluates the rule incrementally. The engine writes the edge, stores the Jaccard score, and retracts the edge if the properties later diverge — without any manual work.

Watch it live — a Cypher SET changes one property, the founded_within rule fires, and new scored edges appear in the bundled explorer:

Open the Rules panel, and the Why slide-over shows the exact predicate arithmetic behind every derived edge:

Predicates

Six predicate kinds ship today. They compose via All(...) (AND, score = min) and Any(...) (OR, score = max), nested up to depth 4.

PredicateWhat it tests
KeyMatchFK equality — source field matches destination key
FieldEqualExact match on a named scalar field (string, int, float, bool)
OverlapJaccard on list-valued fields, min threshold
NumericWithinAbsolute numeric difference within a tolerance; score = `1 -
GeoRadiusHaversine distance on [lat, lon] fields within km; score = 1 - dist/radius
VectorSimilarCosine similarity on float arrays, min threshold

Auto-FK: fields ending in _id whose values match existing node keys get KeyMatch rules created automatically at ingest time. VectorSimilar accepts approximate: true to switch candidate selection to in-tree HNSW (per-query recall floors min 0.90 / mean 0.95, measured 1.0 / 1.0 at 5k nodes / dim 1536, fixed-seed probe). Full reference: docs/site/rules.md.

Built on the same engine

  • Live subscriptions. subscribe_rule (Rust) and GET /subscribe (WebSocket) stream EdgeFired / EdgeRetracted the moment they hit the WAL — not polled, not batched. Bounded 65,536-event queue; slow consumers get a Lagged { missed: N } marker instead of a disconnect. docs/site/subscriptions.md
  • Rule attribution across time. Every derived edge writes a HISTORY-MARKER WAL record carrying the rule name, so edge_history, node_history, and was_linked answer which rule created a link and at which commit. GraphDb::open_at(&dir, 5) replays to a past commit, derived edges included; out-of-range commits return CommitOutOfRange, never wrong data. docs/site/timetravel.md
  • Materialized views. Degree counts and neighbor aggregates (sum/avg/min/max) maintained incrementally on every edge change — no cron, no triggers, no stale caches. docs/site/views.md
  • Rule suggestions. db.suggest_rules() (or mushroomdb suggest ./db) profiles your data and ranks candidate rules with estimated edge counts and rationale. Seeded sampling, so the same database always returns the same suggestions. No rule is ever applied automatically. docs/site/suggest.md

Agent memory

Graph structure captures the shape of real knowledge — entities, associations, similarity, and lineage — and rule-derived edges keep those associations fresh as new facts arrive.

  • Entities map to nodes (Person, Document, Project, Concept, …).
  • Associations are edges derived from data: cosine similarity on embeddings, shared field values, FK relationships, geographic proximity. Declare a rule once; every write maintains the matching edges without agent-side bookkeeping.
  • Recall has three modes: find_similar by query vector (HNSW when available, brute force otherwise); find_similar by key (neighbors along a rule-derived edge type); query for structured Cypher recall. hybrid_search fuses fulltext and vector results via Reciprocal Rank Fusion.
  • Explanations are built in: explain_association shows which rules and scores produced each link, so an agent can cite evidence instead of asserting a conclusion.
  • Node masks are the ACL primitive: pass mask: [key1, key2, …] to query to restrict the visible node set. Write statements are rejected on masked queries. docs/site/masks.md
  • Schema-as-code: mushroomdb schema apply <dir> <schema.json> idempotently applies rules, views, and fulltext indexes, printing a created/updated/unchanged diff.

Minimal workflow (four tool calls):

upsert_entity  →  create_rule  →  find_similar  →  explain_association
  (store)           (link)           (recall)          (explain)

Fourteen task tools answer a question in prose in one call. Seven answer on any store; seven are the deprecated code door. They are what the skill reaches for, and what tools/list shows first:

ToolPurpose
exploreDeprecated (0.7). One tool to find: context, impact, history or all for one target in one reply, capped by a token budget
mapDeprecated (0.7). The repository in one screen: size, last sync, clusters, key files, owners, hot files
contextDeprecated (0.7). One file or symbol from every side: where it is as path:start-end, signature, callers, callees, importers, co-change partners, commits, notes. full adds the body
impactDeprecated (0.7). What changing these files reaches: partners with scores, importers, symbols other files call, owner. Defaults to the working tree's diff
ownersDeprecated (0.7). Top author and share, who else knows the file, last touch, the split by quarter
whyDeprecated (0.7). Every rule edge between two nodes with its evidence, or the shortest path when there is none
explain_associationWhy two entities are associated: every rule-derived edge between them, with the rule, the score, the predicate it matched, and the values the two actually share
node_edgesEvery edge on one node, grouped by edge type, with the rule and score behind each. all_of: [types] answers with the partners linked by every one of them, as keys; edge_type, label, direction and limit narrow it further
neighborhoodAt depth 1 the same grouped listing; above 1 the breadth-first (key, label, depth) table
edges_atThe edges a node had at one 0-based WAL commit — the graph as it was, not as it is — with the same all_of / edge_type / label / direction filters
what_ifThe derived edges a property change would lose and gain, computed without writing anything. edge_type prints both sides as partner keys
recallOne pointer per hit — path:line symbol — first doc line — for the identifiers in a topic
rememberWrite a note into the graph and return its key
syncDeprecated (0.7). Bring the store up to date: commits since the last sync, then the dirty working tree

Each of the fourteen also takes json: true, which answers with the raw report instead of the rendered digest.

The thirteen graph tools reach the store directly. Their descriptions are prefixed Advanced: in tools/list, so an assistant knows which surface is the front door. The default listing follows the store: a store built by ingest-git lists three tools in all — explore, query and stats — and any other store lists fifteen, the association surface: query (with an optional role), explain_association, neighborhood, node_info, node_edges, was_linked, edges_at, what_if, node_history, edge_history, find_similar, hybrid_search, remember, recall and stats. All 27 stay served either way — the listing decides what a session can call, not what the server answers — and mushroomdb mcp <db> --all-tools lists the whole set:

ToolPurpose
upsert_entityInsert or update a node by key (no existence check needed)
ingest_jsonBatch-ingest nodes of one label from a JSON array
create_ruleDeclare a derivation rule; backfills existing nodes in the same commit (a vector index over 2,048 vectors builds in slices, and the edges arrive in a later commit)
find_similarFind similar nodes by query vector (HNSW) or by derived edge traversal
hybrid_searchRRF over fulltext + vector results
explainThe rules and scores that link two nodes, as JSON — explain_association above answers the same question in prose
queryCypher query (read or write); pass mask for an ACL-scoped read, or role to answer as one role from the store's roles.json
node_infoReturn a node's key, label, and properties
statsLive node, edge, and rule counts
node_historyWAL change history for a node (archives included; a snapshot --truncate ends the reach)
edge_historyAdd/retract lifecycle for edges between two nodes, with rule attribution
was_linkedPoint-in-time edge check: was an edge active at a given commit?
rename_nodeRename a node's key; old_key, new_key

Full walkthrough, tool reference, and Claude Desktop setup: docs/site/mcp.md. Skill, plugin, and hook details: docs/site/skill.md.


Install options

claude plugin install mushroom@mushroomdb   # after `claude marketplace add MatthewSherlin/mushroomdb`
npx mushroomdb install            # skill + MCP server + hooks, no toolchain needed
cargo install mushroomdb-cli      # `mushroomdb` binary from crates.io (no embedded UI)
cargo add mushroomdb              # embedded Rust library
pip install mushroomdb            # Python bindings

install writes an MCP entry that runs npx -y mushroomdb@<version>, so the assistant needs nothing installed globally and nothing is copied into your home directory. Point it at a local build with --command <path>. mushroomdb doctor verifies the result end to end — config entry, store, lock, hooks, git hooks, and a real stdio handshake with the configured command.

To see the bundled explorer, write a demo graph and serve it:

mushroomdb demo ./db
mushroomdb serve ./db

Open http://127.0.0.1:8080/. The demo graph has 10 Orgs, 20 Projects, 30 People, and 334 edges — 304 of them derived by seven rule sets. When a token is configured, open http://host:8080/?token=…. Building the binary with the UI embedded, Docker, and the install.sh script are covered in CONTRIBUTING.md.

Role-bound tokens limit a caller to a named subset of nodes. Define roles in schema.json under the roles key (each role has a label selector list), then pass --role-token TOKEN:ROLE (repeatable) when starting the server, or set MUSHROOMDB_ROLE_TOKENS="tok1:role1,tok2:role2". A role token receives only the nodes matching its label selectors — read endpoints return rows filtered to the visible set; write, subscription, and analytics endpoints return 403. Unknown token or role name: 401. The never-widen invariant is enforced in the server: a client-supplied mask is always intersected with the role mask. The MCP interface (mushroomdb mcp) is a stdio JSON-RPC server for local agent use and is not subject to bearer-token or role enforcement.


CLI reference

Shortened here. Read the whole README on GitHub.

Signals

GitHub stars
5
Forks
1
Last commit
Sep 2026
Weekly_downloads
210 weekly_downloads
Advanced
Delivery
mushroomdb MCP server → your ahel connector (mcp.ahel.ai) → your AI.
Item type
mcp-server
Key
io-github-matthewsherlin-mushroomdb
Source
github.com/matthewsherlin/mushroomdb