Hippocampus
Provides Alexa+ with a self-hosted long-term memory backend via MCP tools to remember and recall memories, run sleep consolidation, preview compression, inspect memories, and report memory stats.
Optional integration for LLM-powered memory summaries and reconstruction using OpenAI-compatible APIs, configurable via OPENAI_API_KEY, OPENAI_BASE_URL, and OPENAI_MODEL.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Hippocampusremember that my sister's birthday is June 12"
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.
Hippocampus — brain-inspired memory MCP server for Alexa+
Node ≥ 22.15 required (zstd). On the box:
export PATH=$HOME/.local/node22/bin:$PATH.
Agents usually "remember" by stuffing logs into the context window. Hippocampus is a self-hosted MCP server (spec 2025-11-25, Streamable HTTP) that gives Alexa+ a brain-like long-term memory:
memories are files, not context;
recall is spreading activation over an association graph, shaped by Hebbian learning, the spacing effect and salience;
sleep consolidates similar episodes into schemas and compresses faded memories through graded tiers: lossless hot/warm, then schema + residual in cool/cold with measured fidelity floors;
every pass produces a compression report;
nothing is ever deleted, and no memory ever becomes unrecoverable;
when the storage budget runs out, the server asks the user instead of deleting.
Built for the Amazon Developer Hackathon, Alexa+ track. MIT licensed.
Quick start
# Node >= 22.15 is required for zstd (see .nvmrc). On the dev box: export PATH=$HOME/.local/node22/bin:$PATH
npm install
npm start # MCP: http://localhost:3000/mcp · brain view: http://localhost:3000/
npm run alexa:demo:full # in a 2nd terminal: simulated Alexa+ conversations across sessions (MCP client)
npm run alexa:demo -- --chat # interactive simulated Alexa+ (/sleep, /skip 30, /stats, /quit; piped stdin works)
npm run alexa:demo:video # smaller curated 2-week history used for the demo video
npm test && npm run typecheckDocker: docker build -t hippocampus . && docker run -p 3000:3000 -v $PWD/data:/data hippocampus
Runtime use of MCP. src/server.ts imports @modelcontextprotocol/sdk (McpServer, StreamableHTTPServerTransport) and serves 6 tools at POST /mcp. src/alexa-sim.ts imports the SDK Client and StreamableHTTPClientTransport and calls those tools. Each simulated Alexa+ turn opens a fresh MCP session, so continuity can only come from the memory server.
Related MCP server: Long-Term Memory
Architecture
Alexa+ / any MCP client ──POST /mcp──► server.ts (stateless, one McpServer per request)
│
MemoryEngine (src/memory/engine.ts)
┌──────────────┬──────┴───────┬────────────────┐
Embedder (pluggable) Summarizer (pluggable) data/memory/
local TF vector extractive | OpenAI-compat index.bin (zstd-19 compact index)
raw/<id>.txt|.z|.dz chunks/<sha>.br
packs/{cool,cold}.pack dicts/<id>.dict
Browser ──GET /──► public/index.html (vis-network) ◄──SSE /api/events (recall lights up nodes)Algorithms
Recall: brain-like dynamics
Mechanism | Formula / rule |
Forgetting curve (power law) |
|
Salience |
|
Spreading activation | seed |
Spacing effect |
|
Hebbian |
|
Edge decay (on sleep) | elapsed retention-ticks (days since the edge was last set, or since the previous sleep): |
Storage: graded tiers, picked by retention R and re-planned on every sleep()
Tier | R | Fidelity | Target ratio | How (each tier tries every candidate; smallest output wins; algorithm recorded per node) |
hot | ≥ 0.6 | lossless | 1–2x | stored as-is or LZ4 (fast access) |
warm | ≥ 0.35 | lossless | 2.5–4x | zstd-3 / brotli-5 / LZ4, zstd with a trained dictionary, delta (zstd/deflate with a similar memory as dictionary), chunk dedup |
cool | ≥ 0.15 | ROUGE-L ≥ 0.90, char similarity ≥ 0.85, and local-embedding cosine ≥ 0.80 | 5–8x | schema + residual in a shared archive. A keep count is accepted only when all three clear. Char sits slightly under the ROUGE-L floor so short memories still reach the ratio target. Archive codec: zstd-19(+dict) / brotli-11 / LZMA-9 / deflate-9 |
cold | < 0.15 | ROUGE-L ≥ 0.65, char similarity ≥ 0.65, and local-embedding cosine ≥ 0.50 | 8–15x | schema + key residuals (gist) in a shared archive, same three gates, LZMA-9 / zstd-19(+dict) / brotli-11 |
Why these targets. Agent memories are short: about 50–600 B, about 165 B on average in our corpus. On text that short, per-object codec overhead dominates. That is why warm relies on a trained dictionary and delta, and why cool/cold share an archive. The 8–15x / 20–50x targets suggested at the start only make sense for multi-KB documents. The targets above match what the realistic corpus actually reaches (see the tests).
Schema consolidation (mammal-like). During sleep(), lossless episodes with cosine similarity ≥ 0.35 are candidates (minimum 3). Membership becomes permanent only after a near dual-check: vector similarity and a second signal (surface-token overlap, character-trigram overlap, or residual fidelity of the prototype) both clear their floors. A near-miss stays provisional (schemaHold) and is re-checked on the next sleep; missing the check does not accumulate into a permanent link. Only permanent members are copied onto the pinned, always-lossless schema (the medoid) and may later be stored lossily. Each of those members is a token-level diff against the schema (hunks [pos, del, insert]). Hunks are ordered by importance: digits ×3, capitalised words ×2, CJK ×1.5, other text ×1, divided by size. Greedy selection keeps the fewest hunks that clear the tier's ROUGE-L floor and its char-similarity floor and (cool/cold) the local-embedding cosine floor. The semantic check uses the offline local term-frequency embedder, not a network provider. Cold keeps at least one key residual. Dropped details revert to the schema's wording, which is the same "filling in" human recall does. Provisional candidates stay lossless.
Guarantees.
Nothing is ever deleted.
Every memory can always be reconstructed: schemas are pinned lossless, and every read is integrity-checked with a 64-bit sha256 tag (of the original for lossless memories, of the reconstruction for lossy ones).
memory_stats.unrecoverableis measured, not assumed: every memory is decoded and hash-checked. A damaged blob is reported there and does not stop the rest of the store from loading.A memory's measured fidelity is never below its tier floor. Cool/cold lossy encodes record ROUGE-L, char similarity, and local-embedding cosine, and each one has to clear that tier's floor. Fidelity is computed against the original at compression time and stored per node.
High-salience memories, delta bases and memories without a schema stay byte-exact.
A lossy memory never "warms" back up. A recalled lossless memory returns to the warm tier.
Budget. MEMORY_BUDGET_BYTES. When exceeded, the weakest memories are forced down to cool, then cold (fidelity floors still apply). If the store is still over budget, the server raises an alert instead of deleting: memory_stats.overBudget/alert are set, a ⚠️ line is appended to every MCP tool result, and the alert is logged once.
Compact index. All metadata lives in one file, data/memory/index.bin: a JSON header plus a binary edge table (two uint16 node indices and a uint8 weight per edge), compressed with zstd-19 and written atomically, once per tick. Redundant fields are not stored. Keywords, schema members and summaries are re-derived. Vectors from the default local embedder are recomputed from the stored text; for a faded memory they come from its reconstruction, so it is cued by what is left of it. Hashes are 64-bit tags. During sleep, edge weights fall with elapsed time toward a soft floor of 0.05 (half-life 60 days) and never exceed the cap of 1; weak associations beyond each memory's six strongest links are then pruned ("synaptic pruning"). Memories themselves are never pruned. The trained zstd dictionary is capped at 1/6 of the raw corpus, and memories that still use an old dictionary are re-encoded during sleep so it can be retired. memory_stats and the budget report contentBytes, dictionaryBytes, indexBytes and totalBytes separately, and the budget applies to the total. An older store using nodes/*.json is migrated automatically.
Store | Raw | Content | Dictionary | Index | Total on disk |
| 23.7 KB | 5.3 KB | 2.6–3.5 KB | 8.7 KB | 16.6–17.3 KB |
test corpus (290 memories, 60 days + 1 simulated year) | 46.8 KB | 5.5 KB | 1.0 KB | 14.6 KB | 21.1 KB |
| 5.1 KB | 1.8 KB | 1.0 KB | 3.3 KB | 6.1 KB |
before the compact index ( | 23.7 KB | 5.0 KB | 60.3 KB | ~250 KB | ~308 KB |
The size table was measured before lossy nodes also stored a semantic-fidelity number, so a store built now can be slightly larger. Demo runs vary slightly between runs, because the server clock is real time plus the simulated skips. The index costs about 50–65 B per memory (an 8-character id, a 64-bit hash, tier/encoding and fidelity numbers, timestamps, and on average four or five pruned edges). Content for these short memories compresses to about 35 B each, so the index is still larger than the content. It is about a third of the raw size, and is now proportional to the number of memories rather than the dominant cost.
Compression report. Every pass (sleep, time-skip, budget enforcement) produces a per-tier report with: target ratio and fidelity floors (ROUGE-L, char similarity, local-embedding cosine), before / expected (planned) / after for nodes, raw→stored bytes, ratio, ROUGE-L mean and minimum, char similarity, semantic similarity, algorithms used, and moves. It is returned by sleep, stored in memory_stats.lastReport, and appended to data/memory/compaction.log as text plus a JSON line. compress_preview (or GET /api/preview) is a dry run that writes nothing. It doesn't form new schemas; those are created at the start of a real sleep.
Codecs are registered in src/memory/codecs.ts (registerCodec, TIER_CODECS). Requires Node ≥ 22.15 for zstd (.nvmrc pins 22.23.3). LZ4 comes from lz4-napi; LZMA from the pure-JS lzma package. lzma-native was tried, but its synchronous mode did not flush output, so it was dropped.
MCP tools
remember(text, salience?, tags?)recall(cue, k?)sleep(): returns the compression reportcompress_preview(): dry-run reportmemory_stats()inspect(id)
Run
npm install
npm start # MCP at http://localhost:3000/mcp, brain view at http://localhost:3000/
npm test # unit + time-skip scenario tests (node:test)
npm run typecheck
npm run smoke # end-to-end MCP client against a running serverEnvironment variables:
MEMORY_DIR: storage folder (defaultdata/memory)MEMORY_BUDGET_BYTES: storage budget (default: unlimited)PORTMEMORY_LLM=openaiwithOPENAI_API_KEY: LLM summaries and reconstruction. Optional:OPENAI_BASE_URL,OPENAI_MODEL.Bedrock: hook point in
src/memory/providers.ts
Demo REST helpers (not part of MCP):
POST /api/remember,/api/recall,/api/sleepPOST /api/timeskip {days}: shifts the server clock and runs decayGET /api/graph,/api/stats,/api/events
Demo
The full shot list is in submission/demo-video-script.md. Short version: run npm start, open http://localhost:3000/, run npm run alexa:demo:video (or alexa:demo:full) in a second terminal and watch the graph light up, click 🔍 preview pass / 😴 sleep / ⏩ +7 days, then restart with MEMORY_BUDGET_BYTES=5000 (after alexa:demo:video) to show the alert. The brain view is self-contained: a custom 60 fps canvas renderer and force layout, with no external libraries or CDN. It shows activation pulses with particle trails, a camera zoom to the recalled memory, and sleep as replay → fold into schemas → condense, with a byte counter and per-tier bars. Set DEMO_EPOCH=<ms> for a reproducible demo: the clock is frozen except for /api/timeskip, and ids are deterministic, so two runs produce byte-identical stores. The budget alert is derived state. It is recomputed at startup and not stored in the index, so the alert and memory_stats always report the same total.
This server cannot be deployed
Maintenance
Related MCP Connectors
Person-owned AI memory that learns, not just stores — portable context for any MCP client.
Persistent, portable memory for AI assistants — your private memory graph, from any MCP client.
Persistent personal memory for AI assistants — save, search, and recall across every MCP client.
- EngramOAuthapp.getengram
Persistent, verbatim, searchable memory for AI assistants — one memory across every MCP client.
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceProvides a selective persistent memory layer for AI companions, enabling structured recall, reinforcement, and time-decayed retrieval through an MCP interface.56 npm1MIT
- AlicenseAqualityDmaintenanceA persistent, self-organizing memory MCP server for AI assistants, using semantic search, knowledge graphs, and reinforcement learning to automatically manage and retrieve memories.13MIT
- AlicenseNot gradedqualityAmaintenanceEnables AI assistants to have a living memory with atomic knowledge storage, multi-factor recall, organic decay, automatic learning, and graph traversal via MCP.1MIT
- AlicenseCqualityAmaintenanceProvides AI agents with a human-inspired memory layer via MCP, enabling episodic and semantic memory recall, forgetting curves, consolidation, and contradiction detection. It integrates with MCP clients to offer local-first, dependency-free memory management.981MIT