shared-memory
shared-memory
A portable, self-hosted semantic memory layer for LLM agents, exposed over the Model Context Protocol (MCP).
Point any number of agents — Claude Code, other MCP clients, or your own scripts — at one shared store and let them recall past decisions, notes, and conversations by meaning instead of grepping files.
One SQLite file. Text, a full-text index and vectors live together; no database service to run. ChromaDB is still available as an option.
Hybrid ranking. Vector similarity, plus exact matching of identifiers (order numbers,
ABC-123ids) that vectors alone miss, plus weights that put distilled notes above raw transcripts. See Search quality.Local by default. Embeddings run on-device via fastembed; nothing leaves the host unless you opt into a remote API (OpenAI-compatible or Voyage AI).
One store, many agents. Every chunk carries an
agentandsourcetag, so searches can be global or scoped to a single agent.Five MCP tools.
memory_search,memory_add,memory_update,memory_forget,memory_stats.Bring your own content. Ships with a generic markdown indexer; writing an adapter for chat logs, tickets, or docs is a short script.
Why
Agents are stateless between sessions. The common fix is a short "always-loaded" memory file, but it can't scale — you can't paste everything you've ever decided into every prompt.
shared-memory is the second layer: an unbounded store you search on demand.
Layer A — a short, hand-curated memory file loaded into every prompt (you keep whatever you already use for this).
Layer B (this project) — unbounded, searched semantically. "What did we decide about X?" returns the relevant past chunk instead of a file dump.
Related MCP server: mnemo-mcp
Architecture
┌────────────────┐
agent A ─┐ │ MCP server │ memory_search ──▶ memory.sqlite
agent B ─┼──▶ │ (FastMCP) │ memory_add / update chunks + FTS5 + vectors
scripts ─┘ │ │ memory_forget / stats (or ChromaDB, optional)
└────────────────┘
▲
│ indexers / adapters
your content (markdown, sessions, docs, …)shared-memory/
├── shared_memory/
│ ├── server.py # FastMCP server, the five memory_* tools → shared-memory-mcp
│ ├── index_markdown.py # generic adapter: index a folder of *.md → shared-memory-index
│ ├── migrate.py # copy a Chroma store into SQLite → shared-memory-migrate
│ ├── embedder.py # embeddings: local fastembed | OpenAI-compatible | Voyage AI
│ ├── store.py # backend selection, shared helpers
│ └── store_sqlite.py # SQLite backend: storage, hybrid ranking, Chroma-style API
├── mcp-server/server.py # compatibility shim for 0.1/0.2 configs (removed in 1.0)
├── embedding.env.example # copy to embedding.env to customize (optional)
└── requirements.txtInstall
Requires Python 3.10+.
git clone https://github.com/fazerluga-creator/shared-memory.git
cd shared-memory
python -m venv .venv && source .venv/bin/activate
pip install -e . # SQLite backend (default)
pip install -e ".[chroma]" # also the ChromaDB backend / migrationOr without cloning:
pip install "git+https://github.com/fazerluga-creator/shared-memory.git@v0.3.0"This installs three commands: shared-memory-mcp (the server),
shared-memory-index (markdown indexer) and shared-memory-migrate.
Where data lives. From a clone (pip install -e .) the config and data stay
in the repo folder: embedding.env, memory.sqlite. From a regular install
they live in ~/.local/share/shared-memory/ ($XDG_DATA_HOME/shared-memory).
SHARED_MEMORY_HOME moves both; SHARED_MEMORY_ENV / SHARED_MEMORY_DB set
single files.
Optionally copy the config and tweak it (defaults are fine to start):
```bash
cp embedding.env.example embedding.envThe first run downloads the local embedding model (a few hundred MB) once.
With a remote provider (voyage, openai_compatible) nothing is downloaded.
Docker
docker build -t shared-memory .
docker run -i --rm -v shared-memory-data:/data shared-memoryThe container speaks MCP over stdio and needs no credentials: the SQLite store
lives in /data and embeddings run locally (the model is downloaded on the first
search or add). Mount /data to keep the memory between runs.
Quick start
Index some markdown and search it:
# 1. ingest a folder of notes
shared-memory-index ./notes --agent notes
# 2. run the MCP server (stdio transport)
shared-memory-mcp
# or over HTTP on 127.0.0.1:8000 (read the Security section first)
shared-memory-mcp --transport httpOr use the library directly:
from shared_memory import Embedder, get_client, get_collection
col = get_collection(get_client())
emb = Embedder()
col.add(
ids=["note::1"],
embeddings=[emb.embed_document_one("Ship the beta on Friday, feature-flag the new UI.")],
documents=["Ship the beta on Friday, feature-flag the new UI."],
metadatas=[{"agent": "notes", "source": "manual"}],
)
res = col.query(query_embeddings=[emb.embed_one("when is the beta?")], n_results=3)
print(res["documents"])MCP tools
Tool | Signature | Returns |
|
|
|
|
| id of the added chunk |
|
|
|
|
|
|
|
|
|
memory_forget is a dry run unless you pass dry_run=False; deleting by filter
also requires expect_count equal to the number of matches, and a call with no
ids and no filters is refused.
Example memory_search result:
[
{
"id": "notes::markdown::decisions.md::003",
"text": "decisions.md › Release: ship the beta on Friday, feature-flag the new UI.",
"metadata": {"agent": "notes", "source": "markdown", "kind": "note",
"timestamp": "2026-10-01T09:12:00+00:00"},
"score": 0.7134
}
]Filters:
agent_filter— restrict to a singlemetadata.agentvalue.source_filter— restrict to ametadata.sourcevalue (e.g.markdown,sessions).since— ISO timestamp lower bound onmetadata.timestamp. On the SQLite backend it is applied before ranking, so a narrow window on a large store still returns the matches inside it.
Connect to Claude Code / any MCP client
Add the server to your client config (paths are examples):
{
"mcpServers": {
"shared-memory": {
"command": "/path/to/shared-memory/.venv/bin/shared-memory-mcp"
}
}
}Security
The server has no authentication. Anyone who can reach it can read every
memory, add to it, rewrite it and delete it. Run it over stdio, or bind the
HTTP transport to 127.0.0.1 (FastMCP's default), and never expose it to the
internet or to a network you do not fully control. shared-memory-mcp --transport http refuses a non-loopback --host unless you also pass
--allow-unauthenticated-remote. If several machines need it,
put it behind a VPN or an authenticating reverse proxy.
Memories tend to collect secrets that were pasted into chats. Treat the
database file like a password store: restrictive file permissions (chmod 600)
and encrypted backups. With a remote embedding provider every chunk is sent to
that provider; filter secrets out in your indexer before that if it matters.
Configuration
All settings are read from embedding.env (see embedding.env.example). Paths
are overridable by environment variable:
Variable | Default | Purpose |
|
| location of the env file |
|
|
|
|
| SQLite database file |
|
| ChromaDB persistence directory |
|
|
|
| MiniLM multilingual ( | embedding model id |
|
| collection name (display only on SQLite) |
To route embeddings through a remote OpenAI-compatible /v1/embeddings
endpoint, set EMBEDDING_PROVIDER=openai_compatible and fill in
EMBEDDING_BASE_URL / EMBEDDING_API_KEY. For Voyage AI set
EMBEDDING_PROVIDER=voyage and EMBEDDING_API_KEY (or VOYAGE_API_KEY).
Vectors are tagged with the model that produced them and search ignores vectors
of any other model, so changing the provider or model means re-indexing
(shared-memory-migrate --reembed does this for a Chroma store).
Upgrading from 0.1.x (Chroma)
If an existing chroma_data directory is found and no memory.sqlite, 0.2.0
keeps using Chroma and logs a warning, so nothing disappears after an upgrade.
To move to SQLite:
pip install -e ".[chroma]"
shared-memory-migrate # reuses stored vectors, no API calls
# check memory_stats / a few searches, then set SHARED_MEMORY_BACKEND=sqliteSearch quality
On the SQLite backend a chunk's score is its cosine similarity times a weight
for metadata.kind — note 1.0, doc 0.97, transcript 0.90, anything else
1.0 — plus 0.3 when the query contains an exact token (a number of 4+ digits, a
word with a digit, ABC-123) that the chunk contains verbatim. Chunks with
metadata.superseded: true are multiplied by 0.9: still findable, just below
the current version. Without a query vector (the embedding API is down) search
falls back to BM25 full-text ranking instead of failing.
Measured on a private 32-question benchmark over a real 25k-chunk multi-agent memory (right file among the top 3 results):
setup | top-3 |
ChromaDB + local MiniLM (0.1.x) | 16 / 32 |
Voyage | 26 / 32 |
Voyage + kind weights + exact tokens + superseded (0.2.0) | 30 / 32 |
The numbers come from one corpus; treat them as a direction, not a guarantee.
Upgrading from 0.2.x
The lib package is now shared_memory: change from lib.store import ... to
from shared_memory.store import ... (or from shared_memory import ...).
Client configs that run mcp-server/server.py keep working through a shim;
switch them to the shared-memory-mcp command when convenient. Data files in
a clone stay where they were.
Agents without access to the server: a file bus
The MCP server is meant to stay on a private machine (see Security). Agents that cannot reach it, such as a chat assistant on a phone or a hosted agent with only a Google Drive or Dropbox connector, can still share work through a plain shared folder used as a message bus. One setup that works in practice:
Agent Bus/
├── 00 Welcome # what this is, which files to read first
├── 01 Rules # task and answer formats, what never goes here (secrets, personal data)
├── 01_Inbox # one file per task: task_id, from, to, priority, goal, expected result
├── 02_Outbox # one file per answer: task_id, agent, status done|blocked|needs_review
├── 03_Shared Memory # confirmed facts and decisions only, one file per decision
└── 05_Logs # traces, daily snapshotsRules that keep it sane: every task and answer carries a task_id; silence
from another agent is never treated as agreement; a record is a proposal, not
permission to act on anything irreversible; secrets stay on the server and the
bus carries only references. An agent that does have server access (for
example Claude Code on the same machine) bridges the two: it reads the inbox,
does the work with memory_search / memory_add, and writes confirmed facts
back as files. shared-memory does not ship a bus; the folder layout above is a
convention, not code.
Writing your own indexer
shared_memory/index_markdown.py is the template. An adapter needs to:
discover source items,
turn each into
(text, metadata)chunks — always setagentandsource, an ISOtimestampif you wantsincefiltering, andkind(note/doc/transcript) if you want the ranking weights,call
add_chunks(collection, embedder, ids, texts, metadatas, upsert=True).
Use a stable, deterministic id scheme so re-runs upsert instead of duplicating.
Design notes
Embeddings are computed by us, not by the store. Vectors are passed explicitly on
add/query, so the store stays decoupled from embedder availability.No vector index on SQLite. Search is a brute-force cosine over an in-memory numpy matrix: 25k chunks x 1024 dims is ~100 MB and a few milliseconds per query, with nothing to corrupt or rebuild. The matrix is reloaded when another process writes to the file.
Chunking (markdown): split by
##headings; fall back to paragraphs; soft-cap 8000 chars at word/newline boundaries. Paths in ids/metadata use POSIX form for cross-OS stability.Timestamps are ISO-UTC strings throughout; the SQLite backend normalizes them on write, so
Z,+02:00, naive and unix-epoch inputs compare correctly.Search-time hygiene: results are de-duplicated by content hash and short known-error strings are dropped. Scores are clamped to
[0, 1].Stats:
memory_statspages through metadatas to bound peak memory.
Roadmap
TTL / forgetting policy for high-volume sources.
Optional PII filter at index time.
Session-end hooks to auto-index new content.
More example adapters (chat logs, issue trackers).
Contributing
Issues and PRs welcome — see CONTRIBUTING.md. New indexer adapters (chat logs, issue trackers, docs) are a great place to start.
License
MIT.
Available Tools
5 toolsmemory_addMemory AddC
Add an ad-hoc memory chunk. Returns the generated id.
| Name | Required | Description | Default |
|---|---|---|---|
| text | Yes | ||
| metadata | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full behavioral burden. It notes that an id is returned but says nothing about persistence lifetime, duplicate handling, whether metadata is indexed/searchable, or any permissions or rate limits for a write operation.
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 short sentences with the core action front-loaded and no filler. It is efficient, though the return-value sentence is partly redundant given an output schema exists.
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 covers the return value, but with no annotations, 0% parameter coverage, and a mutation that stores user data permanently, the definition omits the ingestion semantics and sibling routing an agent needs to call this safely and correctly.
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 nothing documents 'text' or 'metadata'. The description only implies a free-form string ('memory chunk') and gives no hint about what metadata is for or how it affects later retrieval, leaving the schema gap unclosed.
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 concrete verb and resource ('Add ... memory chunk'), so an agent can tell it is the write path in a memory_* family. However, it does not differentiate itself from siblings (memory_update, memory_search) or explain what 'ad-hoc' means and how it differs from other insertion paths.
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?
There is no when-to-use guidance and no mention of alternatives. An agent must infer on its own that this is for creating a new free-form memory rather than updating an existing one via memory_update, which is a real ambiguity given the sibling names.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
memory_forgetMemory ForgetA
Delete memory chunks by explicit ids or by agent/source filter.
Deletion is irreversible, so there are two safety catches: dry_run is on by default, and deleting by filter requires expect_count equal to the number of matches, so an over-broad filter cannot wipe the collection by mistake. A call with no ids and no filters is refused.
| Name | Required | Description | Default |
|---|---|---|---|
| ids | No | specific chunks (memory_search returns ids) | |
| dry_run | No | True (default) only reports what would be deleted | |
| agent_filter | No | everything from this agent | |
| expect_count | No | required for filter deletes with dry_run=False | |
| source_filter | No | everything from this source |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the entire behavioral burden and does so well: it discloses irreversibility, that dry_run defaults to true, that filter deletes require expect_count to match, and that empty calls are refused. This is exactly the kind of safety-critical context an agent needs before invoking a destructive 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 short paragraphs, zero filler, with the core action front-loaded and the safety mechanics following. Every sentence adds distinct information; nothing is restated from the schema verbatim without added context.
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 destructive, 5-parameter tool with an output schema present, the description covers targeting modes, irreversibility, defaults, the filter guard, and the refusal case. Return-value explanation is unnecessary given the output schema, and no critical gap remains.
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 already 100%, so the baseline is 3; the description adds meaning beyond it by framing dry_run and expect_count as a coordinated pair of "safety catches" and explaining the rationale (preventing an over-broad filter from wiping the collection). It stops short of describing the ids format or filter matching semantics, so it is not a full 5.
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 ("Delete memory chunks") and immediately names the two supported targeting modes (explicit ids vs. agent/source filter). This clearly separates it from siblings like memory_add, memory_search, and memory_update, which are non-destructive or retrieval-oriented.
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 clear usage contexts: delete by ids, or delete by filter, plus an explicit when-not ("A call with no ids and no filters is refused"). It does not explicitly route the agent to an alternative tool (e.g., memory_update for modifying rather than removing), so it falls short of the full when/when-not/alternatives bar.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
memory_searchMemory SearchC
Semantic search across shared memory.
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | natural-language query | |
| since | No | ISO timestamp lower bound on metadata.timestamp | |
| top_k | No | number of results (default 5, max 50) | |
| agent_filter | No | restrict to a single agent label stored in metadata.agent | |
| source_filter | No | restrict to a metadata.source value (e.g. 'sessions', 'memory') |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full behavioral burden. "Semantic search" implies ranking by similarity but says nothing about scoring, result ordering, whether the search spans all agents/sources by default, permission requirements, or whether "shared memory" implies cross-agent visibility. Only the bare minimum is conveyed.
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 fragment with zero filler, which is efficient. It is arguably too terse for a five-parameter tool, but no sentence is wasted.
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. However, for a five-parameter semantic retrieval tool with no annotations and four distinct filter parameters, the description leaves the agent without any guidance on default scope, ranking semantics, or routing versus memory_stats.
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 100%, so all five parameters (including since, top_k, agent_filter, source_filter) are already documented in the schema; baseline 3 applies. The description adds no additional meaning such as default scoping behavior or how filters combine.
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 ("search") and resource ("shared memory") with the retrieval modality ("semantic") made explicit, which is more than a tautology. It does not name or contrast with any sibling, though the read-only nature of search makes it distinguishable from memory_add/update/forget on the surface.
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?
There is no when-to-use guidance, no statement of what this tool is for relative to memory_stats (the other read-oriented sibling), and no exclusions. The agent must infer that this is the retrieval path while the others are mutation paths.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
memory_statsMemory StatsA
Return collection statistics: total count, breakdown by agent/source.
| 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?
No annotations are provided, so the description carries the disclosure burden. It reveals the shape of what comes back, which implies a safe read with no side effects, but it never states that it is non-mutating, requires no auth, or has any cost/limit. Adequate but thin for an annotation-free 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?
A single short sentence that front-loads the return content with no filler or redundancy.
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 re-explained, and a zero-parameter read tool has few unknowns. Nothing essential is missing, though the absence of any read-only/safety statement leaves a small gap given no annotations.
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 baseline is 4. The description correctly implies no input is needed by describing only output content.
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 (Return) and resource (collection statistics) and enumerates what is returned (total count, breakdown by agent/source). It is distinguishable from the mutating siblings (add/update/forget) and the query sibling (search), but it never explicitly contrasts itself 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?
There is no statement of when to use this tool versus the search or add siblings, nor any prerequisite context. The usage is only faintly implied by the read-oriented nature of the name.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
memory_updateMemory UpdateA
Update an existing memory chunk in place; the id is kept.
Keeping the id means references to it stay valid. An unknown id raises, so a typo never silently turns into a new chunk.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | chunk id (memory_search returns it in "id") | |
| text | No | new text; the embedding is recomputed when given | |
| metadata | No | metadata fields to change (merged unless replace_metadata) | |
| replace_metadata | No | replace metadata wholesale instead of merging |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the behavioral burden and does well: it discloses that the id is preserved, references remain valid, and an unknown id raises rather than silently creating a new chunk. It does not cover permission requirements or all side effects, but it provides meaningful error and identity behavior 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.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is three short sentences with zero waste, front-loads the core update behavior, and then explains the two most important behavioral consequences: id stability and unknown-id errors.
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 100% schema coverage and an output schema, the description does not need to explain parameters or return values. It complements those structured fields with the key mutation semantics: in-place update, id preservation, and error on unknown id. It could be slightly more complete by clarifying when to use this versus memory_add, but it is otherwise sufficient.
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 100%, so the schema already documents all four parameters thoroughly, including embedding recomputation and metadata merge/replace behavior. The description adds no additional parameter semantics beyond the schema, so the baseline 3 is appropriate.
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: update an existing memory chunk in place. The phrase 'existing' and 'id is kept' helps distinguish it from memory_add, though it does not explicitly name sibling tools or contrast against memory_search/memory_forget.
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 'update an existing memory chunk' and the failure behavior for unknown ids, but the description does not explicitly say when to use this versus memory_add or other siblings. It gives enough context to infer the tool's role but leaves alternative selection unstated.
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.
5 tool updates
v0.3.0- First observed
memory_add - First observed
memory_forget - First observed
memory_search - First observed
memory_stats - First observed
memory_update
TDQS
Scored across 5 tools
Each tool maps to a distinct lifecycle operation on a single resource: add, search, update, forget, stats. There is no meaningful overlap — search retrieves, stats aggregates, and the write operations are cleanly separated.
All five tools follow a strict memory_<verb> snake_case pattern with clear, conventional verbs (add, search, update, forget, stats). No mixed conventions or vague names.
Five tools is a tight, well-scoped surface for a memory store: write, read, mutate, delete, and observe. Every tool earns its place with no redundancy or filler.
The set covers the full CRUD lifecycle plus stats, and search likely substitutes for a direct get-by-id. Minor gaps remain around bulk operations and explicit id-based retrieval, but core workflows are covered without dead ends.
Maintenance
Related MCP Connectors
Persistent memory for AI agents. Semantic search, memory graph, W3C DID identity.
Memory system for AI agents with semantic search. Store and recall memories with ease.
Hosted persistent memory with semantic search, importance and TTL for AI agents.
Universal memory for AI agents and tools. Save, organize and search context anywhere.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceSelf-hosted semantic memory for AI agents. Save worklogs, decisions, and notes via MCP, then recall them across sessions by meaning rather than keyword. Backed by Postgres + pgvector with local embeddings (multilingual-e5-base).1MIT
- AlicenseAqualityCmaintenancePortable cognitive memory for AI agents with semantic search, decay, and deduplication.87 npm2MIT
- AlicenseNot gradedqualityCmaintenanceA semantic memory store for AI agents, enabling persistent memory across sessions via MCP tools with semantic search, scoped access, and local embeddings.MIT
- AlicenseNot gradedqualityDmaintenanceA portable self-hosted memory layer for AI tools, storing context, memories, and handoffs for access from any MCP-compatible client.22 npmMIT