mcp-chest-memory
Click on "Install 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., "@mcp-chest-memorywhat did I learn from the last database migration?"
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.
mcp-chest-memory
English | 日本語
These daily frustrations end today:
Giving the same instructions over and over
Answering the same questions again and again
Watching your LLM stumble in the same place every time
Burning through tokens so fast you keep hitting your limits
mcp-chest-memory makes all of these a thing of the past — automatically.
Add this MCP server — then there is nothing left for you to do.
It automatically remembers what was worked on, why things failed, and what research concluded — across all your projects.
With this MCP installed, your LLM grows together with you: mistakes and repeated questions keep decreasing, and the LLM increasingly behaves like an extension of yourself.
As a welcome side effect, it also cuts your LLM token usage substantially.
Local-first persistent memory for coding agents, served over MCP. Your agent forgets everything when a session ends; chest gives it a durable, searchable "past self" — failures it must not repeat, decisions and their reasons, per-file edit history — stored in a single SQLite file on your machine.
One memory store spans all your projects and all your LLM agents: knowledge is recalled and recorded automatically by the LLM itself, without you having to think about it — so you stop giving the same instructions over and over.
Optimized for Claude Code (bundled skill + hooks), works with any MCP client.
This MCP server is built to be easy to adopt. It scales from personal use to multiple machines and on to a whole project team. Start with personal use and feel the difference for yourself — getting started solo is very easy.
Features
6-layer structured memory —
goal/context/emotion/implementation/realize(failures & pitfalls, protected from forgetting) /learning(insights & decisions)Hybrid recall — SQLite FTS5 trigram full-text search fused with vector similarity via Reciprocal Rank Fusion, then weighted by recency heat, entity momentum, and importance
Multilingual by construction — trigram tokenization needs no morphological analyzer; Japanese/Chinese/Korean and whitespace-delimited languages all work
Offline-first embeddings — a small multilingual model (
multilingual-e5-small, ONNX, ~120 MB) runs locally via transformers.js; no API key, no network after the one-time model downloadMemory lifecycle — ACT-R style activation decay, TTL expiry, archive-first deletion, supersession detection, sleep-mode consolidation
Token-saving file reads —
chest_read_smartcaches file chunk hashes and returns only what changed since the last readSession continuity — work-state snapshots survive context compaction (Claude Code PreCompact/SessionStart hooks)
Three deployment profiles — same tools, same semantics: single PC, LAN-shared (Docker), or WAN (nginx + TLS)
Related MCP server: Agent Memory Bridge
Installation
Requirements: Node.js ≥ 24. No clone needed — everything runs via npx.
Single PC (local SQLite)
The database lives at ~/.chest-memory/chest.db on your machine.
One-command setup
npx -y -p mcp-chest-memory chest-memory-setup --yesRegisters the MCP server with Claude Code, installs the /chest-memory skill,
and wires the hooks. The database schema is created automatically on first
launch; the embedding model (~120 MB) downloads in the background on first
use.
Manual registration
claude mcp add -s user chest-memory -- npx -y mcp-chest-memoryThen wire hooks and install the skill separately:
npx -y -p mcp-chest-memory chest-memory-install-hooks
npx -y -p mcp-chest-memory chest-memory-install-skillImport existing Claude Code history (optional)
Seed the memory store from every past session under ~/.claude/projects/
and each project's curated auto-memory files (memory/*.md):
npx -y -p mcp-chest-memory chest-memory-import --allPass --dry-run to parse and report without writing. Pass --skip-embed to
skip embedding backfill (background maintenance will catch up later).
Re-running is safe — each session is wiped and re-inserted idempotently.
Multi-PC (LAN): Docker backend
All clients share one SQLite database that lives on the Docker host.
Start the backend (on the host that owns the data)
Clone the repository to get the deploy/ directory, then generate a token
and start the container:
git clone https://github.com/siosig/mcp-chest-memory.git
cd mcp-chest-memory
openssl rand -hex 32 # copy this — you need it on every client
cd deploy
CHEST_API_TOKEN=<token> docker compose up -dThe SQLite file is persisted at deploy/data/chest.db and survives container
re-creation. Keep a single backend replica — one writer process owns the
database.
Register each client PC
npx -y -p mcp-chest-memory chest-memory-setup --docker http://<host-ip>:8765 <token> --yesManual registration (each client)
claude mcp add -s user chest-memory \
-e CHEST_MODE=remote \
-e CHEST_REMOTE_URL=http://<host-ip>:8765 \
-e CHEST_API_TOKEN=<token> \
-- npx -y mcp-chest-memoryMulti-PC (WAN): Docker + nginx TLS
Same Docker backend as LAN, published through nginx with TLS.
Start the backend
Same as LAN. If nginx runs on the same host, bind the port to localhost:
change the port mapping in compose.yaml to 127.0.0.1:8765:8765.
Configure nginx
Copy deploy/nginx.conf.example into your nginx
configuration, set server_name and certificate paths, then
nginx -t && systemctl reload nginx. The example publishes the backend under
the /chest-memory path prefix; a health probe is available at
https://chest.example.com/chest-memory/healthz.
Register each client PC
npx -y -p mcp-chest-memory chest-memory-setup --nginx https://chest.example.com/chest-memory <token> --yesManual registration (each client)
claude mcp add -s user chest-memory \
-e CHEST_MODE=remote \
-e CHEST_REMOTE_URL=https://chest.example.com/chest-memory \
-e CHEST_API_TOKEN=<token> \
-- npx -y mcp-chest-memoryDefense in depth: TLS terminates at nginx, while the backend still verifies the Bearer token — a proxy misconfiguration never exposes an unauthenticated backend.
Uninstall
claude mcp remove -s user chest-memory
npx -y -p mcp-chest-memory chest-memory-install-hooks --remove
rm -rf ~/.claude/skills/chest-memory
rm -rf ~/.chest-memory # only if you also want to delete your memoriesDaily usage
What you have to do: (almost) nothing
After installation, just work with Claude Code as usual. The bundled
/chest-memory skill teaches the agent to recall and save memories on its
own. Everything below is optional:
Say "remember this: ..." to force a save of something specific
Invoke
/chest-memoryto save the recent context explicitly, or/chest-memory statusto check store healthAsk "did we hit this before?" to force a recall
Hooks are wired automatically by
chest-memory-setup --yes: session auto-capture on Stop, snapshot save/restore around compaction
What runs automatically even if you do nothing
On every save (
chest_remember): the layer is classified by the agent, content is stored in SQLite, the FTS5 index updates via triggers, the vector is embedded in-process by the local model, andrealize-layer memories are auto-protected from forgettingOn every recall (
chest_recall): FTS + vector hybrid search with decay-aware ranking; access heat is updated so frequently used memories rank higher over timeDuring a session (skill-driven): recall at task start and before editing files with history; saves after errors are resolved or decisions are made
On every session end (hooks, wired by
chest-memory-setup): the session is captured on Stop, and work-state snapshots survive context compactionIn the background after saves (throttled, at most once per
CHEST_MAINTENANCE_INTERVAL_SEC, default 600 s / 10 min): activation decay recompute, TTL expiry and archive sweep, supersession detection, consolidation of cold memories, and embedding backfill for any pending rows. No scheduler setup is required;chest-index upremains available for manual runs
MCP tools
Tool | Purpose |
| Save a memory into a layer (with importance, TTL, supersedes) |
| Hybrid search across memories (FTS5 + vector + decay-aware ranking) |
| Complete edit history of a file with per-edit intent |
| Edit a memory in place (preserves links) |
| Entity overview sorted by recent activity |
| Delete by id or run risk-based auto-forgetting (realize/goal/pinned protected) |
| Compress cold memories into learning summaries |
| Diff-cached file read (returns only changed chunks) |
How it works
Architecture
flowchart LR
subgraph client [Any client PC]
CC[Claude Code] -->|stdio| MCP[chest-memory MCP server]
end
MCP -->|"local mode (default)"| DB[(chest.db SQLite + FTS5)]
MCP -->|"remote mode: REST + Bearer token"| NG[nginx TLS - WAN only]
NG --> API[chest-server REST backend Docker]
MCP -.->|"LAN: direct REST"| API
API --> DB2[(host-mounted chest.db)]
subgraph maintenance [Background maintenance - auto after writes]
IDX[decay / sweeps / embedding backfill] --> DB
IDX2[same, inside the backend] --> DB2
endProfile | Transport | Database lives | Setup |
Single PC | stdio → in-process SQLite |
|
|
Multi-PC (LAN) | stdio → REST (Bearer) → Docker | host bind mount ( |
|
Multi-PC (WAN) | stdio → nginx (TLS) → Docker | host bind mount | above + |
The MCP tool surface is identical in every profile: the stdio server either executes tools in-process (local) or forwards the same JSON payload to the backend (remote), which runs the very same executor code.
Memory layers
Six layers define how memories are stored and decay:
Layer | Meaning | Default TTL | Auto-protected |
| Project objectives and targets | none | — |
| Background, timing, situational facts | 30 days | — |
| Tone, mood, and emotional state | 14 days | — |
| Code/config that worked or didn't; how things were tried | 90 days | — |
| Failures, pitfalls, and traps that must not be repeated | none | yes |
| Insights, decisions, and belief updates | 365 days | — |
realize-layer memories are created with protected=1 and survive all
automatic forgetting sweeps. goal has no TTL and is exempt from forgetting.
importance >= 0.9 pins any memory regardless of layer.
context, emotion, and implementation are subject to sleep-mode
consolidation: once cold (heat < 30) and older than 7 days, clusters of ≥ 2
per (entity, layer) are compressed into a single protected learning summary.
Accepted layer aliases: decisions/insights/learned → learning;
warnings/pitfalls/rule → realize; why/goals → goal; how/tried → implementation.
Forgetting
Forgetting risk is computed per memory with an Ebbinghaus-inspired formula:
risk = heatFactor × importanceFactor × timeFactor
heatFactor = 1 - (heatScore / 100)
importanceFactor = 1 - importance
timeFactor = daysSinceLastAccess × (1 + daysSinceLastAccess / 30)risk | action |
< 50 | keep |
50 – 199 | compress — archived and summarised into a |
≥ 200 | drop — fully deleted |
The heat score (0–100) is computed from access frequency and recency:
30-day access count (×3, cap 30) + 90-day count (cap 20) + recency bonus
(+20 if ≤ 7 days, −10 if > 90 days) + tenure bonus (cap 15) + importance
boost (up to 15). Bands: hot ≥ 70 / warm ≥ 40 / cold ≥ 20 / frozen < 20.
Supersession (overwrite detection)
When a new memory is saved, the next maintenance pass compares it against recent memories of the same entity and layer using cosine similarity. If a near-duplicate is found (cosine ≥ 0.97), the older memory is archived and linked to the new one — so the store never accumulates stale near-copies.
Guards that reduce false positives:
Same entity + same layer required
90-day time window and 200-peer row cap per entity (prevents O(n²) scans)
JSON memories with identical top-level key shapes are not superseded (periodic snapshots / file-edit logs that look structurally similar but hold distinct facts)
The chest_remember tool also accepts a supersedes list for manual
supersession without waiting for the batch sweep.
Storage
One SQLite database (WAL mode) holds entities, memories, edges, events, file snapshots, sessions, and consolidation audit rows. Schema is managed by Prisma migrations; the FTS5 virtual table and its sync triggers are plain SQL inside the same migration.
Full-text search: FTS5 trigram
memories_fts indexes 3-character substrings (tokenize='trigram remove_diacritics 1'). This is language-agnostic: CJK text needs no word
segmentation and no MeCab-style analyzer. Queries shorter than 3 characters
fall back to a LIKE path. Scores come from SQLite's built-in bm25().
Hybrid ranking
For a recall query both paths run:
FTS path — trigram match, ranked by bm25
Vector path — query embedded by the local model, cosine similarity against stored vectors (only rows whose
(model, dim)match the current model), top-k
The two rankings are fused with Reciprocal Rank Fusion
(1/(k + rank_fts) + 1/(k + rank_vec)), min-max normalized to a relevance
score. The final composite is:
composite = (0.45·relevance + 0.25·heat + 0.15·momentum + 0.15·importance)
× activation × ttl_penalty × supersession_penaltyheat — access frequency/recency of the memory (hot/warm/cold/frozen)
momentum — recent activity of the owning entity
activation — ACT-R inspired decay computed offline by
chest-indexfrom the access logttl / supersession penalties — soft demotion before hard expiry
Memory lifecycle
Archive-first: nothing is physically deleted on decay; rows get
archived_atand drop out of default recallSupersession: a newer, near-duplicate memory (cosine ≥ 0.97, same entity/layer, 90-day window) archives its predecessor and records the link
Consolidation: cold low-importance memories are clustered per (entity, layer) and compressed into one protected
learningsummaryProtection:
realize-layer and pinned (importance ≥ 0.9) memories are never auto-forgottenSnapshots: a per-session work-state snapshot survives context compaction; the SessionStart hook restores it
Maintenance
Maintenance is self-driving: after a save, the server runs (in the
background, without delaying the response) activation recompute →
decay/archive sweep → supersession sweep → embedding backfill of pending
rows. Passes are throttled to once per CHEST_MAINTENANCE_INTERVAL_SEC
(default 600 s / 10 min) and guarded by a file lock, so they never overlap a manual
chest-index up run. Set CHEST_AUTO_MAINTENANCE=0 to disable the
automatic passes and drive everything via chest-index yourself.
Configuration reference
Variable | Default | Meaning |
|
|
|
|
| Data root (database, model cache) |
|
| SQLite file |
| — | Backend base URL (remote mode) |
| — | Shared Bearer token (backend refuses to start without it; minimum 32 characters) |
|
| REST backend listen port |
|
| REST backend listen host. Set to |
|
| Max memory content length (clamped to ≥ 1; 0/negative are ignored) |
|
| Max memories archived per argument-less |
|
| Max rows backfilled per embedding sweep |
|
| Min seconds between background maintenance passes |
|
| Set |
Security notes
Token length: the REST backend requires
CHEST_API_TOKENto be at least 32 characters and refuses to start otherwise.openssl rand -hex 32(64 chars) satisfies this.Token on the command line: passing the token inline to
claude mcp add(or any shell command) leaves it visible in/proc/<pid>/cmdlineand your shell history on a shared machine. Prefer setting it via your shell's secret manager or an env file, and clear the relevant history entry afterward.Network exposure: the LAN profile publishes the backend on all interfaces by default and protects it with the Bearer token only, in cleartext HTTP. Run it only on a trusted network, or restrict it with
CHEST_BIND_HOST=127.0.0.1plus the nginx + TLS (WAN) profile. The bundled nginx example sends HSTS and a restrictive CSP.File reads:
chest_read_smartonly reads files inside the MCP client's declared roots and is unavailable on the REST backend (which has no client roots), so a token holder cannot read arbitrary files on the backend host.
Claude Code integration
Skill:
/chest-memory(installed bychest-memory-setup) auto-classifies the recent conversation intorealizevslearningand saves it with the rationale shown;/chest-memory statusreports store healthHooks (wired by
chest-memory-setup --yes):chest-memory-precompactsaves a work-state snapshot before context compaction;chest-memory-session-startrestores it;chest-memory-sync(Stop hook) auto-captures sessions. Re-wire any time withnpx -y -p mcp-chest-memory chest-memory-install-hooks; remove with--remove
Development
pnpm install
pnpm typecheck
pnpm test # node:test against a throwaway SQLite db
pnpm buildFrom source (for development or self-hosted LAN/WAN backend)
git clone https://github.com/siosig/mcp-chest-memory.git
cd mcp-chest-memory
pnpm install
pnpm build
npx -y -p mcp-chest-memory chest-memory-setup --yes # local mode
# or for remote:
npx -y -p mcp-chest-memory chest-memory-setup --docker <url> <token> --yesSecurity
chest-memory stores a durable, cross-project record of how you and your agents work. That store is valuable, so it is also worth protecting. This section describes the threat model the project designs against and the concrete measures in the code.
Threat model
Two principals can reach the tools, and neither is fully trusted:
The LLM agent itself. An agent reads third-party content (repositories, web pages, issues) and can be steered by prompt injection hidden in that content. So a tool call is not automatically a trustworthy request — it may be an attacker's request laundered through the model.
Any holder of the shared Bearer token (LAN/WAN profiles). The REST backend authenticates with one shared token; anyone who has it can POST arbitrary tool payloads to the backend host.
The design goal is that neither a prompt-injected agent nor a token holder can read arbitrary host files, dump the whole memory store, or silently destroy or rewrite memories.
Principles
Fail closed. When the safe scope is unknown, deny. File reads with no declared roots return nothing rather than falling back to "read anything".
No deployment branches in tool logic. Profile differences flow only through the executor port (
src/core/executor.ts); a tool behaves identically in every profile. Where a tool must refuse on the backend, that falls out of the input (no client roots) rather than anif (remote)branch.Protect the irreplaceable.
realize(pain lessons), pinned (importance >= 0.9), andgoalmemories are exempt from every automated and caller-driven removal path.Root-cause over symptomatic fixes. Cross-cutting concerns live in one audited helper (LIKE-escaping, path confinement, atomic writes) instead of being re-implemented per call site.
Defense in depth. TLS terminates at nginx and the backend still verifies the token; content caps are enforced in both the schema and the handler.
What the code does
Risk | Measure | Where |
Arbitrary host file read via | Reads are confined to the MCP client's declared roots, symlinks are resolved ( |
|
Full-store disclosure via wildcard input | All user values interpolated into SQL |
|
Silent destruction of protected memory via |
|
|
Mass-archival via an argument-less | The sweep archives at most |
|
Content-cap bypass via | The same |
|
SQL injection | Every query binds values as parameters — no user string is concatenated into SQL. Simple CRUD uses the Prisma ORM (typed columns, no string-built clauses); the remaining raw SQL is reserved for SQLite-specific features (FTS5/ | repo-wide |
Stored-memory prompt injection | Recall responses carry a notice that memory |
|
Settings corruption / secret leakage |
|
|
Container/host compromise | The Docker image runs as the non-root |
|
Weak auth / network exposure | The backend requires a Bearer token of at least 32 characters, compares it in constant time, binds the host configured by |
|
Residual risks (by design)
The LAN profile uses cleartext HTTP: the token and memory content cross the network in the clear. Run it only on a trusted network, or use the WAN profile (nginx + TLS). See Security notes.
The shared token grants full access: there is no per-client scoping. Treat it as a high-value secret.
Data markers reduce but do not eliminate stored prompt-injection risk; they are one layer, not a guarantee.
Found a vulnerability? Please open a private report rather than a public issue.
License
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Latest Blog Posts
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/siosig/mcp-chest-memory'
If you have feedback or need assistance with the MCP directory API, please join our Discord server