Echo Memory
Echo Memory is an MCP server that gives AI agents a shared, auditable graph memory they can write to and query without server-side model calls.
Store memories:
write_episoderecords entities and facts connecting them, with provenance, confidence, and optional entity resolution for ambiguous mentions.Recall memories:
query_memoryretrieves relevant facts by hybrid vector/full-text search, scoped per agent or shared, withtop_kand an opt-in digest of recent facts.Record when recall helped:
record_recall_savemarks that a recalled fact saved the user from re-explaining something, gated by a realfact_idand note.Inspect history:
get_audit_logreturns a chronological, human-readable trail of what was written, invalidated, superseded, or resolved.Manage pending memory files: the broader toolset also exposes
pending_documentsandmark_ingestedto bring model-extracted memory files into the graph.
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., "@Echo MemoryEcho Memory, remember that the API rate limit is now 100 req/min."
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.
Echo Memory
Shared memory for AI agents, as a graph in your own database. What Claude Code learns, Cursor and Codex can recall. Every fact records who wrote it and when, and the server never calls a model to store one.
Your agents start every session from zero. The usual fix is a notes file you paste into context, which grows until it is mostly irrelevant to whatever you are asking. Echo Memory is the other shape: facts connected to each other, and a query that returns the few that matter. On the author's own store that is 96.7% less context for the same answer, with the answer still present 87.2% of the time across 1,190 questions.
write_episode query_memory
billing ──uses──▸ Razorpay "how do we take payments"
│ written by claude-code ▸ billing uses Razorpay, not Stripe
│ supersedes ──▸ Stripe written by claude-code, 3 days ago
└ no model invoked ▸ 1,372 tokens, not 41,838Install
Requires: Python 3.11+ and Docker (for the database).
pipx install echo-mem
echo-memory quickstartquickstart starts the database, applies the schema, and prints the claude mcp add
line that registers it, filled in with the port it actually used. The Postgres image is
published, so nothing compiles.
Or use the hosted service and run no database at all:
pipx install echo-mem
echo-memory connect <key> # a key from https://app.echo-mem.comThen once per machine, so an agent knows when to record and recall rather than only that the tools exist:
echo-memory install --globalRestart your client afterwards. An MCP server is a long lived process that holds the code and config it started with, and an editable install does not change that.
The PyPI name is
echo-mem, notecho-memory. That name belongs to an unrelated hosted product. The import package and the CLI are bothecho_memory/echo-memory; only the distribution name differs.
Related MCP server: smriti-memcore
Usage
echo-memory status # what each scope holds, and which agents have written
echo-memory health # a score, what is weak, and what to do about it
echo-memory dashboard --serve # the graph, in a browser, localhost only
echo-memory why <fact_id> # the full audit trail for one fact
echo-memory recall "<question>" # query the store from a terminal
echo-memory export # everything, as JSON
echo-memory install --for cursor # wire one client, project scoped
echo-memory adopt # wire every MCP client on the machine, each with its own id
echo-memory eval # retrieval quality against your own store
echo-memory eval --context # what a recall costs against injecting everything
echo-memory eval --context --sweep # the same, as a curve across corpus size
echo-memory calibrate # is entity resolution trustworthy on your data
echo-memory benchmark # write, query and digest latencyThe six MCP tools
Tool | What it does |
| Store entities and the facts connecting them. No model call. |
| Hybrid vector and full text retrieval, fused by reciprocal rank. |
| Mark that a recalled fact saved re explaining something. Refuses a fact no read returned. |
| Every change to memory, with a plain language reason. |
| Memory files this project wrote that the graph has not heard about. |
| Close one of those out. |
What you get
A graph, not a list. Entities are nodes and a fact is an edge between two of them. Two sessions that never knew about each other resolve onto the same entity by name, so the second inherits what the first learned.
Bounded retrieval. Old, rarely read memory consolidates into higher level summaries over time. Nothing is discarded; what changes is how much a query has to walk.
Provenance on every fact. Who wrote it, which tool, which project, when, and which reads returned it. A superseded fact is never deleted. It stops being drawn and stays reachable with its history.
Causal typing. Edges can be tagged caused_by, led_to, blocked_by,
contradicts, set by the agent's own read of the conversation rather than inferred
statistically.
No inference on the write path. Extraction happens in the calling agent, so storing a memory invokes no model on the server. The cost moved rather than vanished: the agent has to arrive with entities and facts already extracted, which is what the tool contract spells out. The comparison that makes this matter is Zep/Graphiti, the closest architectural match, whose own description of ingestion is that "every episode triggers multiple LLM calls" and that "write cost scales with volume".
The obvious reply is that cheap writes are cheap because they do less, and that reply is
correct on the mechanism. docs/WRITE-COST.md answers it properly,
including the two measured costs of the choice: the Stop gate fired seven times and
produced one fact, and a write touching an ambiguous entity is deferred while the call
returns as though it succeeded.
Any MCP client. A coding assistant, a chatbot, an ops agent, or something built in house. Coding agents are where this is proven, not what it is limited to.
Numbers, and how they were taken
Every figure comes from this repository or a live store, on a date, with the command that reproduces it on yours. The corpus is small and the noise floor is stated, because a difference nobody sized is not a result.
Measure | Value | Reproduce |
Context per recall vs injecting everything | 96.7% less, hit@10 0.872 over 1,190 questions |
|
The same saving across 8x of corpus growth | 75.5% at 32 facts rising to 96.4% at 261, hit@10 0.900 to 0.946 |
|
LoCoMo retrieval, 1,982 questions, 5,882 turns | recall@10 0.601, hit@10 0.658, MRR 0.460 |
|
LongMemEval retrieval, 90 questions, 15 per type | session@10 0.940, turn@10 0.727 |
|
Server side model calls per write | 0 |
|
Write, query, digest latency (median) | 15ms, 8ms, 1ms |
|
Entity resolution AUC | 0.666, 95% CI [0.421, 0.881] |
|
That last row is the one that went the wrong way, and it is here on purpose. The interval includes chance, so the unattended merge is switched off: at the automatic bar precision was 50% over two reviewed pairs, and the audit log showed that path had fired once in the system's entire history. A near match is now offered for confirmation instead.
The LoCoMo row is retrieval, not QA accuracy. Published LoCoMo results have a model write
an answer and a second model judge it; this asks only whether the turn holding the answer
came back, which is a ceiling on QA accuracy rather than a substitute for it, and is not
comparable to anybody's published QA figure. It also feeds raw dialogue turns, which skips
the extraction step this design pushes to the calling agent, so it is a floor as well as a
ceiling. The worst row, multi hop at recall@1 0.099, is in
docs/BENCHMARKS.md with the rest.
The context saving is measured against a specific baseline, stated so it cannot be read as more than it is. Not "no memory at all", which is however long a human spends re explaining and is unmeasurable. It is the thing people do instead: keep the project's notes in one file and paste the whole file. On that store the file is 325 facts, about 41,838 tokens; a recall returned 1,372 on average. The hit rate belongs beside it, because a recall that returned nothing would score 100%.
The graph
Memory is a graph, not a list of notes. Entities are nodes; a fact is an edge between two of them. That is the whole data model, and everything else follows from it.

