Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

MCP tools

Every tool mushroomdb mcp serves, with the description and the arguments the server itself sends to a client. The server answers 25 tools and lists 23 of them by default. mushroomdb mcp <db> --all-tools lists the rest.

This page is the reference. Agent memory is the guide: how to register the server, a full session from remember to explain_association, and what each answer looks like.

An argument marked required must be sent; the others have defaults the description names. Nothing here is an access boundary: role, mask and namespace ask to be answered as a caller, and the stdio server holds no one to them. Access control says where the boundary is.

Task tools

These answer a question in prose in one call, on any store, and are what the /mushroom skill reaches for. Each also takes json: true for the raw report.

explain_association

Why are A and B related — every relationship between the two keys and its evidence: the rule that derived it, its edge type, the match score, the predicate it matched on, and the values the two actually share (which specialties overlapped, which field was equal, how far apart they are). Answer from those shared values; the nodes’ full property lists name everything either one holds, not what they have in common. Both keys must already exist.

ArgumentTypeRequiredWhat it is
astringyesFirst node key.
bstringyesSecond node key.
jsonbooleannoAnswer with the report as JSON, not the rendered digest.

node_edges

What is K related to — every relationship of one node, grouped by edge type with a count, each listed edge carrying its direction, the rule that derived it, its score and the predicate it matched on. Answers ‘why is this here’ in the same call that lists it, so no follow-up explain is needed. Which partners are linked by all of these types? pass all_of and the reply is just their keys; pass one edge_type for that type’s partner keys with the rule named once. label narrows partners. With json:true the report carries listed and total, so a reply that was cut still says how much there was.

ArgumentTypeRequiredWhat it is
all_ofarray of stringnoOnly the partners linked by EVERY one of these types — the intersection, as keys.
directionone of "out", "in", "any"noWhich edges count (default any).
edge_typestringnoOnly this type: the reply is that type’s partner keys, compactly. Omit for the grouped listing over every type.
jsonbooleannoAnswer with the report as JSON, not the rendered digest.
keystringyesNode key.
labelstringnoOnly partners carrying this node label, counts included.
limitintegernoEdges listed per edge type (default 10, max 100), or partner keys listed under edge_type/all_of (default 200, max 2000). The rest are counted as ‘… and N more’.

neighborhood

What is around K — one hop out, as the same grouped relationship listing node_edges gives, with the rule and score behind each edge. With depth above 1 it is the breadth-first table of (key, label, depth) instead, because past one hop no single rule accounts for a row. label narrows the reply to nodes carrying it, at either depth.

ArgumentTypeRequiredWhat it is
depthintegernoHops to traverse (default 1). 1 gives the relationship listing; above 1 gives the traversal table.
directionone of "out", "in", "both"noEdge direction to follow (default both).
edge_typesarray of stringnoOnly follow these edge types. Omit for every type.
jsonbooleannoAnswer with the report as JSON, not the rendered digest.
keystringyesNode key to start from.
labelstringnoOnly nodes carrying this label: at depth 1 the partners, counts included; above it the rows of the traversal table. The walk itself is never narrowed — a hop through another label is how the label you asked about is reached.
limitintegernoAt depth 1, edges listed per edge type (default 10).

edges_at

What did K’s relationships look like on DATE (or at commit C) — the edges that were live at one point in the store’s history, with the rule that had derived each. at takes EITHER an RFC 3339 date (“2026-06-19”, or “2026-06-19T12:00:00Z”) OR a 0-based WAL commit index. Pass the date directly: it resolves to the last commit at or before that instant. Do NOT guess a commit index for a date, and do not go probing commits to find one — a store that cannot answer a date says so by name. Which partners were linked by all of these types on that day? pass all_of and the reply is just their keys; pass one edge_type for that type’s partner keys with the rule named once. label narrows partners. With json:true the report carries listed and total, so a reply that was cut still says how much there was.

