engrava-mcp
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@engrava-mcpremember that I prefer dark mode in editors"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Engrava MCP
The Model Context Protocol server for Engrava — expose an agent memory database to any MCP client (Claude Desktop, Claude Code, Cursor, Windsurf, VS Code, …) over stdio.
engrava-mcp is a standalone, runnable package that consumes Engrava's public
API. It is the one way to run Engrava as a memory server; the engrava library
itself ships no MCP code.
uv tool install engrava-mcp # recommended for daily use: a persistent install
engrava-mcp # spawned by your MCP client over stdiouvx engrava-mcp runs it without an install step, and pip install engrava-mcp
works too. uvx keeps its environment in a cache. When that cache is cold, the
first start waits for the download; see Optional providers
for the [local] extra, where the download is largest.
Installing engrava-mcp pulls in engrava transitively, so you also get the
import engrava library in the same environment.
Compatibility
engrava-mcp follows Engrava's version: engrava-mcp X.Y.z targets engrava X.Y
and requires engrava >=X.Y,<X.(Y+1). This is a one-way version mirror for legibility —
not a lockstep: Engrava releases on its own cadence, and engrava-mcp patch releases
are independent.
engrava-mcp | Works with engrava |
|
|
|
|
|
|
The dependency range is the source of truth. Normal installs resolve a compatible
engrava automatically; if you pin engrava yourself, keep it within that range. If no
matching engrava-mcp exists yet for an engrava newer than the table's last row, that
pairing is not yet verified/supported — not broken; stay on a supported pair until a
matching engrava-mcp ships.
Related MCP server: Engineering Knowledge Graph MCP Server
Which package do I want?
Goal | Install |
Build on the Engrava Python API (memory DB in your own code) |
|
Run Engrava as a memory server for an MCP client |
|
There is no third option.
Migrating from engrava[mcp]
The server used to ship inside Engrava as the engrava[mcp] extra and an
in-engrava engrava-mcp command. As of Engrava 0.5.0 it lives here instead.
Before | After |
|
|
|
|
client | client |
Watch out:
pip install "engrava[mcp]"against Engrava 0.5 does not fail — pip ignores the now-unknown extra and quietly installs bareengrava, so it can look like the server installed when it did not. Installengrava-mcpinstead.Update any pinned requirement strings (
engrava[mcp]>=...) to depend onengrava-mcp, not just reinstall.Your store configuration is unchanged — the same
engrava.yaml/ env vars work exactly as before (see Configuration).
Configuration
The server resolves its store from environment variables, in priority order:
Variable | Meaning |
| Path to an |
| Path to a bare SQLite database file. Use an absolute path: a relative one resolves against the server's working directory, which the client chooses. Zero-config quick-start; no embedding provider is configured, so semantic (vector) search is inert — full-text search, the graph, and MindQL still work. This route builds the store with no journal; use |
| When set to |
Recommended: give the MCP server the same engrava.yaml your application
uses. The yaml is the only place to declare an embedding provider (and its
model / key), which the server needs to embed a new query at search time for
semantic search. With only ENGRAVA_DB_PATH set, the server emits a startup
warning that semantic search is inert and points you at ENGRAVA_MCP_CONFIG.
At search time, the server embeds the query with the provider this yaml
declares. Whether this server's writes embed anything is decided by the same
yaml's embeddings.auto_embed, which Engrava leaves off by default. With it
off, a thought created through store_thought gets no embedding, so
search_memory's vector ranking cannot match it — its keyword ranking still
can — and an update_thought leaves whatever embedding the thought already had
as it was, not refreshed. With it on, creating a thought, or changing its
essence or content, also calls the provider.
Store-hook extensions need the config path
Engrava extensions that hook the store — anything wired through an
engrava.yaml's hooks: section — are attached only on the
ENGRAVA_MCP_CONFIG launch. ENGRAVA_DB_PATH opens a bare database and carries
no configuration, so it runs with Engrava's default hooks and cannot attach a
store-hook extension. That is deliberate: it is an intentionally minimal
read/write facade.
Installing such an extension and starting with ENGRAVA_DB_PATH therefore
leaves its store hooks unattached in this server. When an installed package
advertises any extension, the server emits a startup warning naming it — it
reports what is advertised, not what each one does, since it never loads them
itself — so you can tell the difference between "nothing advertised" and
"advertised but nothing wired it here". If reading the installed-package
metadata raises an ordinary error, the server attempts to log that instead and
carries on starting. Both go through Python's logging, so whether and where
they surface is up to your logging configuration. To wire a store hook, launch
with ENGRAVA_MCP_CONFIG pointing at an engrava.yaml with a hooks:
section:
hooks:
class: "my_package.hooks.MyHooks"Example engrava.yaml
database:
path: /absolute/path/to/memory.db
embeddings:
provider: openai-compatible # or: ollama, sentence-transformer, huggingface
model: text-embedding-3-small
api_key: ${OPENAI_API_KEY}A relative database.path resolves against the server process's working directory,
which the MCP client chooses, not against the yaml's folder.
Client setup
Point your MCP client at the server over stdio. For example, a typical
mcp.json entry:
{
"mcpServers": {
"engrava": {
"command": "engrava-mcp",
"env": {
"ENGRAVA_MCP_CONFIG": "/absolute/path/to/engrava.yaml"
}
}
}
}A ${VAR} value in the engrava.yaml, such as ${OPENAI_API_KEY}, is read from the
server's own environment, so add that variable to the same env block, unless the
client is known to pass its own environment through.
This assumes uv tool install engrava-mcp. If your client cannot find the
command, give its absolute path; uv tool dir --bin prints the directory.
Without an install, use "command": "uvx", "args": ["engrava-mcp"].
Use ENGRAVA_DB_PATH instead of ENGRAVA_MCP_CONFIG for the zero-config
quick-start, and add "ENGRAVA_MCP_READ_ONLY": "1" for an app-writes /
agent-reads deployment.
Running without uvx
engrava-mcp # console script
python -m engrava_mcp # module run
python -m engrava_mcp.server # module run (server module directly)Optional providers
For an MCP deployment, prefer an embedding provider that runs outside the
server process: Ollama (provider: ollama) or an OpenAI-compatible endpoint
(provider: openai-compatible). The default install already covers both, and
the server then loads no embedding model itself.
The default install supports the vector backend and HTTP-based embedding
providers (OpenAI / Ollama) once configured in the yaml. Heavier providers are
opt-in extras that mirror Engrava's own extras:
uvx --from "engrava-mcp[local]" engrava-mcp # sentence-transformers (local model)
uvx --from "engrava-mcp[hf]" engrava-mcp # HuggingFace Inference API
uvx --from "engrava-mcp[openai]" engrava-mcp # OpenAI-compatible embeddings deps
uvx --from "engrava-mcp[ollama]" engrava-mcp # Ollama embeddings deps[local] runs the model inside the server process and installs PyTorch, which
can add several gigabytes. A first start on a cold uvx cache waits for that
download; later starts reuse the cache. uv tool install "engrava-mcp[local]"
pays the download once, at install time. A model that is not already in the
local model cache is downloaded when it is first loaded.
The surface
Tools (13):
get_thought,search_memory,search_keywords,list_memory,query_memory,memory_stats,get_edges,list_edges(read);store_thought,update_thought,link_thoughts,delete_thought,delete_edge(write, gated byENGRAVA_MCP_READ_ONLY).Resources (3):
engrava://thought/{thought_id},engrava://stats,engrava://recent.Prompts (3):
summarize_recent_memory,find_related,reflect_on_topic.
query_memory accepts only MindQL FIND queries; raw SQL and every other
command are rejected. It returns at most 5000 rows. A limit argument replaces
the query's own LIMIT; without one, a LIMIT outside 1–5000 is refused.
get_edges traverses a thought's edges by direction (IN / OUT / BOTH);
with limit, at most that many edges, the highest-weight ones first, and
without it, every edge. list_edges browses edges filtered by type, source,
or metadata.
link_thoughts accepts optional edge metadata (JSON fields that list_edges
can filter on). search_memory accepts an optional recency_now (ISO-8601
timestamp) giving the moment to measure age against (transaction time); recency
takes part in the ranking only when you pass it.
Development
pip install -e ".[dev]"
ruff check src/ tests/
ruff format --check src/ tests/
mypy --strict src/
pytest --cov --cov-fail-under=90License
MIT
Available Tools
13 toolsdelete_edgeADestructiveIdempotent
Delete an edge between two thoughts by its identifier. Use this to remove a relationship that is wrong or no longer wanted. Returns whether an edge was removed; deleting an identifier that does not exist is not an error and simply reports that nothing was removed.
| Name | Required | Description | Default |
|---|---|---|---|
| edge_id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true and idempotentHint=true, so the safety profile is covered; the description adds genuinely new behavior: it returns whether an edge was removed, and a nonexistent identifier is not an error but a no-op report. That not-found semantics is exactly the kind of detail annotations cannot express. It does not mention permissions or side effects on the connected thoughts.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences, front-loaded with the action and resource, followed by when-to-use and then return semantics. No filler or restatement of the name.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be spelled out, yet the description still flags the removed/not-removed outcome and the non-error no-op case, which is the key ambiguity for a delete. The only gap is whether deleting the edge leaves the two thoughts intact and whether any permission is required.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
There is one parameter at 0% schema description coverage, so the description must carry the burden. "By its identifier" confirms edge_id selects the edge, but adds no format, source, or where-to-obtain guidance (e.g., from list_edges). Adequate but thin for a fully undocumented parameter.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource (delete an edge between two thoughts) plus the lookup key (by its identifier), so the agent knows exactly what is being removed. It does not explicitly contrast itself with the closest siblings (link_thoughts for creation, list_edges/get_edges for inspection), but the semantics are unambiguous on their own.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
"Use this to remove a relationship that is wrong or no longer wanted" gives a clear condition for invocation, and the mental model of edge-vs-thought deletion is clear from the resource named. It stops short of naming an alternative tool or stating when-not to use it (e.g., to modify rather than remove, relink instead).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
delete_thoughtADestructiveIdempotent
Delete a thought by its identifier. Use this to remove a memory that is wrong or no longer wanted. This cascades: the thought's edges, embeddings, and action records are deleted with it. Returns whether a thought was removed; deleting an identifier that does not exist is not an error and simply reports that nothing was removed.
| Name | Required | Description | Default |
|---|---|---|---|
| thought_id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint and idempotentHint, yet the description goes further by spelling out the cascade: edges, embeddings, and action records are destroyed along with the thought. It also discloses that deleting a nonexistent id is not an error, which is behavioral information unavailable anywhere in the structured fields.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four sentences with no filler, and the core action plus cascade are front-loaded. The final sentence partly restates the return contract that the output schema already provides, though it earns its place through the non-error-on-missing-id detail.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a one-parameter destructive tool with full annotations and an output schema, this covers everything an agent needs: what gets deleted transitively, idempotent no-op behavior on missing ids, and the return signal. Nothing material is left to inference.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
There is a single required parameter with 0% schema description coverage, so the description carries the burden and only says 'by its identifier' — effectively restating the parameter name without format, source, or how to obtain a valid id. Adequate but not compensating for the coverage gap.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource (delete a thought by identifier) and immediately distinguishes the action from editing via update_thought by naming its use case as removing a memory that is wrong or unwanted. The cascade scope (edges, embeddings, action records) further pins down exactly what entity is being removed.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives a clear condition for use ('remove a memory that is wrong or no longer wanted'), which is enough to pick it over read-oriented siblings like get_thought or search_memory. It stops short of explicit exclusions — it never says when to prefer update_thought or delete_edge instead, so an agent must infer that itself.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_edgesARead-only
Fetch the edges connected to a thought by its identifier. Choose the direction: OUT for edges leaving the thought, IN for edges arriving at it, or BOTH (the default) for either. Returns full edge records including their metadata, and a count. With limit, it returns at most that many edges, the highest-weight ones first; without it, it returns every edge. This is the read companion to link_thoughts and delete_edge.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| direction | No | BOTH | |
| thought_id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, and the description adds useful behavior: full edge records with metadata and count, highest-weight-first ordering when limit is set, and all edges when limit is omitted. It does not cover auth or rate limits, but those are less critical for a read-only tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four sentences, front-loaded with the core action, then direction, return behavior, and limit semantics. No wasted text.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the output schema exists, the description need not explain return values in full, but it still covers return shape and count. It also compensates for the 0% schema description coverage by explaining every parameter.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description carries the full burden. It explains thought_id as the thought identifier, direction values OUT/IN/BOTH with default BOTH, and limit as a cap returning highest-weight edges first.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: fetch edges connected to a thought by identifier. It also names link_thoughts and delete_edge as related tools, but does not explicitly distinguish itself from the closest sibling, list_edges.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explains direction choices and defaults, and describes limit behavior. It frames itself as the read companion to link_thoughts and delete_edge, but does not explicitly say when to use it instead of list_edges.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_thoughtBRead-only
Fetch a single thought by its identifier.
| Name | Required | Description | Default |
|---|---|---|---|
| thought_id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, so safety is covered. The description adds nothing beyond that: it does not say what happens when the id doesn't exist, whether an error or null is returned, or any scoping/permission constraint.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single front-loaded sentence with no filler, but its brevity comes at the cost of the guidance and failure-mode context an agent would want.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists so return values need not be described, and there is only one required param. Still missing is the not-found behavior, which matters for a by-id fetch tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema documents nothing about thought_id (0% coverage), but the description at least clarifies that the parameter is the thought's identifier used for lookup. It gives no format, source, or example of a valid id.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('Fetch') and resource ('a single thought') plus the lookup key, which distinguishes it from list/search siblings by cardinality. It does not name any sibling explicitly, so the differentiation is implicit.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The phrase 'by its identifier' implies this is the direct-lookup path versus search_memory/query_memory, but no when-to-use or when-not-to-use guidance is stated, and no alternative is named.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
link_thoughtsA
Create a typed edge between two existing thoughts, identified by their identifiers. Choose the edge type and optionally a weight in [0.0, 1.0]. Optionally attach a metadata object (simple field names to JSON scalars) that list_edges can later filter on. Both endpoints must already exist. An edge is unique per (source, target, type): linking the same pair with the same type twice is rejected rather than ignored.
| Name | Required | Description | Default |
|---|---|---|---|
| weight | No | ||
| edge_id | No | ||
| metadata | No | ||
| edge_type | Yes | ||
| to_thought_id | Yes | ||
| from_thought_id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=false, idempotentHint=false, destructiveHint=false; the description adds the important nuance behind non-idempotency — duplicate (source, target, type) is rejected, not ignored, so retries will error. It also discloses the endpoint-existence requirement. It doesn't mention failure modes for invalid weights or auth needs.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four short sentences, front-loaded with the action, then constraints. Every sentence adds a non-obvious rule; nothing is padding.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Output schema exists so return values need no explanation, and the mutation semantics are well covered. The only meaningful gap for a 6-parameter write tool is the undocumented `edge_id` and the lack of per-type guidance for the edge enum.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description must compensate, and it largely does: source/target ids, edge type, weight range [0.0, 1.0], and metadata limited to scalar fields filterable by list_edges. The `edge_id` parameter is never explained and the seven EdgeType enum values carry no semantic guidance beyond their names.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a specific verb+resource: "Create a typed edge between two existing thoughts." It immediately distinguishes itself from read-side siblings (list_edges, get_edges) and from node-creation tools like store_thought.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
States a concrete precondition ("Both endpoints must already exist") and points at list_edges as the consumer of metadata, which tells the agent how the write pairs with reading. It does not explicitly say when to prefer this over store_thought/update_thought for connecting concepts, but the context is clear enough.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_edgesARead-only
List stored edges with optional filters. Filter by edge type, by knowledge source, and by edge metadata: metadata_equals takes a mapping of field name to a required value (exact match on every pair), and metadata_in takes a mapping of field name to a list of allowed values (the field must equal one of them). Metadata keys are simple field names and values are JSON scalars. Returns full edge records including their metadata, and a count.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| source | No | ||
| edge_type | No | ||
| metadata_in | No | ||
| metadata_equals | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
readOnlyHint=true already tells the agent this is a safe read. The description adds real value by disclosing the return shape ('full edge records including their metadata, and a count'), but it omits ordering, pagination/truncation behavior, and what happens when limit is hit, which matter for a list tool capped at 5000.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The purpose statement is front-loaded and the two metadata filters are each defined in a single clause. The sentences are dense but every one carries information; the only mild drag is repeating the return content that the output schema already covers.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only filtered-list tool with a full output schema, the description covers the non-obvious parts (metadata filter semantics) and the return content. The gaps are minor: no word on limit defaults/paging or result ordering, which an agent would need to page reliably.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description carries the burden — and it does explain metadata_equals and metadata_in carefully, including exact-match-all-pairs vs any-of semantics and that values are JSON scalars, which the schema's anyOf does not make obvious. However, limit, source, and edge_type receive no explanation at all, leaving the most basic paging parameter undocumented.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The opening sentence states a specific verb and resource ('List stored edges') plus scope ('with optional filters'), and the following sentences enumerate the filterable dimensions. It never names or contrasts with the sibling get_edges, so an agent must infer the boundary between listing and fetching edges.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied by the filter description (use it to browse edges narrowed by type, source, or metadata), but there is no explicit when-to-use/when-not guidance and no mention of when get_edges or search_memory would be the better choice. The reader must derive the selection rule from sibling names alone.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_memoryARead-only
List stored thoughts with optional filters and pagination. Unlike search_memory this does no relevance ranking and returns no scores: it is a plain browse over memory, ordered by highest cognitive cycle first; thoughts written through this server all carry cycle 0, so their relative order is unspecified and does not represent recency. Filter by thought type, lifecycle status, priority, and an updated-cycle range; page through results with limit and offset. Use this to enumerate memory by structured fields; use search_memory when you want the best matches for a query.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| offset | No | ||
| priority | No | ||
| max_cycle | No | ||
| min_cycle | No | ||
| thought_type | No | ||
| include_expired | No | ||
| lifecycle_status | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the `readOnlyHint` annotation, the description provides critical behavioral details, including the sorting logic (ordered by highest cognitive cycle first), the server constraint (thoughts written through this server are cycle 0), and detailed pagination mechanics.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The definition is dense and highly informative, using every sentence to convey a specific, useful piece of operational or comparative information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (multiple filter types, specific ordering rules, and use-case alternatives), the description is highly comprehensive and requires no further elaboration for a sophisticated agent.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Despite having 0% schema description coverage, the text explicitly lists all the filtering capabilities ('Filter by thought type, lifecycle status, priority, and an updated-cycle range'), giving conceptual meaning to the abstract parameters.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool lists stored thoughts and immediately clarifies its scope: it performs a 'plain browse' without relevance ranking, distinguishing it sharply from `search_memory`.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It provides explicit use cases: use this to 'enumerate memory by structured fields' (like status or priority), and use `search_memory` when a relevance-based query is needed.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
memory_statsARead-only
Return aggregate statistics about the memory store: thought and edge counts and total storage size. If the store's metrics collection is disabled, the counts in this response are zero-filled placeholders rather than a real measurement — check the 'measured' flag to tell the two cases apart.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Adds real behavioral context beyond readOnlyHint: it warns that counts may be zero-filled placeholders when metrics collection is disabled and tells the agent to read the 'measured' flag to disambiguate. That is exactly the kind of non-obvious trait an agent could otherwise misinterpret as a genuinely empty store.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, no waste. The primary return content is front-loaded and the caveat follows immediately, so the agent reads the important behavior without scanning.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return shape needn't be explained, and the description covers the one piece of behavior the output schema cannot convey on its own — that zeros may mean 'not measured' rather than 'empty'.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so the schema baseline of 4 applies; there is nothing for the description to compensate for.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Return aggregate statistics about the memory store') and enumerates what's included: thought count, edge count, storage size. This clearly distinguishes it from all siblings, which are per-item or listing operations (get_thought, list_memory, search_memory).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives a clear context for use (inspecting aggregate store size/counts) and specifically calls out the disabled-metrics scenario where the numbers are placeholders. It stops short of explicitly naming alternatives, but the sibling set contains no equivalent stats tool, so the routing ambiguity is low.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
query_memoryARead-only
Run a structured MindQL FIND query over stored memory, e.g. "FIND thoughts WHERE lifecycle_status = 'ACTIVE' LIMIT 10". Only the FIND command is supported, and only against thoughts, edges, or actions — FIND embeddings is refused, since a stored embedding is raw vector bytes with no JSON representation. Results are capped at 5000 rows: a query with no LIMIT clause gets this cap injected, and a LIMIT above it is refused rather than truncated. The limit argument, if given, always replaces any LIMIT already in the query text — the two are never combined.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| query | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnlyHint annotation, it discloses the 5000-row cap, that a missing LIMIT gets the cap injected, that an oversized LIMIT is refused rather than truncated, and that the limit argument replaces an inline LIMIT instead of combining with it. These are exactly the runtime behaviors an agent must know to avoid failed or surprising queries.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Purpose is front-loaded in the first sentence, followed by constraints in decreasing order of importance, with zero filler. Every sentence conveys a distinct rule the agent needs.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be explained, and the query syntax, command restrictions, and limit interactions are all covered. The only gap is the absence of guidance on choosing this tool over the sibling read tools for a given retrieval need.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description must carry the load, and it does: it defines the query parameter through a concrete MindQL example and fully specifies the limit parameter's override semantics and ceiling. The distinction between the argument and an inline LIMIT is not inferable from the schema and prevents real errors.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Names a specific verb and resource: it runs a structured MindQL FIND query over stored memory, and it illustrates the query format with a concrete example. The MindQL framing effectively separates it from keyword search or plain listing, though no sibling tool is named explicitly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides strong when-not guidance: only FIND is supported, only against thoughts, edges, or actions, and FIND embeddings is refused with a stated reason. It does not route the agent between this and sibling read tools such as search_memory or list_memory, so it stops short of the 5 bar.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_keywordsARead-only
Full-text BM25 keyword search over stored memory. Returns ranked thought identifiers with scores. Archived thoughts are never returned; this tool has no filter to widen that.
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | ||
| top_k | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, so safety is covered; the description adds genuinely new behavioral facts: results are ranked with scores, archived thoughts are excluded, and there is no parameter to widen scope. That last constraint is exactly the kind of non-obvious behavior an agent needs. It stops short of describing pagination or scoring normalization.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences, each load-bearing: purpose, return shape, and the exclusion constraint. No filler, and the core capability is front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Output schema exists and the description still helpfully summarizes the return shape, and read-only safety is annotated. The significant remaining gap is parameter semantics: with a 0% schema coverage on two parameters, an agent lacks guidance on query syntax and result-set sizing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0% for two parameters, so the description must carry the burden, and it does not: neither 'query' (syntax, whether BM25 operators are supported) nor 'top_k' (default 10, max 1000) is addressed. The only parameter-adjacent statement is the negative one about no filter existing, which is marginal.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Full-text BM25 keyword search over stored memory') plus the return shape ('ranked thought identifiers with scores'), which is more than the bare name conveys. It does not, however, distinguish itself from siblings like search_memory or query_memory, so an agent must infer the keyword-vs-semantic split.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The 'BM25 keyword' framing implies exact-term lookup rather than semantic retrieval, which hints at when to pick this over search_memory/query_memory. But no alternative is named and no explicit when/when-not condition is stated, so the routing guidance is only implied.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_memoryARead-only
Hybrid ranked search (lexical + vector + recency) over stored memory. Returns ranked thought identifiers with scores and the search backends that were available. Optionally narrow the ranked hits by thought type, lifecycle status, or priority; these filters are applied after ranking, so a filtered call may return fewer than top_k results and reports how many ranked hits were dropped. Archived thoughts are excluded from ranking by default; set lifecycle_status=ARCHIVED to search them instead. For an exhaustive, unranked, paginated listing by those same fields, use list_memory instead. Recency takes part in the ranking only when you pass recency_now: an ISO-8601 timestamp giving the moment to measure age against (transaction time).
| Name | Required | Description | Default |
|---|---|---|---|
| top_k | No | ||
| priority | No | ||
| query_text | Yes | ||
| recency_now | No | ||
| thought_type | No | ||
| lifecycle_status | No | ||
| include_reflections | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond readOnlyHint=true, the description discloses the ranking signals, return contents, post-ranking filter behavior, dropped-hit reporting, archived handling, and the exact role of recency_now. This gives the agent substantial behavioral context for invoking the search correctly.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is dense but well structured: purpose first, return shape next, then filtering caveats, archived behavior, alternative tool, and recency semantics. Every sentence adds useful information without repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a complex search tool with an output schema and read-only annotation, the description covers nearly everything needed to call it correctly. The main remaining gap is include_reflections, which is neither described nor covered by schema description coverage.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With schema description coverage reported as 0%, the description carries most parameter meaning and does well for the filters, top_k implications, archived behavior, and recency_now. However, it does not explain include_reflections, leaving one non-obvious parameter undocumented in both the description and schema coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description gives a specific verb and resource: hybrid ranked search over stored memory. It also states what is returned (ranked thought identifiers, scores, and available backends) and explicitly distinguishes itself from list_memory.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explains when to use this tool versus list_memory, notes that filters apply after ranking and may reduce results below top_k, and clarifies the default archived exclusion with the lifecycle_status=ARCHIVED alternative.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
store_thoughtB
Create a new thought node. Provide its essence (short canonical text) and full content; optionally set the thought type, priority, source, and confidence. Returns the created thought's identifier and key fields.
| Name | Required | Description | Default |
|---|---|---|---|
| source | No | agent | |
| content | Yes | ||
| essence | Yes | ||
| priority | No | P3 | |
| confidence | No | ||
| thought_id | No | ||
| deduplicate | No | ||
| thought_type | No | NOTE |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=false, idempotentHint=false, and destructiveHint=false, so the safety profile is covered. The description adds that the call returns the created identifier and key fields, which is useful but partially redundant with the output schema. It says nothing about the non-idempotent consequence of repeat calls or what deduplicate actually changes — arguably the most behaviorally significant aspect of a create tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, no filler, required inputs front-loaded before optional ones and the return value last. Nothing to trim.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The output schema and annotations relieve some burden, but a create tool with eight parameters and zero schema-coverage documentation should explain deduplicate and thought_id, which materially change what gets written. As-is an agent could call this correctly for the simple path but would be guessing on the advanced path.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description carries the full burden. It names six of eight parameters, but the only real semantic addition is "essence (short canonical text)"; it omits thought_id and deduplicate entirely, and gives no meaning for priority ordering, confidence range, or thought_type values beyond their names.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ("Create a new thought node") and enumerates the primary inputs, so an agent knows this is the write path for thoughts versus get_thought/update_thought. It never names a sibling explicitly, but the create-vs-update distinction is inferable from the verb.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance on when to use this versus update_thought or link_thoughts, no prerequisites, no mention of when to prefer deduplicate over manual checking. "Optionally set" only describes parameter optionality, not usage conditions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
update_thoughtB
Update fields of an existing thought by identifier. Only the fields you supply change; omit the rest. Can change essence, content, priority, lifecycle status, and confidence.
| Name | Required | Description | Default |
|---|---|---|---|
| content | No | ||
| essence | No | ||
| priority | No | ||
| confidence | No | ||
| thought_id | Yes | ||
| lifecycle_status | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=false, destructiveHint=false, and idempotentHint=false, so safety profile is partly covered. The description usefully adds partial-update (patch) semantics, but omits the transition-enforcement behavior that is a real failure mode of this tool, leaving the agent to discover it from the enum docs.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences, front-loaded with the action and identifier, then the patch constraint, then the field list. No filler; the only mild redundancy is repeating field names already in the schema.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, return values need not be explained, and annotations cover the safety profile. Still, for a mutation tool with state-machine-constrained fields, the description should warn that lifecycle changes are transition-checked and may fail, which it doesn't.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description carries the burden and does list the five mutable fields (essence, content, priority, lifecycle status, confidence), mapping to the properties. It still says nothing about confidence bounds or that lifecycle_status must satisfy the state machine, which the schema's $defs hint at but the description never reinforces.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Specific verb+resource ('Update fields of an existing thought by identifier') with the scope of mutable fields enumerated. It is distinguishable from siblings like get_thought, store_thought, and delete_thought by name and verb, though it never explicitly contrasts with them.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
'Only the fields you supply change; omit the rest' gives clear patch-style usage guidance for the null-defaulted params. However, there is no explicit when-to-use vs. alternatives, no prerequisite on valid lifecycle transitions, and no mention of what happens if an invalid transition is requested.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
13 tool updates
v0.7.0- First observed
delete_edge - First observed
delete_thought - First observed
get_edges - First observed
get_thought - First observed
link_thoughts - First observed
list_edges - First observed
list_memory - First observed
memory_stats - First observed
query_memory - First observed
search_keywords - First observed
search_memory - First observed
store_thought - First observed
update_thought
TDQS
Scored across 13 tools
The four read paths (search_memory, search_keywords, list_memory, query_memory) overlap conceptually, but each description explicitly contrasts itself with the others (ranked vs. unranked, hybrid vs. BM25, structured MindQL) so an agent can pick correctly. Similarly, get_edges (edges touching one thought) vs. list_edges (global filtered edge browse) is distinguishable but confusable on first read.
Most names follow verb_noun, but conventions drift across entities: thoughts use store/get/update/delete_thought while edges use link_thoughts plus delete_edge, and memory_stats is the one noun-only name. The entity vocabulary also shifts between 'thought' and 'memory' (store_thought vs list_memory/search_memory), which muddies the pattern.
13 tools sit comfortably in the well-scoped range for a memory-graph server, with reads, writes, deletes, and analytics each represented. No tool looks like filler or a near-duplicate of another.
Thoughts have full create/read/update/delete plus ranked, keyword, structured, and paged listing, and edges have create/read/delete; deletion cascades are documented. The notable gap is that edges have no update operation, so weight or metadata on an existing edge cannot be changed without deleting and re-linking it.
Maintenance
Related MCP Connectors
Persistent memory, hybrid search and a goal graph for AI agents, over stdio or remote HTTP.
Persistent memory, knowledge graph, task management and more for AI agents via MCP.
Agent-native MCP server over the public saagarpatel.dev corpus. Read-only, stateless.
Analytical memory for AI agents: a real Postgres queried in plain English over MCP. One command.
Related MCP Servers
- AlicenseAqualityBmaintenanceExposes the mindgap knowledge graph as an MCP server over stdio, providing tools to add, link, query, and manage nodes and edges in a local org-roam-style graph.10MIT
- AlicenseNot gradedqualityDmaintenanceProvides a stdio MCP bridge for coding agents to query and record engineering knowledge locally, preserving debugging history, failed attempts, and verified solutions.3 npmMIT

openrhyme-mcpofficial
AlicenseAqualityBmaintenanceEnables any MCP-compatible agent to query a local OpenRhyme activity timeline, search history, and issue control commands over stdio while keeping all data on-machine.5MIT- AlicenseNot gradedqualityAmaintenanceProvides a drop-in MCP memory server over stdio using a local SQLite store, enabling agents to store, search, and audit memory with provenance, scoped access, and contradiction tracking without requiring API keys, LLMs, or embedding providers.318 npm16Apache 2.0