Three projects here. checkout-api, mobile-app and data-pipeline were recorded in
separate sessions and never told about each other, yet the picture already separates them,
because separation is a property of the edges rather than a label anyone applied.
Clusters come from structure. Densely connected facts are grouped by label propagation
over the edges, and each cluster is named after its most connected node. That is why
data-pipeline sits apart: nothing it knows touches payments. It is also why
checkout-api and mobile-app share a cluster despite being different codebases. They
genuinely share an idea, and the graph found it rather than being told.
Components are the stronger claim. Two nodes in different components have no path between them at all, which is the strongest statement this graph can make that two memories are unrelated.
Click a node: everything it takes part in

idempotency keys is the largest node here and nobody made it large: seventeen facts from
several services resolved onto one entity by name. The panel lists every one, with which
agent wrote it and when.
Click a link: why memory believes it

Not a tooltip. Who wrote the fact, in which project, when, and how each of its entities
resolved. echo-memory why <fact_id> prints the same trail in a terminal.
Seeing your own
echo-memory dashboard --serve --openThe images above come from a synthetic dataset (scripts/demo-seed.py) rather than a real
store, for the obvious reason: a real memory graph is full of hostnames, account numbers
and client names.
Wiring more than one tool
Give each client its own ECHO_MEMORY_AGENT_ID. Cursor should say cursor, Claude
Desktop claude-desktop. Memory is shared either way, but a fact records which tool
learned it, and two tools claiming the same id makes cross tool recall impossible to see
afterwards.
echo-memory adopt # every MCP client on the machine, each with its own id
echo-memory install [path] # one project: MCP config plus a skill, committed with the codeadopt shows the diff before writing anything. For an agent that does not speak MCP, see
docs/INTEGRATIONS.md.
Is the graph in good shape?
echo-memory healthA score, what is strong, what needs attention, and what to do about each, including what
recall has cost: how often memory was read, how often a read returned anything, roughly
how many tokens were injected, and how many saves those reads produced. Writes were
counted from the start; reads were not counted at all, so nothing could answer whether
recall earns what it costs. It exists to be run when you have no question, because a store
can look healthy by every other number while most of its facts came from a bulk import,
the last real write was a week ago, and only one of several wired agents has ever written
anything. --json for machine readable output.
Nothing in it is gated. The paid plan sells hosting; diagnostics about your own data are not a thing to withhold from the person whose data it is.
Architecture
Storage PostgreSQL with pgvector and Apache AGE, from a single local agent up to an
organisation wide shared graph, with no forced migration later. The novel work is the
memory structure and the read/write algorithm on top of it, not a new database engine.
Retrieval Hybrid vector and full text search fused by reciprocal rank in v1a.
Personalised PageRank via networkx lands in v1b for multi hop associative retrieval.
Interface Model Context Protocol, so any compliant agent reads and writes the same graph.
Status
Early and staged, on purpose. See docs/designs/ for the architecture
and the v1a to v1b plan.
v1a, built | Basic recall. Six MCP tools, thirty CLI commands, on PyPI and in the MCP registry. |
v1b, gated | Causal typing and multi hop retrieval. 187 questions no single fact answers score MRR 0.212 today; the number to beat exists before the feature does. |
v1.1, planned | Organisation wide tenancy: per agent, per team, or org wide graphs. |
The validated wedge driving v1a is memory shared across coding agents, which is the author's own daily pain and the case with the most evidence behind it. Everything else is the target this architecture is built toward.
Hosted
Running it yourself is free forever under Apache 2.0, with no account and no feature held back. app.echo-mem.com runs the database for you at $99 a month if you would rather not.
See CONTRIBUTING.md. Issues and pull requests welcome; please read the
design docs first so proposals fit the staged build plan. A first pull request is asked to
sign the Contributor License Agreement, once, in the PR thread.
The most useful contribution is a measurement that disagrees with one of the numbers
above. Run echo-memory eval, calibrate or benchmark on your own store and open an
issue with the output.
License
Apache License 2.0. See LICENSE.
mcp-name: io.github.ayushcodes10/echo-mem
Available Tools
4 toolsget_audit_logCInspect
Human-readable audit trail: what was written, invalidated, superseded, or resolved, and why. since is an ISO8601 timestamp; entries at or after it, chronologically ordered.
| Name | Required | Description | Default |
|---|---|---|---|
| scope | Yes | ||
| since | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the burden for behavioral disclosure. It usefully explains that results are chronological, filtered by 'since', and cover certain event types. However, it does not disclose pagination, response shape, or the behavior when 'since' is null.
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 tight and front-loaded, with the core purpose stated first and the 'since' behavior in the second sentence. It wastes no words, though the missing scope explanation prevents a top score.
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 tool with no annotations and no output schema, the description leaves important gaps: it does not define the required 'scope' parameter, describe the return structure, or state how 'since' defaults behave. The event-type list is helpful but only partially completes the picture.
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 must compensate. It clearly documents the 'since' parameter as an ISO8601 timestamp with ordering semantics, but it does not explain the meaning of the required 'scope' parameter at all, leaving a significant 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?
The description identifies the tool as a human-readable audit trail and lists the event categories it covers (written, invalidated, superseded, resolved) plus the rationale. This distinguishes it from the sibling memory operations, though it lacks an explicit retrieval verb like 'gets' or 'returns'.
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 description implies this is for viewing historical audit information but gives no explicit guidance on when to choose this over write_episode, query_memory, or record_recall_save. There are no stated exclusions, prerequisites, or alternative routing conditions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
query_memoryAInspect
Recall prior facts relevant to query, from this agent's own memory (scope="solo") or the pool shared across this user's agents (scope="shared"). Call this at session start, and any other time recalling prior context would save the user from re-explaining something - check here before asking them to repeat themselves or guessing at context you don't have.
digest=True ignores query and returns the most recently written active facts instead, as an opt-in "catch me up" convenience; call it explicitly at session start if you want one, it's never automatic.
A pending_ingest field appears when memory files have been written that
the graph hasn't heard about yet. Read each listed file and call
write_episode with the entities and facts it states, then mark it done
with echo-memory pending --done <path>. The queue exists because
extraction needs a model and this server never calls one.
| Name | Required | Description | Default |
|---|---|---|---|
| query | No | ||
| scope | Yes | ||
| top_k | No | ||
| digest | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does well: it discloses that digest=True ignores the query, returns the most recently written active facts, and is never automatic. It also reveals the pending_ingest field behavior and why the queue exists, which is valuable operational context.
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 front-loaded with the main purpose, then usage, then digest, then the pending_ingest workflow. Each paragraph is relevant and non-redundant; the length is justified by the tool's complexity.
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 description covers purpose, usage timing, scope semantics, digest behavior, and the pending_ingest workflow. It is less complete on the output format of ordinary recall results and top_k semantics, which matters more because there is no output schema.
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 has 0% description coverage, so the description must compensate. It explains scope values ('solo' vs 'shared') and the digest parameter's behavior in detail. However, top_k is never mentioned, and the behavior of a null query without digest is left unspecified.
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 states a specific verb and resource: 'Recall prior facts relevant to query' from memory. It immediately clarifies the two scopes ('solo' vs 'shared'), making the tool's function unmistakable and distinct from write-oriented siblings like write_episode.
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 explicitly prescribed: 'Call this at session start, and any other time recalling prior context would save the user from re-explaining something.' It also tells the agent to check here before asking the user to repeat themselves, and it explains when digest should be invoked explicitly.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
record_recall_saveAInspect
Record that a fact you recalled from memory saved the user from re-explaining something to you.
Call this IN THE SAME TURN, the moment it happens. The trigger is concrete: you called query_memory (or read a memory-derived fact), it answered something the user would otherwise have had to tell you again, and the fact was originally written by a DIFFERENT tool or a past session.
That last part is the whole point, and it is why this takes fact_id
rather than a written_by string. Pass the fact_id of the fact that
helped - every query_memory result carries one. The server reads that
edge's own agent_id and uses it as written_by; the caller does not get
to assert who wrote a fact.
Until 2026-08-29 written_by was free text supplied by the caller. Nothing
checked the fact existed, so the number gating v1a was a string typed by
the model being graded. A fact_id is checkable, so the reading is
admissible.
recalled_by is you, defaulting to this server's own agent id. If the fact's author and you are the same tool, the save is still recorded but does not count toward the trial's bar - recalling your own note from ten minutes ago is not the thing being measured.
note should be one sentence naming what it saved re-explaining, written so it still makes sense read cold in six months. Recording the identical note twice is a no-op, so a retry after an error is safe.
Do NOT call this speculatively, for a fact you wrote this session, or because a recall was merely interesting. It is evidence for a gate that decides real build work; an inflated count is worse than an empty one.
| Name | Required | Description | Default |
|---|---|---|---|
| note | Yes | ||
| scope | Yes | ||
| fact_id | Yes | ||
| recalled_by | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and handles it thoroughly. It discloses idempotency (duplicate note is a no-op), disqualification (same-tool recalls are recorded but do not count), server-side written_by resolution, and the consequences of inflated counts. It also warns that the caller cannot assert authorship.
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 front-loaded with the core action and trigger, then organized into focused paragraphs. It is long, but the behavior is subtle enough to justify the length. The historical note about v1a is arguably redundant for callers, but it does explain why fact_id is required.
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 description is unusually complete for a recording tool: it explains when, why, and how to call it, including edge cases and disqualifying conditions. It falls short of a 5 only because the required `scope` parameter remains undocumented and success/error behavior is not explicitly described beyond the duplicate no-op.
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 description adds meaningful context for fact_id, note, and recalled_by, going well beyond the bare schema. However, schema coverage is 0% and the required `scope` parameter is never explained, leaving a significant gap in a required field.
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 opens with a specific verb and resource: 'Record that a fact you recalled from memory saved the user from re-explaining something to you.' This clearly distinguishes it from siblings like query_memory (which reads memory) and write_episode (which writes memory) by positioning it as a post-recall evidence-recording action.
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 description gives an explicit trigger condition: call in the same turn, only when query_memory returned a memory-derived fact that would otherwise require re-explanation, and only when the fact was written by another tool or past session. It also lists clear exclusions: do not call speculatively, for facts written this session, or simply because the recall was interesting.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
write_episodeAInspect
Record something worth remembering later: a decision, a correction, a stated preference, or context that would otherwise have to be re-explained to a different tool or a future session. Call this proactively and immediately when you notice one of these - don't wait to be asked, and don't batch it up for later in the conversation. The cost of a missed memory (re-explaining something later) is higher than the cost of one extra call.
You (the calling agent) extract entities/facts yourself - this server never calls an LLM. Exact shape, every key required unless marked optional:
entities: [{"name": "Postgres", "type": "tool"}, ...]
name: non-empty string, unique per entity in this call
type: any short string describing what kind of thing this is (e.g. "tool", "person", "decision", "preference") - your choice, not a fixed enum
facts: [{"source": "Decision", "target": "Postgres", "relation_type": "uses", "fact": "decided to use Postgres for storage", "confidence": "extracted"}, ...]
source/target: must each exactly match a "name" in entities above
relation_type: any short string describing the relationship (e.g. "uses", "prefers", "caused_by") - your choice, not a fixed enum
fact: the actual sentence to remember, plain text
confidence: MUST be exactly one of "extracted" (directly stated), "inferred" (you deduced it), or "ambiguous" (uncertain) - any other value, including numbers or omitting it, is rejected
entity_resolutions (optional): only needed when a previous call returned ambiguous_entities and you're now confirming which candidate a mention refers to, or that it's new: {"mention name": {"resolved_to": "" | "new"}}. Omit entirely on a call with no prior ambiguity to resolve.
Example call: write_episode(scope="solo", session_id="sess-1", entities=[{"name": "Postgres", "type": "tool"}, {"name": "Decision", "type": "decision"}], facts=[{"source": "Decision", "target": "Postgres", "relation_type": "uses", "fact": "decided to use Postgres for storage", "confidence": "extracted"}])
| Name | Required | Description | Default |
|---|---|---|---|
| facts | Yes | ||
| scope | Yes | ||
| entities | Yes | ||
| session_id | Yes | ||
| entity_resolutions | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden and meets it thoroughly. It discloses that the server never calls an LLM and that the calling agent must extract entities/facts itself, specifies that the confidence value must be exactly one of three literal strings or the call is rejected, and explains when entity_resolutions is required. It also documents the strict matching constraint between fact source/target and entity names, giving the agent a clear behavioral model.
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 long but every sentence earns its place: it front-loads the purpose, gives precise field-by-field shapes and validation rules, and ends with a concrete example. Given that the schema provides no property descriptions, the length is justified and well-structured rather than verbose.
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 5-parameter tool with no annotations, no output schema, and an empty schema, the description covers the entities/facts structure, confidence validation, optional entity_resolutions flow, and an example. It falls short on the semantics of scope and session_id, and it does not describe what the tool returns in response, so an agent still has some uncertainty about the complete call contract.
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 input schema is nearly empty (objects with additionalProperties: true and 0% description coverage), so the description must compensate. It richly defines entities (name, type, uniqueness), facts (source/target/relation_type/fact/confidence with validation), and entity_resolutions (resolved_to or new). However, the two required parameters scope and session_id are only shown in the example call and never semantically defined, leaving a gap in compensation.
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 a specific verb and resource: 'Record something worth remembering later' and enumerates concrete examples (a decision, a correction, a stated preference, or context). It does not explicitly contrast itself with the sibling tool 'record_recall_save', so an agent cannot immediately distinguish between the two write-like tools, which prevents a 5.
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 description gives explicit situational triggers: 'Call this proactively and immediately when you notice one of these - don't wait to be asked, and don't batch it up for later in the conversation.' It also explains the cost-benefit rationale for erring on the side of calling. However, it does not mention any alternatives or state when not to use the tool, so it lacks exclusions and sibling routing.
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.
4 tool updates
v0.1.0- First observed
get_audit_log - First observed
query_memory - First observed
record_recall_save - First observed
write_episode
TDQS
Scored across 4 tools
write_episode creates new memory, query_memory retrieves it, get_audit_log inspects history, and record_recall_save logs a specific recall-save event. Even the two 'record' tools are cleanly separated by what they write: episode facts versus a recall-save reference.
All four tools follow the same imperative verb_snake_case convention: write_episode, query_memory, get_audit_log, record_recall_save. There is no mixing of camelCase or inconsistent verb styles.
Four tools is well-scoped for a memory server: a write path, a query path, a history/audit path, and a meta-tracking path. No tool feels redundant, and none is missing for the stated purpose.
The core write-query-audit loop is covered, and agents can work around stale facts by writing corrections. The main gaps are the lack of an explicit invalidate/delete tool and the fact that completing the pending-ingest workflow requires an external CLI command, but these are minor rather than fatal.
Maintenance
Related MCP Connectors
Long-term memory for AI agents: durable records, observable retrieval, governed context assembly.
Graph-native persistent memory for AI agents — 33 MCP tools, zero-LLM writes.
Long-term memory for AI agents: semantic facts, episodic events, and procedural workflows
- memoryOAuthcom.humaux
Persistent long-term memory for AI agents: semantic search, knowledge graph, and task canvas.
Related MCP Servers
- AlicenseBqualityAmaintenanceCausal graph memory engine for AI agents. Scores memories using relevance × connectivity × reactivation, connects them in a causal graph, and actively forgets irrelevant ones. 11 MCP tools including store, recall, search, traverse, and explain.1337 PyPI27AGPL 3.0
- AlicenseNot gradedqualityAmaintenanceA neuro-inspired long-term memory architecture for AI agents.186 PyPI3MIT
- AlicenseNot gradedqualityCmaintenancePersistent memory infrastructure for AI agents, enabling cross-session recall and autonomous memory evolution via an MCP server.1MIT
- AlicenseAqualityCmaintenanceAn MCP server providing long-term memory for AI agents with forgetting curves, consolidation, and graph-based retrieval.1014 npmMIT