ArgumentTypeRequiredWhat it is
all_ofarray of stringnoOnly the partners linked by EVERY one of these types at that commit — the intersection, as keys.
atstring or integeryesWhen to read the edges. Either an RFC 3339 date string — “2026-06-19”, “2026-06-19T12:00:00Z”, offsets accepted — which resolves to the last commit at or before that instant, or a 0-based WAL commit index. Prefer the date when the question names one.
directionone of "out", "in", "any"noWhich edges count (default any).
edge_typestringnoOnly this type: the reply is that type’s partner keys, compactly. Omit for the grouped listing over every type.
jsonbooleannoAnswer with the report as JSON, not the rendered digest.
keystringyesNode key.
labelstringnoOnly partners carrying this node label, counts included.
limitintegernoEdges listed per edge type (default 10, max 100), or partner keys listed under edge_type/all_of (default 200, max 2000). The rest are counted as ‘… and N more’.

what_if

What changes if K’s FIELD became VALUE — the relationships lost and gained, with the rule behind each. Does not change the store: nothing is written, nothing on disk is copied, and the live graph answers the same way before and after the call. Which partners of one type would it cost? pass edge_type and the lost and gained lists are just their keys, with the rule named once. label narrows partners.

ArgumentTypeRequiredWhat it is
edge_typestringnoOnly this type, counts included: the reply is the partner keys lost and gained, compactly.
fieldstringyesProperty name to set.
jsonbooleannoAnswer with the report as JSON, not the rendered digest.
keystringyesNode key to change.
labelstringnoOnly partners carrying this node label, counts included.
limitintegernoEdges (or partner keys) listed per side (default 10). The rest are counted as ‘… and N more’.
valueanyyesThe value it would take: a string, number, boolean, or a list or map of those. Not null.

recall

What do I already know about this — ranked nodes matching a free-text topic across every indexed text field, with one line each.

ArgumentTypeRequiredWhat it is
jsonbooleannoAnswer with the report as JSON, not the rendered digest.
topicstringyesFree-form text. A question, a name, or a phrase.

remember

Remember this for next time — write a note into the graph and return what it did. Use ‘about’ for a subject whose type you don’t know yet — an unknown key there is created as a provisional entity (label ‘Entity’), not refused, and stays that label permanently until it is named through ‘entities’ instead. Use ‘entities’ for a subject whose type you DO know: it is created (or described, if it already exists) under the label you give it, correctly labelled the first time — the label can never be changed afterward, not even by upsert_entity, so name it here when you can rather than leaving it for ‘about’ to guess at. Pass ‘facts’ for the relationships you recognised, between keys named in ‘entities’ or ‘about’, in the same commit.

ArgumentTypeRequiredWhat it is
aboutarray of stringnoNode keys the note is about, when you don’t know their type. A key that does not exist yet is created as a provisional entity (label ‘Entity’) — permanently: prefer ‘entities’ when you know the label, since a provisional node’s label can never change later.
entitiesarray of objectnoEntities you recognised in the text.
entities[].aliasesarray of stringnoOther names this entity goes by, kept as written in its ‘alias_keys’ list. With the identity preset, one equal to a provisional stub’s key (exact, case-sensitive) links that stub.
entities[].keystringyes
entities[].labelstringyes
entities[].propsobjectno
factsarray of objectnoRelationships you recognised, between keys named above.
facts[].objectstringyes
facts[].predicatestringyes
facts[].subjectstringyes
jsonbooleannoAnswer with the report as JSON, not the rendered digest.
kindone of "note", "decision", "todo"noWhat kind of note this is (default: note).
sourcestringnoWhere this came from — a session id, a file, a person. Defaults to “agent”.
textstringyesThe note itself, 1 to 4000 characters.
tsintegernoUnix seconds the fact dates from. Defaults to now. Pass it when importing.

schema

What’s in here — the store’s labels with their property names, its edge types and what derives them, every rule with its predicate, the full-text fields recall searches, the equality indexes, and how many provisional nodes remember created. Call it before writing Cypher against a store you have not seen.

ArgumentTypeRequiredWhat it is
jsonbooleannoAnswer with the report as JSON, not the rendered digest.

analyze

What matters here, and what clusters — over the whole store, with no role or mask applied. kind ‘central’ ranks nodes by PageRank along edge direction, ‘degree’ by edge count, ‘components’ groups connected nodes with sizes, ‘clusters’ finds communities of two or more, ‘identities’ resolves SAME_AS links into sets every pair of which is linked, oldest node first. ‘top’ (default 10, at most 50) bounds the rows; ‘edge_type’ restricts to one type. The same store always gets the same answer.

