Skip to main content
Glama

qcdoc-mem

Persistent long-term memory for AI agents, served over MCP.

Connect an MCP client, pass a user_id, and the agent remembers: facts are extracted from conversations, stored as plain files on disk, and handed back for injection into later sessions. No database to operate, no vector store, no embedding pipeline.

agent ──► memory_remember_conversation ──► LLM extraction ──► facts/*.md + memory.json
agent ◄── memory_context / memory_search ◄── budgeted injection ◄──┘

python mcp tests license


Why

LLMs are stateless. Every session starts blank, so the user re-introduces themselves, re-states preferences, and re-corrects the same mistakes. qcdoc-mem is the memory subsystem that fixes that, packaged as a standalone service:

  • It lives outside your agent. One process serves any number of agents over MCP or an in-process SDK. Your client only needs the tool names.

  • It decides what to remember. You hand over the conversation; an LLM extracts durable facts, scores their confidence, drops the noise, dedupes near-identical entries, and merges fragments over time.

  • It is inspectable. Memory is Markdown and JSON on disk. You can read it, grep it, diff it, edit it, back it up with rsync, and recover it without a database.

Related MCP server: engram

What you get

10 MCP tools

recall, explicit saves, automatic conversation extraction, fact CRUD, erasure, flush, status. See docs/tools.md.

Two write paths

memory_remember for facts you can already state (no LLM needed); memory_remember_conversation to hand over a session and let extraction decide.

Three-layer isolation

per user_id, per agent_name, with an explicit strict_user_scope switch for multi-tenant deployments.

Lifecycle management

confidence gates, two-level dedup, max_facts capacity eviction, staleness review, and fragment consolidation. See docs/architecture.md.

Budgeted injection

the memory block is ranked and truncated to a token budget, with correction facts in a protected reserve.

No infrastructure

Markdown facts + a JSON summary + an embedded SQLite FTS5 index that is derived and rebuildable. See docs/operations.md.

Swappable backend

the whole memory system sits behind a MemoryManager contract. See docs/extending.md.


Quick start

Requires Python 3.12+.

uv sync                      # or: pip install -e .
uv run qcdoc-mem-mcp         # streamable HTTP on http://127.0.0.1:8130/mcp

Or, for a client that spawns the server itself:

uv run qcdoc-mem-mcp --transport stdio

Point your MCP client at it:

{
  "mcpServers": {
    "qcdoc-mem": {
      "type": "http",
      "url": "http://127.0.0.1:8130/mcp"
    }
  }
}

Optional extras:

uv sync --extra cjk          # jieba word segmentation, better Chinese/Japanese/Korean recall

No built-in authentication. The server binds to loopback by default for exactly that reason. If you expose it, put authentication in front of it -- anyone who can reach the port can read and write every user's memory.

Give it an LLM

Reads, explicit saves, and fact CRUD work with no model. Automatic extraction from conversations needs one. Point qcdoc-mem at any OpenAI-compatible endpoint:

# qcdoc-mem.config.yaml
memory:
  backend_config:
    model:
      provider: openai                      # anything init_chat_model supports
      model: deepseek-chat
      base_url: https://api.deepseek.com/v1

Run qcdoc-mem-mcp and call memory_status: it reports llm_configured: true when the model resolved. A misconfigured model does not crash startup -- reads keep working and extraction fails at call time with a clear error.

The API key comes from the environment, never from the file -- the config file is not interpolated, so a ${VAR} written there would be sent as the key verbatim. Either export QCDOC_MEM_LLM_API_KEY, or omit api_key entirely and let the provider read its own variable (OPENAI_API_KEY, ANTHROPIC_API_KEY, ...). See docs/configuration.md.


The 10 tools

Tool

One line

Needs LLM

memory_context

Load memory as injection-ready text. Call once at the start of a task.

no

memory_search

Find facts by query. Call before asking the user to repeat themselves.

no

memory_get

Return the whole memory document (summaries + facts). For inspection/export.

no

memory_remember

Store one durable fact. Idempotent on exact content.

no

memory_remember_conversation

Hand a session over for automatic extraction.

yes

memory_update_fact

Edit a fact by id; omitted fields keep their value.

no

memory_delete_fact

Delete one fact by id.

no

memory_forget

Erase a user's memory and cancel its pending extractions.

no

memory_flush

Force pending extractions to run now.

no

memory_status

Report backend, mode, storage path, whether a model is configured.

no

Plus one MCP resource: qcdoc-mem://status.

Every tool takes optional user_id / agent_name; set default_user_id on the server and a single-tenant client can omit them entirely.

Full reference -- every parameter, every return shape, when to call it and in which phase of the agent loop: docs/tools.md.

Errors

Tools never raise at the model. They return {"error": "...", "kind": "..."}, where kind is one of:

kind

Meaning

invalid_request

The caller's input was wrong (empty query, unknown role, bad confidence).

unsupported

The configured backend does not implement that operation.

backend_error

Storage or the backend failed.


How it works

write path (asynchronous, batched)
  client ── memory_remember_conversation ──► debounce queue
            ──► prompt assembly (current memory + conversation + hints)
            ──► one LLM call ──► JSON with 6 decision types
            ──► deterministic gates ──► dedup ──► capacity eviction ──► files

read path (synchronous, per turn)
  client ── memory_context ──► load bucket ──► rank ──► token budget ──► text
  client ── memory_search  ──► FTS5 (or lexical relevance) ──► ranked facts

The design in one paragraph: one conversation turn produces at most one LLM call, and that call is asked to do six jobs at once -- update the six summary sections, add new facts, reinforce confirmed facts, remove contradicted facts, re-adjudicate aged facts, and merge fragments. Everything the model proposes then passes through deterministic code: a write gate that rejects anything not scope=user + durable + descriptive, a confidence floor, exact and near-duplicate dedup, and a capacity cap. The model proposes; the code decides.

Read docs/architecture.md for the full mechanism -- data model, both pipelines step by step, every gate, the concurrency protocol, and the isolation model.


Using it in an agent loop

qcdoc-mem does not hook your agent -- it cannot see your turns. The client owns three moments:

Phase

Call

Why

Session start

memory_context

Prepend the returned text to the system prompt.

Before asking the user to repeat

memory_search

Only if facts were not already injected.

Session end

memory_remember_conversation then memory_flush

Capture the session; the flush matters because extraction is batched.

The server's MCP instructions tell the model when to make these calls, so a client that surfaces them gets the behaviour with no integration code. If you want automatic capture/injection at the framework level (LangGraph middleware, turn hooks), you write that layer -- see docs/integration.md for recipes and for the automatic-capture behaviour that this package deliberately leaves to you.


SDK

The same operations in-process, no MCP:

from qcdoc_mem.contract import get_memory_manager
from qcdoc_mem.service import MemoryService
from qcdoc_mem.settings import configure_defaults

server_settings = configure_defaults()          # env + optional config file
service = MemoryService(get_memory_manager(), server_settings)

service.remember("prefers uv over pip", user_id="alice", category="preference")
print(service.context(user_id="alice")["context"])
print(service.search("uv", user_id="alice")["results"])

Or talk to the backend contract directly, bypassing the facade:

from qcdoc_mem.contract import HostHooks, MemorySettings, build_memory_manager

manager = build_memory_manager(
    MemorySettings(backend_config={"storage_path": "/var/lib/qcdoc-mem"}),
    HostHooks(),
)
print(manager.get_context("alice"))

Documentation

Start at docs/README.md, which maps every document and gives lookup tables by task ("store a fact now", "why is my read empty", "point it at DeepSeek", ...).

Document

What is in it

docs/README.md

The index: reading paths by role, and "I want to..." lookups.

docs/tools.md

Every MCP tool: parameters, returns, when to call it, which phase of the loop, worked examples, error handling.

docs/architecture.md

Principles, data model, the write and read pipelines step by step, gates, dedup, eviction, staleness, consolidation, concurrency, isolation, observability.

docs/integration.md

Putting it in an agent loop: phases, recipes, multi-tenant identity, and the automatic-capture layer this package does not ship.

docs/configuration.md

Full config reference: precedence, every environment variable, every CLI flag, every backend field with defaults and bounds.

docs/operations.md

Storage layout, backup and recovery, migration, concurrency limits, troubleshooting, known limitations.

docs/extending.md

Swapping the backend, the storage class, the retrieval adapter, the prompts, and the signal patterns.

examples/README.md

Five runnable examples: in-process SDK, agent loop, multi-tenant isolation, a real MCP client, and live LLM extraction.


Where memory lives

<data-dir>/
├── .retrieval/memory-fts5.sqlite3          derived FTS5 index (rebuildable)
└── users/{user_id}/
    ├── memory.json                         six summary sections + revision
    ├── .memory.lock                        cross-process lock
    └── agents/{agent_name}/
        ├── facts/{ab}/{fact_id}.md         one Markdown file per fact
        └── .metadata/                      access counters, eviction audit

Data root resolution: memory.backend_config.storage_path > $QCDOC_MEM_DATA_DIR > ~/.qcdoc-mem. Details, including what is safe to delete, are in docs/operations.md.


Development

uv run pytest                        # 58 tests
uv run pytest tests/test_mcp_server.py -q
uv run python examples/run_all.py    # every offline example, ~5s
uv run python scripts/check_doc_links.py   # docs links and anchors

The MCP tests drive the real tool-dispatch path over FastMCP's in-memory transport, so nothing binds a port. 04_mcp_client.py is the exception: it starts a real server on a free port and drives it over HTTP, then shuts it down.

Credits

The memory backend under src/qcdoc_mem/backends/qcdoc_mem/ is derived from the memory subsystem of deer-flow, at backend/packages/harness/deerflow/agents/memory/, adapted into this standalone service. The adaptation is mechanical: module paths, class names, the environment-variable prefix, the configuration filename and the default storage root were renamed, and the host-coupled layers were replaced by this package's own contract/, service.py, settings.py and mcp/ packages. The storage, extraction, retrieval and lifecycle logic itself originates upstream.

That project is MIT licensed. Its copyright notice is reproduced in THIRD-PARTY-NOTICES.md, which ships with the package.

License

MIT -- see LICENSE. Third-party copyright notices are in THIRD-PARTY-NOTICES.md.

Available Tools

10 tools
memory_contextMemory ContextA

Load the user's memory as text ready to put in your context.

Call this once near the start of a task. The returned context string is the backend's own injection format and should be treated as opaque text -- prepend it to the conversation rather than parsing it.

ParametersJSON Schema
NameRequiredDescriptionDefault
queryNoOptional current-task hint; backends with relevance ranking use it to prioritise more useful memories.
user_idNoWhose memory to load. Defaults to the configured user.
thread_idNoOptional conversation id, for backends that scope reads by thread.
agent_nameNoOptional per-agent bucket.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full behavioral disclosure burden. It meaningfully discloses that the returned context is 'the backend's own injection format' and should be treated as opaque text, and it advises calling only once. This is valuable behavioral context beyond what the schema provides, though it does not mention side effects, errors, or auth requirements.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is compact and front-loaded: the main action in the first sentence, usage timing in the second, and the critical behavioral caveat in the third. Every sentence earns its place with no redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description covers the essential operational details: when to call, what the result is, and how to handle it. An output schema exists to document return values. The only minor gap is lack of guidance on what happens when there is no memory or how this relates to sibling memory tools.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents all four optional parameters. The description adds no further parameter-specific meaning, which keeps this at the baseline score of 3.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource ('Load the user's memory') and defines the output as 'text ready to put in your context.' The additional note about the backend's injection format and prepending it to the conversation clearly separates this from sibling tools like memory_search or memory_get, which imply structured retrieval.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives clear when-to-use guidance: 'Call this once near the start of a task.' It also explains how to use the result ('prepend it to the conversation rather than parsing it'). However, it does not explicitly name alternative tools or state when not to use this tool, so it falls short of a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

memory_delete_factMemory Delete FactA

Delete a single fact by id.

Use when the user says a stored fact is wrong or no longer applies.

ParametersJSON Schema
NameRequiredDescriptionDefault
fact_idYesId of the fact to delete (from `memory_search`).
user_idNoWhose memory the fact belongs to.
agent_nameNoOptional per-agent bucket.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A3.7/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden of behavioral disclosure. It states 'Delete' but doesn't mention irreversibility, potential side effects, permissions required, or the behavior when the fact_id doesn't exist. The optional user_id and agent_name parameters are not explained in terms of their effect on deletion scope.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is extremely concise, with two short sentences that front-load the core purpose and usage. Every word serves a purpose, with no redundancy or filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple delete-by-id tool, the description covers the basic usage but lacks important context such as irreversibility, error handling, or scope implications of the optional parameters. Given the destructive nature and lack of annotations, more detail would be appropriate.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so each parameter is already documented. The description adds a helpful reference for fact_id ('from `memory_search`'), but the optional parameters' semantics are left to the schema. Overall, it provides marginal added value over the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action (delete a single fact) and the resource (by id), making the tool's purpose unambiguous. It also distinguishes it from update and search siblings by emphasizing deletion of a specific fact.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides a clear trigger: 'Use when the user says a stored fact is wrong or no longer applies.' This gives direct guidance on when to invoke the tool, though it doesn't explicitly mention alternatives or when not to use it.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

memory_flushMemory FlushA

Force pending memory extractions to run now, within a time budget.

Useful before shutting down, or when a client wants the memory written before it reports success.

ParametersJSON Schema
NameRequiredDescriptionDefault
timeoutNoHard upper bound in seconds. Defaults to the server's configured shutdown budget.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden of behavioral disclosure. It reveals that the operation is forced and time-bounded, but doesn't state whether it modifies persistent state, what happens if the timeout is exceeded, or whether it is safe to call repeatedly. The use case hints at a write operation but doesn't fully disclose side effects.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences with zero waste. The action is front-loaded in the first sentence, and the second sentence provides practical context. Every word earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple tool with one optional parameter and an output schema, the description adequately covers purpose, usage timing, and the timeout concept. Given no annotations, it could mention that this is a write/mutation operation more explicitly, but the picture is largely complete for an agent to call it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% for the single parameter (timeout), so baseline is 3. The description's reference to a 'time budget' loosely maps to the parameter, but it adds no new semantic detail beyond what the schema already provides.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Force pending memory extractions to run now'), which clearly distinguishes it from sibling tools like memory_get, memory_search, and memory_remember. The action is unambiguous and the name 'flush' is reinforced by the description.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides concrete use cases ('before shutting down' and 'when a client wants the memory written before it reports success') that tell an agent when to invoke it. It doesn't explicitly mention when not to use it, but the two scenarios are clear and cover the main need.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

memory_forgetMemory ForgetA

Erase stored memory for a user (or for one agent bucket).

This is destructive and irreversible. Pending extractions for the same scope are cancelled as part of the call, so a queued update cannot resurrect the memory afterwards. Use it when the user asks to be forgotten, not to tidy up individual facts -- use memory_delete_fact for that.

ParametersJSON Schema
NameRequiredDescriptionDefault
user_idNoWhose memory to erase. Must resolve to a concrete user.
agent_nameNoIf given, only that agent's bucket is erased and the user-level summaries are preserved.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description fully carries the behavioral disclosure burden. It clearly warns that the operation is destructive and irreversible, and discloses the important side effect that pending extractions for the same scope are cancelled, preventing queued updates from resurrecting the memory.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is compact and front-loaded: the core action first, followed by critical warningslorantine side effects, then usage guidance. Every sentence earns its place with no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a destructive tool with no annotationsce, this description is remarkably complete. It covers what is erased, irreversibility, cancellation of pending extractions, scope nuance, and the alternative tool. The existence of an output schema means return-value documentation is not the description's job.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3. The description adds framing around scoping ('for one agent bucket') but the parameter-specific behaviors, such as preserving user-level summaries when agent_name is given, are already present in the schema, so the description does not add substantial extra meaning.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

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: 'Erase stored memory for a user (or for one agent bucket).' It clearly distinguishes itself from siblings like memory_delete_fact and memory_flush by stating scope and effect.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly says when to use it ('when the user asks to be forgotten') and when not to ('not to tidy up individual facts'), and names the exact alternative tool (`memory_delete_fact`). This removes all ambiguity about selection.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

memory_getMemory GetA

Return the complete stored memory document for a user.

Prefer memory_search or memory_context for normal use; this returns everything (summaries plus the full fact list) and is intended for inspection, export or debugging.

ParametersJSON Schema
NameRequiredDescriptionDefault
user_idNoWhose memory to return.
agent_nameNoOptional per-agent bucket.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden. It discloses that the tool returns 'everything (summaries plus the full fact list)' and is intended for inspection/export/debugging, which implies a heavier payload. It does not explicitly state it is read-only or mention performance implications, but given the tool name and the intended use cases, this is a minor gap.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two sentences with zero waste. The first sentence states the purpose, the second gives usage guidance. Information is front-loaded and efficiently organized.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema is present, so return format is covered. Parameters are fully documented. The description covers purpose and usage clearly. Minor missing details like error handling or behavior when no memory exists are not critical given the output schema and simple tool nature.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% – both parameters (user_id, agent_name) have descriptions. The tool description adds no additional parameter semantics beyond what the schema provides, so the baseline of 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb ('return') and resource ('complete stored memory document for a user'), and explicitly distinguishes it from siblings by naming memory_search and memory_context as alternatives. An agent can immediately understand what it does and how it differs.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It explicitly states when to use the tool ('inspection, export or debugging') and when not to ('normal use'), and names the preferred alternatives (memory_search, memory_context). This leaves no ambiguity about selection.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

memory_rememberMemory RememberA

Store one durable fact about the user.

Use this when the user states a preference, corrects you, or shares context worth carrying into future sessions. Do NOT use it for transient details of the current task, and do not re-save something you already saved -- an identical fact is detected and returned as status="duplicate" instead of being stored twice.

ParametersJSON Schema
NameRequiredDescriptionDefault
contentYesThe fact, stated plainly, e.g. "prefers uv over pip".
user_idNoWhose memory to write to.
categoryNoLabel used for filtering, e.g. "preference", "correction", "behavior", "personal", "context".context
agent_nameNoOptional per-agent bucket.
confidenceNoYour certainty, 0.0-1.0. Use higher values for explicit user statements and lower ones for inferences.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden of behavioral disclosure. It does well by revealing the duplicate-detection behavior and the `status="duplicate"` return value, which is not visible in the schema. It could go further by noting whether the tool overwrites existing facts or how it handles conflicting facts, but the duplicate behavior is a meaningful disclosure beyond 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.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is compact and front-loaded: the core action is in the first sentence, followed by clear usage guidance and a behavioral note. Every sentence earns its place, and the duplicate warning is placed at the end where it reinforces the usage rule without cluttering the main purpose.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a write tool with no annotations, the description covers the essential decision boundary (when to use, when not to use) and a key behavioral outcome (duplicate detection). The output schema exists, so return values need not be explained. It is slightly incomplete in that it doesn't mention whether the fact is upserted or how category/confidence defaults behave, but the schema covers those defaults and the description is otherwise sufficient for correct invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents all five parameters thoroughly. The description adds a useful example ('prefers uv over pip') and clarifies the intended semantics of 'content' as a durable fact, but it does not need to add much more because the schema is complete. Baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

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: 'Store one durable fact about the user.' It clearly distinguishes this from siblings like memory_get, memory_search, and memory_remember_conversation by emphasizing durable, user-stated facts rather than transient or conversational details. The scope is precise and immediately actionable.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly states when to use the tool ('when the user states a preference, corrects you, or shares context worth carrying into future sessions') and when not to use it ('Do NOT use it for transient details of the current task'). It also warns against re-saving duplicates, which is a clear exclusion that helps an agent avoid redundant calls.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

memory_remember_conversationMemory Remember ConversationA

Hand a conversation to the backend to extract facts from automatically.

This is the hands-off write path: instead of deciding fact-by-fact what to save, send the turns and let the backend's LLM extraction decide. Requires an LLM to be configured on the server; without one this returns an error rather than silently storing nothing.

ParametersJSON Schema
NameRequiredDescriptionDefault
user_idNoWhose memory to write to.
messagesYesThe turns, oldest first, each `{"role": "user"|"assistant"|"system", "content": "..."}`. Only user turns and the final assistant reply are considered.
immediateNoSkip the debounce window when the conversation is known to be over.
thread_idYesConversation identifier. It keys the de-duplication watermark, so reusing the same id with a growing transcript will not re-extract what was already processed.
agent_nameNoOptional per-agent bucket.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden. It discloses that this is a write path, that extraction is delegated to a backend LLM, and that a missing LLM config causes an error rather than silently storing nothing. This is meaningful behavioral context beyond the schema.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three short sentences with no wasted words. The core action is front-loaded, the second sentence clarifies the design intent, and the third covers the prerequisite and failure mode. It avoids restating schema fields.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no annotations and an output schema, the description covers the essential context: what the tool does, when to use it, and what happens if the server lacks an LLM. Minor gaps like the exact write effect or return shape are acceptable because the schema already documents parameters and output.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the structured schema already documents all parameters thoroughly. The description adds no per-parameter meaning beyond the schema, but it doesn't need to given the high coverage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

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: handing a conversation to the backend for automatic fact extraction. It also distinguishes itself from the fact-by-fact manual path, which clearly separates it from the sibling memory_remember tool.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It clearly explains when to use this tool: when you want a hands-off, automatic extraction path rather than deciding fact-by-fact what to save. It also flags the LLM prerequisite and the resulting error behavior, though it does not explicitly name the alternative tool or list cases where manual saving is preferable.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

memory_statusMemory StatusA

Report the memory backend's configuration and health.

Use to check whether a model is configured (extraction needs one), where data is stored, and which identity the defaults resolve to.

ParametersJSON Schema
NameRequiredDescriptionDefault
user_idNo
agent_nameNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description must carry the safety profile. 'Report' and 'health' clearly frame this as a read-only inspection tool, and it adds context about what is inspected. It does not explicitly state 'no side effects' or address permissions, but nothing suggests mutation and the framing is sufficiently transparent for a status tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two tight sentences: the first states the core purpose and the second provides actionable use-cases. Every sentence earns its place with no redundant wording or restatement of the title.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a read-only status reporting tool with two optional parameters and an output schema, the description covers what the tool does, the exact situations to call it, and enough context about defaults. The output schema covers return details, so nothing essential is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0% and the description never names user_id or agent_name or explains how they filter/select the status returned. It only hints at identity through 'which identity the defaults resolve to,' which is insufficient to compensate for the complete lack of parameter documentation.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description opens with a specific verb and resource: 'Report the memory backend's configuration and health.' It then enumerates concrete sub-purposes (model configured, storage location, identity defaults), which clearly distinguishes it from sibling data-access tools like memory_get or memory_search.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The second sentence explicitly tells an agent when to use it: checking configuration, model readiness, storage location, and default identity resolution. It does not explicitly name excluded alternatives or when-not-to-use conditions, so it stops short of full routing guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

memory_update_factMemory Update FactA

Edit an existing fact by id; omitted fields keep their value.

Use this instead of saving a new fact when something changed -- for example when the user switches tooling. Get the fact_id from memory_search first.

ParametersJSON Schema
NameRequiredDescriptionDefault
contentNoReplacement text, if changing it.
fact_idYesId of the fact to change.
user_idNoWhose memory the fact belongs to.
categoryNoReplacement category, if changing it.
agent_nameNoOptional per-agent bucket.
confidenceNoReplacement confidence (0.0-1.0), if changing it.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the behavioral burden. It discloses that the tool edits an existing fact and that omitted fields retain their values, which defines the update semantics clearly. It does not mention failure behavior or permissions, but the core side-effect contract is stated.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two short paragraphs with no filler. The core behavior is front-loaded in the first sentence, and the usage guidance follows immediately, making it easy to scan and apply.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a six-parameter CRUD update with no annotations, the description covers the operation, partial-update semantics, usage context, and prerequisite lookup. It doesn't detail error cases or return values, but the presence of an output schema reduces the need to explain response structure.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds cross-parameter meaning with 'omitted fields keep their value,' which explains how the optional nullable fields behave. It also tells the agent where to obtain fact_id, reinforcing the key parameter's semantics beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb-resource pair ('Edit an existing fact by id') and immediately clarifies the partial-update behavior. The follow-up sentence explicitly contrasts it with saving a new fact, distinguishing it from siblings like memory_remember and memory_remember_conversation.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It explicitly states when to use this tool ('Use this instead of saving a new fact when something changed') and gives a concrete example. It also names the prerequisite ('Get the fact_id from memory_search first'), leaving no ambiguity about the intended workflow.

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.

  1. 10 tool updatesv0.1.0
    • First observedmemory_context
    • First observedmemory_delete_fact
    • First observedmemory_flush
    • First observedmemory_forget
    • First observedmemory_get
    • First observedmemory_remember
    • First observedmemory_remember_conversation
    • First observedmemory_search
    • First observedmemory_status
    • First observedmemory_update_fact

TDQS

A4.3/5.0

Scored across 10 tools

Disambiguation5/5

Each tool targets a distinct operation: read whole memory, search, context injection, manual write, automatic extraction, update, delete, bulk forget, flush, and status. The only near-overlap (memory_get vs memory_context) is explicitly disambiguated in descriptions, and memory_remember vs memory_remember_conversation clearly separates manual from backend-extracted storage.

Naming Consistency4/5

All tools share the memory_ prefix and use snake_case, mostly following a memory_<verb> pattern. memory_context is a noun-style endpoint and memory_status/remember_conversation vary slightly in structure, but the overall pattern remains predictable.

Tool Count5/5

10 tools is well-scoped for a memory backend: read, search, context load, manual write, automatic extraction, update, delete, full erase, flush, and status. Each tool earns its place with no redundant bloat.

Completeness5/5

Covers the full lifecycle of persistent facts: create (remember/remember_conversation), read (get/search/context), update, delete, plus admin operations (flush/status) and destructive forget. No obvious dead ends for the stated purpose.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables AI agents to maintain persistent memory across sessions by capturing conversations, extracting durable knowledge, and injecting relevant context, supporting various MCP-compatible platforms.
    12
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    Provides persistent, local-first AI memory across sessions via MCP tools for storing, searching, and retrieving context from past interactions.
    1
    MIT
  • A
    license
    A
    quality
    D
    maintenance
    Provides persistent memory for AI assistants via MCP, enabling them to store and recall facts, preferences, and tasks across conversations using either local file storage or a cloud backend with semantic search.
    5
    5 npm
    MIT
  • A
    license
    A
    quality
    D
    maintenance
    Provides persistent memory with semantic search for MCP-based AI agents, enabling them to store and recall information across sessions using vector embeddings.
    4
    1
    MIT