mem-graph

mem-graph

Graph-relational memory MCP server for persistent LLM memory, featuring wikilinks, BM25 auto-linking, spreading activation, and synaptic decay across five memory layers.

Category
访问服务器

README

mem-graph

MCP server for graph-relational memory: a v2 evolution of mem-sol that adds a graph layer (wikilinks, BM25 auto-linking, spreading activation, synaptic decay) on top of a layered memory model. Backed by better-sqlite3.

Purpose

Solo learning build exploring graph-relational memory as an MCP substrate. Not production-aimed, not benchmarked against peer systems; the goal is hands-on understanding of layered memory, wikilinks, and spreading activation.

mem-graph is the LLM's persistent memory between opencode sessions. It builds on mem-sol v1's relational foundation and adds:

  • Layered memory model — five discrete layers (working, episodic, procedural, semantic, partner) with layer-aware decay and retrieval
  • Wikilinks — markdown-style [[reference]] syntax in memory content creates hard, operator-curated edges
  • BM25 auto-linking — on every insert, soft edges are auto-created to textually-overlapping memories in the same project
  • Spreading activation — retrieval is text-match + neighborhood traversal with weight attenuation, not pure FTS
  • Synaptic decay — synapse weights erode over time, with separate rates per layer pair and per connection type, and access-based exemption for hot edges

Install

Clone, install, and register as an MCP server:

git clone https://github.com/GoVanAI/mem-graph
cd mem-graph
npm install