ArgumentTypeRequiredWhat it is
edge_typestringnoOnly edges of this type.
jsonbooleannoAnswer with the report as JSON, not the rendered digest.
kindone of "central", "clusters", "components", "degree", "identities"yesWhich question.
topintegernoRows to list (default 10).

suggest_rules

What relationships are in my data — rules the store proposes from its own values, each with an estimate, examples and the exact create_rule arguments. Nothing is created: show the proposal and wait for approval before calling create_rule. Fields the store writes for bookkeeping are never proposed. Every proposal is global and links across namespaces.

ArgumentTypeRequiredWhat it is
jsonbooleannoAnswer with the report as JSON, not the rendered digest.

forget

Forget that — tombstone a node (‘key’), remove one property (‘key’ and ‘prop’), or retract one fact edge (‘fact’: subject, predicate, object). An edge a rule derived is refused with the rule that owns it. Notes that still state what was forgotten are listed, not deleted. History keeps it until the log is pruned, and the reply says so. There is no role check: this server has no auth.

ArgumentTypeRequiredWhat it is
factobjectnoThe edge to retract, as remember’s facts name it.
fact.objectstringyes
fact.predicatestringyes
fact.subjectstringyes
jsonbooleannoAnswer with the report as JSON, not the rendered digest.
keystringnoThe node to forget, or whose property to forget.
propstringnoWith ‘key’: the one property to remove.

Graph tools

These reach the store directly. In the listing a client receives, each description opens with Advanced:, so an assistant knows the task tools come first.

query

Who may see this, and anything else one pattern can answer — run a Cypher query (read or write) against the graph. Pass ‘role’ to answer as one of the store’s roles: only the nodes that role may see, writes refused. ‘mask’ is the same restriction written out as an explicit key allow-list. Pass ‘as_of’ to answer from a past commit; it composes with ‘role’ or with ‘mask’. Pass ‘namespace’ to answer from one namespace only. Cypher dialect: MATCH/WHERE/RETURN, CREATE, MERGE, SET, DELETE, with $named parameters in ‘params’. A node’s key and label read as properties (n.key, n.label) or as key(n)/labels(n). One MATCH takes comma-separated patterns that share variables — MATCH (t)-[:A]->(c), (t)-[:B]->(c) is the intersection of both, and count(DISTINCT t) after WITH counts each t once. WHERE takes STARTS WITH, ENDS WITH, CONTAINS, IN, and a list subscript (n.location[0]) — which is null when the index is out of range, the property is not a list, or the index is not an integer, so a subscript never errors and never matches.

ArgumentTypeRequiredWhat it is
as_ofintegerno0-based WAL commit index: answer from the graph as it was at that commit. Composes with ‘role’ or with ‘mask’ — never both, which is refused as it is without ‘as_of’ — and whichever is passed is resolved against the graph as it was then. Deleting a node does not remove it from a role’s past, and a role’s ‘keys’ resolve to whichever node held the key at that commit. Writes are refused.
cypherstringyesCypher query text.
maskarray of stringnoOptional node key allow-list. When present, only these nodes are visible; write statements are rejected.
namespacestringnoAnswer only from this namespace. Intersects with ‘role’ and ‘mask’ — it can only narrow what they already allow. A role bound to namespaces honours them with no argument here. ‘default’ is the namespace of every node that names none; a name no node uses answers with nothing.
paramsobjectnoNamed JSON-scalar query parameters.
rolestringnoAnswer as this role from the store’s roles: only the nodes it may see. A role may also be narrowed by one property test (status in [...]), declared in the store’s roles.

ingest_json

Fill the store from a batch — ingest a JSON array of objects as nodes of one label. Each object becomes a node; declare the rules that should link them with ‘create_rule’.

ArgumentTypeRequiredWhat it is
auto_fk_suffixstringno
edgesarray of anynoOptional user edges [{edge_type, src, dst}].
key_fieldstringno
labelstringyes
namespacestringnoNamespace for every node this call creates. Omitted means the ‘default’ namespace. A row that carries its own ‘ns’ must name the same namespace. A namespace is set at insert and cannot be changed afterwards.
rows_jsonstringyesJSON text of an array of objects.

create_rule

