Are you the author? Sign in to claim
Universal MCP memory server: personal + shared memory across any MCP-compatible agent (Claude Code, Cursor, Codex CLI)
MCP server for personal + shared memory that works with any MCP-compatible agent (Claude Code, Cursor, Codex CLI, ...). Personal entries are visible only to the agent that wrote them; shared entries are visible to every agent connected to the same project. Search is hybrid — SQLite FTS5 keyword matching fused with local, offline semantic search (see below) — ranked by past outcome (success/failure) and recall count.
Sixteen MCP tools: memory_remember, memory_recall, memory_mark_outcome, memory_stats, memory_recall_recent, memory_correct, memory_touch, memory_link, memory_convention, memory_session_start, memory_session_end, memory_replay, memory_skill_save, memory_skill_match, memory_skill_score, memory_premortem.
memory_correct fixes an existing entry's text in place (id from a prior recall) instead of leaving the wrong fact around and remembering a corrected duplicate next to it.memory_touch confirms an entry is still true/relevant right now without changing its text - resets its recall-ranking freshness.memory_link connects two entries with an optional relation label (e.g. caused-by, supersedes). Linked entries show up as indented -> /<- lines under either entry whenever it's recalled.memory_convention stores a project rule/standard (type=convention) instead of a one-off fact. Conventions always sort first in memory_recall and memory_recall_recent, regardless of recency or decay - they don't stop being true just because nobody hit them last week.memory_session_start / memory_session_end / memory_replay. The Claude Code adapter calls memory_session_start on SessionStart and memory_session_end (with a summary of the last assistant message) on Stop, keyed by Claude Code's own session_id. memory_replay returns a recap of the most recently finished session - the in-progress one is naturally excluded since it has no end time yet. context-inject.js calls this automatically and prepends the recap to the session-start context, ahead of the usual recent-memories bullet list.memory_skill_save / memory_skill_match / memory_skill_score. Skills are named, reusable task recipes (a "how to do X" procedure) stored separately from one-off facts, with a running success rate. Saving under an existing name updates that recipe instead of creating a near-duplicate. Matching ranks by success rate (times_succeeded / times_used) first.memory_premortem. Given a short description of an action about to be taken, searches memory the same way memory_recall does but returns only the two kinds of rows that represent real risk: past outcome=failure entries and type=convention rules relevant to that action. General facts (successes, unknowns) are filtered out - this tool is specifically "what could bite me here," not "what do I know about this."memory_recall combines two search methods and merges them with reciprocal rank fusion, so a fact surfaces whether the query shares its exact words or just its meaning:
onnx-community/embeddinggemma-300m-ONNX fully on-CPU/offline. No API key, no per-call cost — only a one-time ~1.2GB model download on first use (cached under node_modules/@huggingface/transformers/.cache). Chosen over the smaller Xenova/all-MiniLM-L6-v2 (previously used) specifically for Russian: measured 70% vs 30% top-5 hit rate on a clean benchmark - see CHANGELOG 0.6.0. Switching EMBEDDING_MODEL in db.js auto-invalidates old stored vectors on next start (see meta table), so mixing models never silently corrupts similarity scores.This only runs in the long-lived MCP server session (the one wired into the agent's mcpServers config) — the hook-capture path (adapters/*/capture.js) spawns a fresh process per event and sets HIVE_MEMORY_LIGHTWEIGHT=1 to skip embedding there, so hook latency is unaffected. Any backlog of un-embedded rows (legacy entries, or ones written through the lightweight path) gets embedded lazily the next time memory_recall runs.
If the model can't load (e.g. no internet on first run), recall falls back to keyword-only search instead of failing.
Reranking. After keyword+semantic fusion produces a rough top pool, a second model (RERANKER_MODEL in db.js, tss-deposium/bge-reranker-v2-m3-onnx-int8, ~560MB) scores the query against each candidate directly and re-sorts before the pool is cut down to the requested limit. This is slower per call than the fusion step alone but meaningfully more accurate - measured on this installation's real data, it scored the correct past answer at 0.999 vs -9.5 to -10.6 for unrelated candidates. Falls back to the fusion order unchanged if the reranker can't load.
# 1. install
./install.sh
# 2. connect to your agent — install.sh prints the exact JSON block to paste
# into ~/.claude.json under "mcpServers" (or the equivalent config for
# Cursor / Codex CLI, see adapters/)
# 3. verify: from Claude Code, ask it to call memory_stats — should return
# { "total": 0, "byScope": [], "latest": undefined } on first run
The database file is created automatically on first run of server.js (see db.js), at the path given by HIVE_MEMORY_DB (default ./hive-memory.db).
adapters/ wires the server into specific agents. Each adapter is a thin capture layer — no storage/search logic lives there, it only calls this server's existing MCP tools.
adapters/claude-code/ — hooks.json + capture.js (SessionStart, UserPromptSubmit, PostToolUse, Stop)adapters/cursor/ — hooks.json + capture.js (beforeSubmitPrompt, afterShellExecution, afterFileEdit, stop)adapters/codex/ — README only; MCP-compatible, connects to server.js directly, no hooks neededcli.js is the only thing that writes to an agent's config. It's explicit and human-triggered — no automatic edits happen anywhere in this project.
node cli.js status
# Agent Installed Attached
# Claude Code found attached
# Cursor found not attached
# Codex not found -
node cli.js attach cursor # writes ~/.cursor/hooks.json for real
node cli.js attach all # attaches every installed agent, skips the rest
watcher.js detects installed agents and tells you what to run — it does not silently edit your config files. Event-driven via fs.watch (no polling, near-zero idle CPU): it wakes up when an agent's config dir/file appears or changes, checks (read-only) whether hive-memory is already attached, and if not, prints a one-line notice pointing at the cli.js attach command to run.
node --max-old-space-size=64 watcher.js
# [hive-memory] Found Cursor at ~/.cursor/hooks.json - not yet attached. Run: node cli.js attach cursor
# or in the background, this server's usual pattern:
screen -dmS hive-memory-watcher node --max-old-space-size=64 watcher.js
See .env.example: HIVE_MEMORY_AGENT, HIVE_MEMORY_PROJECT, HIVE_MEMORY_DB.
Set HIVE_MEMORY_PROJECT explicitly if you want one stable memory scope. If unset, the Claude Code/Cursor hook adapters fall back to the hook event's current working directory - fine if each of your projects is its own repo/cwd, but if a session ever cds elsewhere (a subprocess, a temp folder, a nested app dir), that becomes a brand-new, disconnected memory bucket. Pin HIVE_MEMORY_PROJECT in your hook commands and in your MCP server's env (must match) to keep everything under one project regardless of cwd drift.
node cli.js verify [--project X] [--agent X] [--sample N] [--k N]
Builds a ground-truth test set automatically from real history - every captured UserPromptSubmit that's a real question, paired with whichever Stop row answered it before the next question was asked - then re-asks each question as a memory_recall query and checks whether the real past answer comes back in the top-K. Reports the hybrid-search hit rate as shipped, the same search restricted to key='Stop' rows only (a diagnostic ceiling), and a bare chronological recent-N dump (the closest thing to "no real retrieval"). No memory at all is 0% by construction. See CHANGELOG for the measured history: 3% → 33% after switching embedding models, excluding raw prompt/tool-call rows from being recall results, fixing the benchmark's own fixture pairing, and adding a reranker.
npm test
Runs node --test --test-concurrency=1 tests/*.test.js. Concurrency is pinned to 1 on purpose - the embedding model (~1.2GB) and reranker (~560MB) both get loaded fresh per spawned server.js process, and running many test files in parallel (Node's default) can exceed available RAM on a modest VPS and get processes OOM-killed mid-test. Slower (~90s vs ~45s), but reliable.
Run analytics queries on ClickHouse — explore schemas, execute SQL, fetch results
Run Claude Code as an MCP server so any agent can delegate coding tasks to it
Browser automation using accessibility snapshots instead of screenshots
Google's universal MCP server supporting PostgreSQL, MySQL, MongoDB, Redis, and 10+ databases