Add this entry to your MCP client config (e.g., ~/.config/opencode/opencode.jsonc or Claude Code's MCP config):

{
  "mcpServers": {
    "mem-graph": {
      "command": "npm",
      "args": ["start", "--prefix", "/absolute/path/to/mem-graph"],
      "env": {
        "MEM_GRAPH_DIR": "/absolute/path/to/your/mem-graph-db"
      }
    }
  }
}

Replace both placeholder paths with absolute paths on your machine. The server reads MEM_GRAPH_DIR literally — ~ is not expanded at runtime. Default (without MEM_GRAPH_DIR) is ~/.local/share/mem-graph/memory.db.

Run (locally)

npm start

Tests

npm test           # run once, exits 0 on success
npm run test:watch # watch mode for development

108 tests across 9 files exercise the substrate in-memory via :memory: SQLite. Run takes ~500ms. See tests/ for fixtures and tests/helpers.ts for the createInMemoryDb() factory.

Configuration

The MCP reads:

  • MEM_GRAPH_DIR — directory for the SQLite database. Default: ~/.local/share/mem-graph/. The DB file is memory.db inside. Override by setting the env var before launch.

Tools (27)

Group Tools
SQL (4) sql_query, sql_execute, sql_introspect, list_databases
Orient (4) memory_overview, memory_prime, memory_projects, memory_categories
Search (5) memory_search, memory_recent, memory_get, memory_changes, memory_stats
Write (7) memory_add, memory_update, memory_supersede, memory_mark, memory_boost, memory_tag_add, memory_tag_remove
Graph (6) memory_synapse_create, memory_synapse_traverse, memory_activate, memory_decay, memory_spread_stats, memory_stale
Import (1) memory_import_from_mem_sol

memory_add write pipeline

On every memory_add:

  1. Insert into memories (FTS5 triggers fire automatically)
  2. Insert tags into memory_tag (junction table, no JSON)
  3. Extract [[wikilinks]] from content, resolve to memory ids (id → title → slug), upsert synapses
  4. Run BM25 auto-link against same-project memories, upsert bm25_auto synapses
  5. Enforce 50/50 synapse cap (prune lowest-weight bm25_auto if exceeded)
  6. Return: { id, wikilinks_resolved, broken_wikilinks, auto_links_created }

memory_activate (the headline graph tool)

Spreading activation retrieval. Inputs: query (FTS5 string), max_hop_depth (default 2), min_synapse_weight (default 0.3), limit_cap (default 20), land_on_layers (default all except working), pass_through_layers (default [semantic]), project_id (optional).

The recursive CTE carries a path column so the pass-through check can correctly verify "any ancestor in the path is a pass-through layer" (the v1 review's critical issue 1 is fixed here).

memory_stale (operational hygiene)

Find entries not accessed in N days. Inputs: days (default 30), project_id (optional), lifecycle (allow-list: permanent, milestone, ephemeral), layer (allow-list: working, episodic, procedural, semantic, partner), limit (default 50, max 500).

Each result row includes never_accessed: boolean (true when accessed_at IS NULL), making the cold-set cohort grep-able in JSON output. NULLs sort first — never-accessed entries surface at the top of the result set.

memory_tag_add / memory_tag_remove (quiet curation)

Tag curation tools that touch only the memory_tag junction table. Do NOT re-run wikilink extraction or BM25 auto-link. Do NOT bump accessed_at / access_count (tag curation is not a read). Idempotent: re-adding the same tag returns added: false; removing a missing tag returns removed: false.

memory_import_from_mem_sol (v1 → v2 migration)

One-shot migration from a mem-sol v1 SQLite DB. Pipeline: insert memories (FTS5 triggers fire) → parse JSON tags into memory_tag → two-pass wikilink extraction (handles forward references) → migrate v1 memory_links as wikilink synapses. Idempotent on (project_id, title). Auto-link is deferred to next activation.

Field-mapping highlights: projectproject_id, relevance_scoreimportance_score, JSON-encoded tags → junction rows. Layer defaults to episodic for v1 entries (configurable). Source field remapped to import for all v1 origins.

Schema

See src/db.ts for the canonical DDL. Quick reference:

  • memories — relational layer; columns: id, layer, title, slug, content, project_id, category, lifecycle, status, confidence, boost, summary, session_id, source, created_at, updated_at, accessed_at, access_count, importance_score, expires_at, refresh_strategy
  • memory_tag — junction table, (memory_id, tag) PK with ON DELETE CASCADE
  • synapses — graph edges; source_id, target_id, connection_type (wikilink / bm25_auto / parent_child), weight (0.0–5.0), access_count
  • memories_fts — FTS5 mirror of memories (porter stemmer + 2/3-char prefix), kept in sync by triggers
  • decay_matrix(source_layer, target_layer, connection_type) → decay_rate; wildcard * for target_layer

Five layers

Layer Purpose Decay (vs same layer)
working In-progress, in-flight Aggressive (0.70 wikilink, 0.40 bm25)
episodic Session events, time-anchored Moderate (0.95 wikilink, 0.88 bm25)
semantic Connective tissue, conceptual Stable (0.99 wikilink, 0.93 bm25)
procedural How-to, never-fade rules Highly stable (0.995 wikilink, 0.98 bm25)
partner User model, prefs Most stable (0.999 wikilink, 0.97 bm25)

Locked decisions (v2 design doc §12 + review fixes)

# Decision Choice
D1 Tag storage Junction table memory_tag
D2 Wikilink direction author = source
D3 Cycle prevention NOT EXISTS subquery
D4 Decay frequency Tool exposed, runs via cron
D5 Synapse cap 50 in + 50 out per memory, enforced on insert
D6 Wikilink rendering Auto-render to title in tool output
D7 access_count on synapses Both memories and synapses
D8 ID format Integer, autoincrement

Project context

  • The MCP is project-local (this directory) but the database is user-global (~/.config/opencode/mem-graph/memory.db by default).
  • Register in ~/.config/opencode/opencode.jsonc under the mem-graph MCP name; tools will be prefixed mem-graph_.
  • Mem-graph coexists with mem-sol v1 — they are independent servers, independent databases.

Out of scope (explicitly deferred)

  • cwd ↔ project binding
  • Entry versioning / supersedes chain (only the basic memory_supersede tool exists)
  • Tag-intersection queries (schema supports it via the junction table; no tool yet)
  • knowledge.db (separate concern)
  • Auto-link-on-read philosophy (R from analysis § 3.1, deferred to Tier 3+)

v0.2 / Tier 1 closure (2026-07-04)

Tier 1 implementation closed via loop-eng protocol, 6 iterations, 108 tests added. Specifically:

  • R1 — Vitest suite covering wikilinks, auto-link, activate CTE, decay matrix, supersede; in-memory DB factory via exported SCHEMA_SQL + DECAY_MATRIX_SEED.
  • R2memory_tag_add / memory_tag_remove quiet tools; no wikilink or auto-link re-run on tag change.
  • R5memory_stale extended with lifecycle + layer filters; explicit never_accessed boolean surfaces the 28-row cold set.
  • R3memory_import_from_mem_sol one-shot migration from v1 SQLite DB; idempotent on (project_id, title); preserves connections (not v1 type labels).
  • R4category taxonomy documented (11 values: 9 standard + 3 first-class: commitment, open_question, trigger). No CHECK constraint added — agent-as-author migration is the right time to revisit.

Tool count grew from 24 → 27. Preserve-list (SQLite substrate, wikilinks-in-prose, 50-cap bm25-only pruning, 20-row decay matrix, 5-layer + 3-connection-type model) was held intact across all five iterations.

License

MIT

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选