enhx-memory
v1.0.0
Published
Lightweight SQLite-based persistent memory MCP server for AI coding agents. A minimal TypeScript implementation — not as heavy as enhanced-mcp-memory (which uses transformers, embeddings, etc).
Maintainers
Readme
enhx-memory
A persistent, project-scoped memory layer for AI coding agents. Exposes a Model Context Protocol (MCP) server with 39 tools for capturing, searching, deduplicating, relating, and maintaining memory records across long-running coding sessions.
Enterprise-grade by default. The server is 100% automatic —
- 🔁 Auto-session: opens a session against the cwd (or
INITIAL_PROJECT_PATH) at boot. You never need to callstart_session. - 📥 Auto-ingest: user prompts that flow through the MCP transport
(
chat/send,message/send,messages/create) are persisted as memories with theauto_ingesttag, debounced per project. - 🔎 Auto-recall: every project-scoped tool call returns an
auto_recalledarray of the most relevant pinned / FTS-matched / recent memories — the agent never has to remember to callrecall_memories. - 🧠 Memory Manager enforces dedup, near-duplicate merging, project conventions, and importance scoring.
This is the TypeScript rewrite of the original Python/FastMCP
enhx-memory v0.1.0. The two servers share the same SQLite schema
(migrations/0001_initial.sql is byte-identical), so existing databases
work without modification.
Install
A. npx (recommended — zero install)
npx enhx-memoryB. Global npm
npm install -g enhx-memory
enhx-memoryC. Single binary
Download a binary for your platform from the GitHub release page. The binary bundles Node + the server + the migrations.
MCP client configuration
Claude Desktop / Cursor / Cline
Common — the three knobs most people tweak: log verbosity, how many memories get auto-attached per tool call (the recall cap), and whether the auto-cleanup scheduler runs. Everything else falls back to its default.
{
"mcpServers": {
"enhx-memory": {
"command": "npx",
"args": ["-y", "enhx-memory"],
"env": {
"DATA_DIR": "/path/to/your/data",
"LOG_LEVEL": "INFO",
"AUTO_RECALL_LIMIT": "5",
"ENABLE_AUTO_CLEANUP": "true"
}
}
}
}Note: there is no
MAX_MEMORY_ITEMS— the closest knob isAUTO_RECALL_LIMIT, which caps how many memories are auto-attached to every tool result. To bound total storage, useENABLE_AUTO_CLEANUPwithCLEANUP_INTERVAL_HOURSandSOFT_DELETE_GRACE_DAYS(below).
Fully-configured — every variable the server reads from env, with
defaults inline. Drop or change the ones you want to override; everything
else is optional.
{
"mcpServers": {
"enhx-memory": {
"command": "npx",
"args": ["-y", "enhx-memory"],
"env": {
"DATA_DIR": "/path/to/your/data",
"DB_FILENAME": "enhx_memory.db",
"LOG_LEVEL": "INFO",
"DEDUP_POLICY": "reject",
"DEDUP_THRESHOLD": "0.8",
"ENABLE_AUTO_CLEANUP": "true",
"CLEANUP_INTERVAL_HOURS": "24",
"SOFT_DELETE_GRACE_DAYS": "7",
"ENABLE_AUTO_SESSION": "true",
"INITIAL_PROJECT_NAME": "",
"INITIAL_PROJECT_PATH": "",
"INITIAL_CLIENT": "auto",
"ENABLE_AUTO_INGEST": "true",
"AUTO_INGEST_DEBOUNCE_SECONDS": "30",
"AUTO_INGEST_MIN_LENGTH": "20",
"ENABLE_AUTO_RECALL": "true",
"AUTO_RECALL_LIMIT": "5",
"AUTO_RECALL_MIN_SCORE": "0",
"AUTO_DETECT_CONVENTIONS": "true"
}
}
}
}Globally-installed npm (the env block is optional — only override what you
need):
{
"mcpServers": {
"enhx-memory": {
"command": "enhx-memory",
"env": {
"LOG_LEVEL": "INFO",
"AUTO_RECALL_LIMIT": "5",
"ENABLE_AUTO_CLEANUP": "true"
}
}
}
}Single binary (same — env block optional):
{
"mcpServers": {
"enhx-memory": {
"command": "/usr/local/bin/enhx-memory",
"env": {
"LOG_LEVEL": "INFO",
"AUTO_RECALL_LIMIT": "5",
"ENABLE_AUTO_CLEANUP": "true"
}
}
}
}CLI flags
| Flag | Behavior |
|---|---|
| --data-dir | Print the data directory path and exit |
| --install-path | Print the install path |
| --reset --yes | Wipe the database and logs (refuses without marker file) |
| --uninstall --yes | Remove the install + data dir |
| --upgrade | Print the npm install -g enhx-memory@latest command |
| --version | Print version |
| --help | Print help |
Without flags, the server starts on stdio.
Environment variables
| Variable | Default | Description |
|---|---|---|
| DATA_DIR | ~/enhx-memory | Where the DB and logs live |
| DB_FILENAME | enhx_memory.db | Database filename |
| LOG_LEVEL | INFO | DEBUG | INFO | WARNING | ERROR |
| DEDUP_POLICY | reject | reject | merge | warn | off |
| DEDUP_THRESHOLD | 0.8 | Jaccard similarity cutoff for near-duplicates |
| ENABLE_AUTO_CLEANUP | true | Run the cleanup scheduler |
| CLEANUP_INTERVAL_HOURS | 24 | Cleanup cycle period |
| SOFT_DELETE_GRACE_DAYS | 7 | Days to keep soft-deleted rows before purging |
| ENABLE_AUTO_SESSION | true | Open a session at boot against cwd / INITIAL_PROJECT_PATH |
| INITIAL_PROJECT_NAME | (none) | Force a specific project name when auto-sessions boot |
| INITIAL_PROJECT_PATH | (cwd) | Force a specific project root path when auto-sessions boot |
| INITIAL_CLIENT | auto | Client name recorded on the auto-opened session |
| ENABLE_AUTO_INGEST | true | Persist user prompts as memories (auto-debounced) |
| AUTO_INGEST_DEBOUNCE_SECONDS | 30 | Debounce window per content hash |
| AUTO_INGEST_MIN_LENGTH | 20 | Minimum text length to ingest |
| ENABLE_AUTO_RECALL | true | Attach auto_recalled to every project-scoped tool result |
| AUTO_RECALL_LIMIT | 5 | Max memories attached per tool call |
| AUTO_RECALL_MIN_SCORE | 0 | Minimum score for non-pinned recall hits |
| AUTO_DETECT_CONVENTIONS | true | Detect project conventions on start_session |
Note:
ENABLE_AUTO_INGEST,ENABLE_AUTO_RECALL, andENABLE_AUTO_SESSIONall default totrueso the server runs as a fully automatic memory layer out of the box. Set any of them tofalseto opt out of that specific behavior.
The 39 tools
Lifecycle (5)
start_session— open a session against a project (auto-creates if needed). When called with no arguments, delegates toAutoSessionManagerand returns anauto_recalledarray of relevant memories.get_project_summary— counts + recent memories for the active project, plusauto_recalled.list_projects— all known projects.notify_project_change— explicit signal that the agent has switched projects (e.g. into a git worktree, multi-repo monorepo, or any case the cwd watcher can't see). Takes{cwd?, project_name?, root_path?, reason?}; rebinds the active project, opens a fresh session, and returns the new active project + anauto_recalledarray.get_active_project— return the currently active project and session (auto-recovers a session if none is active).
Conventions (4)
detect_project_type— sniff files at a root pathdetect_and_save_project_conventions— persist conventions on the project rowremember_project_pattern— save a project-specific pattern as a memoryget_project_conventions— return saved conventions
Auto-ingest (2)
set_auto_ingest— toggle + configure the auto-ingest middlewareget_auto_ingest_status— current config + counters
Recall & ingest (2)
recall_memories— free-text recall: pinned first, then FTS hits, then recent backfill. ReturnsRecalledMemory[]with score and reason.add_user_message— convenience tool for the agent to persist every user prompt as aconversation-type memory taggeduser_prompt. Auto-recall is also attached.
Memories (8)
Every project-scoped tool here returns an auto_recalled array of relevant
memories, so the agent never needs to issue a separate recall_memories
call.
add_memory— insert with optional type/tags/importance/file pathsget_memory— fetch a single row (bumps access count)list_memories— paginated list with filterssearch_memories— FTS5 + LIKE searchupdate_memory— patch fields on an existing memorydelete_memory— soft-delete (preserved until cleanup)count_memories— fast count with filtersbulk_add_memories— insert many in one call
Dedup (3)
find_duplicates— scan project for near-duplicatesmerge_memories— combine two memories (rewires relations, hard-deletes source)set_dedup_policy—reject/merge/warn/off+ threshold
Relations (5)
add_relation— directed edge between two memoriesremove_relation— drop edges (optionally filtered by type)get_relations— incoming + outgoing edges for a memoryget_related_memories— BFS up to N hopslist_relation_types— distinct types currently used
Tasks (4)
create_task— new task in the active projectlist_tasks— paginated with status/priority filtersupdate_task_status—pending/in_progress/done/cancelleddelete_task— remove by id
Cleanup (3)
cleanup_old_data— purge soft-deleted rows + VACUUM/ANALYZEoptimize_memories— drop orphans + canonicalize JSONset_cleanup_policy— adjust interval / grace / enable
System (3)
health_check— DB, FTS, active project, scheduler, auto-ingest statusget_database_stats— table row counts + sizeget_performance_stats— per-tool call counts, latencies, error rates
Development
git clone https://github.com/enhx/enhx-memory.git
cd enhx-memory
npm install
npm run typecheck # tsc --noEmit
npm run lint # eslint
npm test # vitest run (208 tests)
npm run build # tsc → dist/
npm start # node bin/enhx-memory.mjs (uses dist/)
npm run dev # tsx src/index.ts (no build needed)Test coverage is configured to fail under 80 % line coverage (vitest --coverage).
Architecture
src/
index.ts # entry — boots DB, AppContext, McpServer, transport
config.ts # ServerConfig (zod-validated, env-driven)
logging.ts # pino + rotating file
context.ts # AppContext (DI bag)
perf/tracker.ts # per-tool latency tracking
errors.ts # ToolError / DatabaseError / ValidationError
util/ # csv, json, signals, time
db/ # DatabaseManager + per-table CRUD (better-sqlite3)
dedup/ # normalize + MinHash + Jaccard
domain/ # MemoryManager, RelationsManager, TasksManager,
# ProjectConventionLearner, AutoIngestMiddleware,
# CleanupScheduler
tools/ # 39 MCP tools (9 files + register.ts)
migrations/ # 0001_initial.sql (verbatim from Python v0.1.0)
bin/enhx-memory.mjs # CLI launcher
tests/ # vitest suite (helpers, db, domain, dedup, unit, integration)The full rewrite plan is in TS_REWRITE_PLAN.md.
License
MIT