How should this kind of relationship be derived from now on — declare a rule (RuleDef JSON) and the engine maintains its edges as the data changes. Propose it and show the edges it would derive before creating one.

ArgumentTypeRequiredWhat it is
approximatebooleannoFind candidates through the HNSW index instead of comparing every pair (default: false). Only for a VectorSimilar predicate; the edges are approximate, not exact.
dst_labelstringyes
edge_typestringyes
max_edgesinteger or nullno
namestringyes
namespacestringnoScope the rule to one namespace: it sees only that namespace’s nodes — source, via hop and destination — so every edge it derives stays inside. Omitted means a global rule, which is the only kind that may derive an edge across a boundary.
predicateobjectyes
src_labelstringyes
weight_propstring or nullnoEdge property that stores the score (default: weight).

explain

Why are A and B related, as a raw array — the same rule-derived edges explain_association renders, for a caller that wants the JSON without asking.

Listed only with --all-tools; the server answers it either way.

ArgumentTypeRequiredWhat it is
astringyes
bstringyes

stats

How big is this store — live node, edge and rule counts, plus history_floor, the oldest commit history still reaches (0 when nothing has been pruned). Pass ‘role’ or ‘namespace’ to also get namespaces, the namespaces that argument may see with a live-node count each; without either argument the roster is omitted entirely.

ArgumentTypeRequiredWhat it is
namespacestringnoReport only this namespace. Intersects with ‘role’.
rolestringnoReport only the namespaces this role may see. The store-wide counts beside them are unchanged.

node_info

What is K — its label and every property it holds.

ArgumentTypeRequiredWhat it is
keystringyes

upsert_entity

Record what is now true about K — insert or update a node by key. If the key exists, updates the supplied properties atomically: every property is checked before any is written, so a refusal leaves the node unchanged. If not, creates a new node with the given label and properties. ‘id’ in ‘props’ is ignored on both paths: a created node stores ‘id’ as its key, and ‘rename_node’ is the only way to change it. Useful for agent memory: store or refresh an entity without checking existence first.

ArgumentTypeRequiredWhat it is
aliasesarray of stringnoOther names this entity goes by, kept as written in ‘alias_keys’: with the identity preset, one equal to a provisional stub’s key (exact, case-sensitive) links that stub. The store derives ‘aliases’ from the key and the name only. Do not set either in props.
keystringyesUnique node key.
labelstringnoNode label (required when creating a new entity).
namespacestringnoNamespace for a node this call creates. Omitted means the ‘default’ namespace. On a node that already exists, naming the namespace it is in is a no-op and naming another one is refused — a namespace is set at insert and cannot be changed.
propsobjectyesProperties to set. Values must be scalars (string, number, bool) or arrays of scalars.

find_similar

What is most like this — two modes: (1) Vector search — provide vector (and optionally field, label, k, min, where, exact) to find the k most similar nodes by cosine similarity using the HNSW index when available, brute-force otherwise. where is a property predicate ({field, eq} or {field, in}) and implies exact search. exact true skips HNSW. (2) Edge traversal — provide key (and optionally edge_type, limit) to return neighbors previously connected by a derived rule edge. Results from mode 2 come only from edges already derived by a VectorSimilar rule. Edge-traversal mode ignores where and exact. In both modes, the optional mask array limits visibility: hidden nodes never appear in results, and a hidden query key in edge mode behaves identically to a nonexistent key.

ArgumentTypeRequiredWhat it is
edge_typestringnoEdge type to filter by in edge-traversal mode (default: SIMILAR).
exactbooleannoWhen true, vector-search mode uses exact GEMM brute force and does not consult HNSW. Default false. Edge-traversal mode ignores this.
fieldstringnoProperty field holding the embedding vectors (default: embedding). Used in vector-search mode.
kintegernoMaximum results to return in vector-search mode (default: 10).
keystringnoSource node key for edge-traversal mode.
labelstringnoRestrict search to nodes with this label. Empty string means all labels. Used in vector-search mode.
limitintegernoMaximum neighbors to return in edge-traversal mode (default: 10).
maskarray of stringnoOptional node key allow-list for vector-search mode. When present, only nodes whose key appears in this list are eligible for results. Hidden nodes are excluded before k-truncation. The beam widens until it has k visible hits, then falls back to an exhaustive masked scan at the same cap an exact VectorSimilar rule uses, so the result is not short while more visible hits exist. Unknown keys are silently ignored.
minnumbernoMinimum cosine similarity threshold in vector-search mode (default: 0.8 on every surface; before 0.7 HTTP and the Python binding defaulted to 0.0). Pass 0.0 to keep low-similarity hits.
vectorarray of numbernoQuery embedding vector for vector-similarity search. When present, vector-search mode is used and key is ignored.
whereobjectnoOptional property predicate for vector-search mode, same shape as visible_where: {“field”: “…”, “eq”: value} or {“field”: “…”, “in”: [values]}. Implies exact search (skips HNSW). Invalid predicates are a tool error. Edge-traversal mode ignores this.

pairwise_similar

Which of these are most like each other — exact cosine top-k among a caller key set. Self excluded. Never uses HNSW. Unknown keys, missing embeddings, zero-norm and wrong-dimension vectors are skipped. Duplicate keys collapse to first-seen order. Empty keys returns nothing. n above PAIRWISE_MAX_N is a tool error.

ArgumentTypeRequiredWhat it is
fieldstringyesProperty field holding the embedding vectors.
kintegernoMaximum neighbors per key (default: 10).
keysarray of stringyesNode keys to score against each other.
minnumbernoMinimum cosine similarity threshold (default: 0.0).

What matches these words and this vector at once — Reciprocal Rank Fusion (RRF) over fulltext + vector results. Provide query_text and text_field for the fulltext leg. Optionally provide vector (embedding array) and vector_field (default: embedding) for the vector leg; omitting vector gives text-only ranking through the same RRF path. label restricts the vector search to nodes with that label (required for brute-force; omit to rely on HNSW rules). k controls result count (default: 10). RRF constant is fixed at 60; scores are 1/(60+rank) summed over lists a node appears in.

ArgumentTypeRequiredWhat it is
kintegernoMaximum results to return (default: 10).
labelstringnoRestrict vector search to nodes with this label. Required when relying on brute-force (no HNSW rule covers the field). If omitted, the vector leg always returns empty results (no rule-created HNSW index covers the unlabeled path); ranking is text-only in that case.
query_textstringyesFulltext query string.
text_fieldstringyesProperty field to search with fulltext.
vectorarray of numbernoQuery embedding vector. Omit for text-only ranking.
vector_fieldstringnoProperty field holding embedding vectors (default: embedding).

node_history

What has happened to K — every recorded change to one node, newest last. Events include NodeInserted, PropSet, PropRemoved, EdgeAdded, EdgeRemoved, and NodeDeleted. The response includes total_commits (the horizon upper bound) and horizon, the oldest commit still retained; events before it are gone. History is WAL-scoped — pre-snapshot commits are not visible.

ArgumentTypeRequiredWhat it is
keystringyesNode key to look up.

edge_history

When did A and B become linked, and when did it break — the full add/retract lifecycle for every edge between the two keys. Includes derived (rule-attributed) edges via DerivedEdgeAdded/DerivedEdgeRetracted WAL markers. The response includes total_commits (the horizon upper bound) and horizon, the oldest commit still retained; events before it are gone.

ArgumentTypeRequiredWhat it is
astringyesFirst node key.
bstringyesSecond node key.

was_linked

Were A and B linked on DATE (or at commit C) — whether an edge of edge_type existed between the two keys (either direction) at that point in the store’s history. Pass the date directly; do not guess a commit index for it. Returns an error when the commit is outside the retained horizon (horizon..total_commits).

ArgumentTypeRequiredWhat it is
astringyesFirst node key.
at_commitstring or integeryesWhen to check. Either an RFC 3339 date string — “2026-06-19”, “2026-06-19T12:00:00Z”, offsets accepted — which resolves to the last commit at or before that instant, or a 0-based WAL commit index.
bstringyesSecond node key.
edge_typestringyesEdge type to check.

rename_node

Rename K — the key changes and nothing else does. The dense id and all edges/properties remain stable. Returns 404 if old_key does not exist, 409 if new_key is already taken.

Listed only with --all-tools; the server answers it either way.

ArgumentTypeRequiredWhat it is
new_keystringyesDesired new node key.
old_keystringyesCurrent node key.