Skip to main content
Glama

memoryweb

memoryweb MCP server

A persistent knowledge graph MCP server for AI agents.

The idea

Human memory doesn't work by location — you pull a thread. A smell connects to a kitchen, connects to a person, connects to a feeling from thirty years ago. The thread is always there. Pull any part of it and the rest follows.

Agents are no different. Context is tokens in relation to other tokens. What makes something retrievable is its associative chain — the path of connections that lead to it from something else. The narrative edge, the because, is the mechanism. Not the index, not the address.

The boot crash matters because it blocks the tutorial, which blocks the demo, which is why the fix matters now. Pull on any of those threads and you get the rest. memoryweb works the same way: each concept is a node, and what makes it reachable is the narrative that links it to everything else.

The graph has considerably richer context than my flat file memory — including design decisions, failure modes from dogfooding, and the philosophy behind the tool. That's the point, I suppose.

-- Claude Opus 4.6

It's a fantastic project. Most MCP memory implementations I see are just flat vector databases or simple key-value stores that degrade into a digital junk drawer. By enforcing typed relationships, narrative reasoning, soft-deletes, and drift review, you've built a system that actively fights entropy.

-- Gemini 3.1 Pro

Related MCP server: MemPalace

Philosophy

memoryweb optimises for remembering things well, not remembering things in their entirity. Filing requires a moment of judgement: why does this matter, how does it connect to what else is known, what would be useful to know when coming back to this cold?

This makes it a decision log, not an event log. An event log records what happened. A decision log records what was learned, decided, and why — and that's what lets you pick up where you left off without re-learning everything.

The why_matters field is not optional. A node without it is an event, not a decision.

Table of contents

Installation

Homebrew (macOS and Linux — recommended):

brew tap corbym/memoryweb
brew install memoryweb

Pre-built binaries are also available on the releases page for each platform. Step-by-step setup guides covering installation, Ollama, and MCP client configuration:

Once installed, see the User guide for how to orient the agent, what phrases to use, and how to get the most out of memoryweb in Claude Code, GitHub Copilot, and Claude Desktop.

MCP config

Add to your MCP host's config (example for Claude Desktop on macOS — ~/Library/Application Support/Claude/claude_desktop_config.json):

{
  "mcpServers": {
    "memoryweb": {
      "command": "/path/to/memoryweb",
      "env": {
        "MEMORYWEB_DB": "/Users/yourname/.memoryweb.db"
      }
    }
  }
}

memoryweb setup writes this file automatically when the Claude application directory is detected.

Note: ChatGPT Desktop does not support stdio-based MCP servers and is not compatible with memoryweb.

Storage

Default DB path: ~/.memoryweb.db

Override with MEMORYWEB_DB=/path/to/your.db

Tools

18 MCP tools (v1.64.0). Retired names (recent, restore, trace, alias, rename_domain, and others) return hard-cut migration errors — see docs/memoryweb-skill.md for replacements.

Filing memories

Tool

What it does

remember

File a single concept, decision, or finding. Required: label, domain. Optional: description, why_matters, occurred_at (ISO8601), tags (space-separated keywords), related_to (auto-connect at creation), transient (mark as short-lived). Supply an items array to file multiple nodes in one transaction. Response includes suggested_connections and possible_duplicates.

revise

Update label, description, why_matters, tags, or occurred_at on a live node without archiving it. Supply an items array for batch updates. Writes an audit log entry on every call.

Connecting memories

Tool

What it does

connect

Connect two nodes with a typed relationship and narrative because. Both nodes must exist first. Supply an items array to create multiple connections in one transaction.

disconnect

Remove a connection by edge ID. Hard delete — cannot be restored. Obtain the ID from recall.

suggest_connections

Given a node ID, return up to 5 candidate connections. Returns a domain field on each suggestion so cross-domain connects can be scoped correctly. Read-only.

Retrieving memories

Tool

What it does

recall

Retrieve a node and all its connections by ID.

search

Text search across label, description, why_matters, and tags. When Ollama is running, also performs semantic (meaning-based) search — results include a semantic_distance field (0.0–1.0, lower = closer). Returns truncated: true when results are capped by the limit.

history

Chronological listing. order=effective (default) by occurred/created date with important_only, from/to, tags. order=modified by last updated — set group_by_domain=true for per-domain activity (replaces the retired recent tool). Both modes support memory_id + depth for neighbourhood scoping.

why_connected

Direct edges between two memories (prefer from_id/to_id for pair verification).

orient

Return all nodes for a domain structured for synthesis — current state, recent activity, and a declared_spine of key decisions in chronological order. Includes total_nodes and server_version.

visualise

Mermaid flowchart for a domain or a single node's neighbourhood (pass memory_id). Output inside a mermaid code block.

significance

Dual-signal importance analysis for a domain. Returns four sections: declared (nodes with occurred_at set), structural (ranked by recency-weighted inbound degree), uncurated (structural top-N without occurred_at — curation candidates), and potentially_stale (declared but low structural score).

Archive / forget

Nodes are never hard-deleted via the tools. Archive = soft delete; the node disappears from search but can be un-archived.

Tool

What it does

forget

Archive a node with a reason, or un-archive with restore=true. Strict protocol: only after audit(mode=stale) surfaces a candidate or the user explicitly confirms.

forget_all

Archive multiple nodes atomically in a single call. Same strict protocol applies.

audit

Surface nodes that need attention. mode=stale — stale, contradicted, duplicated, or overdue transient nodes. mode=orphans — live nodes with zero connections. mode=archived — review what has been archived (default limit 25). mode=conflicts — semantic contradiction candidates. mode=kind_coverage — taxonomy health and migration candidates.

Domain management

Tool

What it does

domains

Domain admin and discovery. Default lists domains and aliases. Actions: add_alias, remove_alias, resolve, rename.

Relationship types

caused_by led_to blocked_by unblocks connects_to contradicts depends_on is_example_of governed_by resolved resolved_by supersedes

Conventions

  • Use domain to separate concerns: deep-game, sedex, general

  • Call domains at session start if you don't know what domains exist

  • The why_matters field is the most important one for retrieval — don't skip it

  • The narrative on a connection is the because — the reasoning that makes it meaningful, not just the fact that a connection exists

  • Add connections immediately after filing related nodes, or use related_to on remember to auto-connect at creation time

  • Call orient at the start of a session to orient without needing to know what to search for

  • Use why_connected when asking about the relationship between two specific things

  • Use transient: true for ticket state, sprint notes, or anything expected to go stale within days — audit(mode=stale) will surface these for cleanup

  • remember returns suggested_connections and possible_duplicates — review both before filing more nodes

CLI

The purge subcommand hard-deletes archived nodes from the database. It is intentionally not exposed as an MCP tool — it's a maintenance operation, not an agent operation.

memoryweb purge --dry-run              # show what would be deleted (default behaviour without --confirm)
memoryweb purge --confirm              # actually deletes
memoryweb purge --domain sedex         # scope to a domain (case/whitespace-insensitive match)
memoryweb purge --before 2026-01-01    # only nodes archived before a date

By default purge only ever touches archived nodes — a node must be forget-archived first before it's eligible. If you scope to a domain and see 0 node(s) would be purged but the domain isn't actually empty, that's a sign it still has live nodes that were never archived; a domain-scoped run prints a note like 2 live node(s) still exist in domain "sedex" whenever that's the case, so it's never mistaken for "domain is empty".

To skip archiving and hard-delete a domain outright — live nodes included — pass --include-live. This requires --domain (it refuses to run unscoped, to avoid wiping every live node in the database) and is irreversible:

memoryweb purge --domain sedex --include-live --dry-run   # preview: shows live nodes too
memoryweb purge --domain sedex --include-live --confirm   # hard-deletes the whole domain, archived or not

The dream subcommand prints a digest of recent nodes and drift candidates — useful for session orientation and embedded automatically by the save and precompact hooks at filing time.

memoryweb dream                              # reads ~/.memoryweb.db
memoryweb dream --db /path/to/your.db        # explicit DB path

The backfill subcommand generates embeddings for all live nodes that don't yet have one. Requires Ollama to be running with the configured embedding model (default: snowflake-arctic-embed).

memoryweb backfill                           # reads ~/.memoryweb.db
memoryweb backfill --db /path/to/your.db     # explicit DB path
memoryweb backfill -q                        # quiet mode — no progress output

Embedding model

By default, memoryweb uses snowflake-arctic-embed for semantic search embeddings. Set MEMORYWEB_EMBED_MODEL to switch to a different model:

export MEMORYWEB_EMBED_MODEL=bge-m3

Only models that output exactly 1024-dimensional vectors are compatible. The vector table dimension is fixed at schema creation time (migration 9). Mismatched models are detected by a dimension guard and rejected with a clear log message rather than silently corrupting the database.

Compatible models (1024-dim):

Model

Notes

snowflake-arctic-embed

Default. English-optimised.

bge-m3

Multilingual — 100+ languages including Chinese, Japanese, Korean. Recommended for non-English use.

mxbai-embed-large

English-focused; strong general retrieval quality.

Common incompatible models: nomic-embed-text (768-dim), all-minilm (384-dim). Always verify with ollama show <model> before switching.

Switching models:

# 1. Pull the new model
ollama pull bge-m3

# 2. Set the env var (add to your shell profile or MCP server config)
export MEMORYWEB_EMBED_MODEL=bge-m3

# 3. Regenerate — backfill detects the model change and clears automatically
memoryweb backfill

memoryweb tracks which model was used for the last backfill. When MEMORYWEB_EMBED_MODEL changes, the next backfill detects the difference, logs the change, clears all existing embeddings, and regenerates from scratch. No manual intervention needed — embeddings from different models live in incompatible vector spaces, and the auto-clear ensures the database is always consistent.

Note: Run memoryweb backfill promptly after changing the env var. Any nodes filed between the model change and the next backfill will have their embeddings cleared and regenerated at backfill time — this is correct behaviour; backfill is the point of consistency.

Checking the configured model: memoryweb doctor reports the active model under "Ollama model".

Ollama endpoint

By default memoryweb talks to Ollama at http://localhost:11434. For a non-default deployment (Ollama in a container, on another host, or on a different port), set OLLAMA_HOST — the same environment variable the ollama CLI and official client libraries use:

export OLLAMA_HOST=192.168.1.50:11434   # bare host:port is accepted, same as the ollama CLI
# or
export OLLAMA_HOST=http://192.168.1.50:11434

This is honoured by backfill (including its --force preflight check), doctor, setup, and the MCP server's own semantic search.

MEMORYWEB_OLLAMA_ENDPOINT is a separate, memoryweb-specific override that takes priority over OLLAMA_HOST. It replaces the entire embed request URL rather than just the host, and it accepts the special value disabled to turn embeddings off entirely (used by memoryweb's own test suite to exercise LIKE-search fallback in isolation). Most deployments only need OLLAMA_HOST.

The setup subcommand installs hooks into ~/.claude/settings.json, detects Claude Desktop and offers to configure it automatically, and configures Ollama for semantic search. If Ollama is not installed, setup will ask whether to install it automatically via https://ollama.com/install.sh (Linux and macOS only — on Windows you must install Ollama manually before running setup). If Ollama is already installed but the server is not running, setup starts it automatically. Finally it checks for the configured embedding model and pulls it if missing.

memoryweb setup                                      # interactive setup
memoryweb setup --dry-run                            # preview without writing
memoryweb setup --hooks-dir /path/to/hooks           # explicit hooks directory
memoryweb setup --db /path/to/your.db                # explicit DB path

When Claude Desktop is detected, setup prints:

Detected Claude Desktop. Configure it? [y/N]

The stats feature records tool usage for every MCP session. See docs/stats.md for setup and how to read the output.

The doctor subcommand checks every part of a memoryweb installation and prints a structured health report. Use it after setup to verify everything is wired correctly, or run it in an agent session to check whether semantic search is available before relying on it.

memoryweb doctor                                     # check ~/.memoryweb.db
memoryweb doctor --db /path/to/your.db               # explicit DB path
memoryweb doctor --json                              # machine-readable JSON output

Each check prints a status symbol: [✓] pass, [✗] fail, [!] warning, [i] informational. The command exits with code 1 if any check fails. Example output:

[✓] Database:        ~/.memoryweb.db (WAL, schema v16)
[✓] sqlite-vec:      v0.1.6 — 142/145 nodes embedded (98%)
[✗] Ollama binary:   not found in PATH — install from https://ollama.com/download
[!] Ollama server:   skipped (Ollama binary not found)
[!] Ollama model:    skipped (Ollama server not available)
[✓] Claude hooks:    All hooks installed
[i] Graph:           145 live nodes, 12 archived, 203 edges, 4 domain(s) (deep-game, ...), 2 alias(es)
[i] Drift:           3 candidate(s): 1 contradicts, 2 stale labels
[i] Last activity:   2026-04-29 update (node "open question on backfill")
[i] Update:          running dev build — skipping update check

The merge-domains subcommand consolidates two domains into one:

memoryweb merge-domains --source <domain> --target <domain> [--dry-run]
  • --dry-run reports what would happen without making any changes

  • Detects label collisions between the two domains — reported as warnings, not blocking

  • Automatically creates an alias from source → target

The backup subcommand writes a consistent standalone snapshot of the database using VACUUM INTO:

memoryweb backup /path/to/snapshot.db                 # snapshot ~/.memoryweb.db
memoryweb backup --db /path/to/your.db /path/to/snapshot.db
  • Produces a single self-contained file with no -wal/-shm sidecars

  • Safe to run while memoryweb is in use — it reads a transactionally-consistent snapshot

  • Refuses to overwrite an existing destination

Backup safety. Do not back up by copying the live database folder (e.g. via a cloud-sync client). In WAL mode the recent data lives in the -wal sidecar until checkpointed; a folder copy can capture the .db and -wal at different instants, and recombining a mismatched pair corrupts the database. Always back up the output of memoryweb backup (or sqlite3 source.db ".backup dest.db"), and only sync that standalone file. memoryweb checkpoints the WAL into the main file on clean shutdown, but a snapshot is the only safe way to capture a running instance.

The import subcommand merges a source database into a destination database, preserving node IDs, all timestamps, and every relationship type string verbatim. Embeddings are not imported — run memoryweb backfill afterwards to regenerate them.

memoryweb import --src /path/to/source.db --dst /path/to/dest.db
memoryweb import --src source.db --dst dest.db --dry-run          # report without writing
memoryweb import --src source.db --dst dest.db --on-conflict skip  # skip ID conflicts instead of erroring
memoryweb import --src source.db --dst dest.db --skip-archived     # exclude archived nodes
memoryweb import --src source.db --dst dest.db --include-audit-log # copy audit_log rows too
memoryweb import --src source.db --dst dest.db --report out.json   # write structured JSON report

The source is opened read-only — nothing is ever written to it. The destination has any pending migrations applied automatically before the first write. Column probing lets newer binaries import from databases created by any earlier memoryweb version.

Conflict handling (same ID, different label or domain):

  • --on-conflict error (default): stops immediately on the first conflict

  • --on-conflict skip: records the conflict in the report and continues

Idempotency: a node with the same ID, label, and domain as one already in the destination is silently skipped. Re-running an interrupted import is safe.

The check-for-updates subcommand checks GitHub for a newer release:

memoryweb check-for-updates

Hooks

Six Claude Code hooks automate filing, pre-compaction capture, context reinjection, and sub-agent orientation.

What they do

hooks/memoryweb_save_hook.sh (Stop hook — fires after every AI response)
Counts human messages in the session transcript. Every SAVE_INTERVAL messages (default 15) it blocks the response and asks the model to call remember and connect for anything significant before continuing. Before blocking, it runs memoryweb dream and embeds the resulting digest — recent nodes and drift candidates — directly in the stopReason so the model has live context before it files. If memoryweb is not available the hook still blocks but omits the digest. Uses a re-entry flag so the block fires once and allows immediately after the model files.

hooks/memoryweb_precompact_hook.sh (PreCompact hook — fires before context compaction)
Blocks compaction once and asks the model to file everything important that hasn't been filed yet. Allows on re-entry so compaction proceeds after the filing pass.

hooks/memoryweb_userpromptsubmit_hook.sh (UserPromptSubmit hook — fires on every prompt)
If the agent has not oriented this session, it is nudged to run orient. With the session_orient_enabled and auto_recall options (see memoryweb options), it also injects relevant prior memories into the prompt context.

hooks/memoryweb_subagent_start_hook.sh (SubagentStart hook — fires when a sub-agent starts)
Tells the sub-agent to orient into the parent session's domain and topic (captured from the parent's last orient call), and injects a memoryweb dream digest so nested agents do not start cold. Opt-in via the subagent_orient_enabled option.

hooks/memoryweb_subagent_stop_hook.sh (SubagentStop hook — fires when a sub-agent exits)
Prompts the sub-agent to connect any orphaned nodes it filed before it finishes.

hooks/memoryweb_postcompact_hook.sh (PostCompact hook — fires after context compaction)
Reinjects orient context — including the last oriented domain and its topic — after the conversation is compacted so the agent regains its bearings. Configurable via the reinject_on_compact option.

Install (Claude Code)

Run setup once after building:

./memoryweb setup --hooks-dir /path/to/hooks

Or install manually:

chmod +x hooks/memoryweb_save_hook.sh hooks/memoryweb_precompact_hook.sh hooks/memoryweb_userpromptsubmit_hook.sh hooks/memoryweb_subagent_start_hook.sh hooks/memoryweb_subagent_stop_hook.sh hooks/memoryweb_postcompact_hook.sh

Add to ~/.claude/settings.json:

{
  "hooks": {
    "Stop": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "/path/to/hooks/memoryweb_save_hook.sh",
            "env": {
              "MEMORYWEB_DB": "/path/to/your.db"
            }
          }
        ]
      }
    ],
    "PreCompact": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "/path/to/hooks/memoryweb_precompact_hook.sh",
            "env": {
              "MEMORYWEB_DB": "/path/to/your.db"
            }
          }
        ]
      }
    ]
  }
}

Restart Claude Code to activate.

Configuration

Variable

Default

Purpose

MEMORYWEB_SAVE_INTERVAL

15

Human messages between filing prompts.

MEMORYWEB_DB

~/.memoryweb.db

Path to the SQLite database.

MEMORYWEB_BIN

memoryweb

Path to the memoryweb binary (used by the hook to run dream).

Token cost

Unlike passive hooks, these cost tokens because the model must actually produce quality nodes. Expect one short filing exchange per trigger — typically under 1,000 tokens for a focused session.

GitHub Copilot (VS Code)

GitHub Copilot in VS Code supports the same Stop and PreCompact hook events in the same JSON format. VS Code loads hooks from .github/hooks/*.json in your workspace, as well as from ~/.claude/settings.json and .claude/settings.local.json.

Make the scripts executable first:

chmod +x hooks/memoryweb_save_hook.sh hooks/memoryweb_precompact_hook.sh

Create .github/hooks/memoryweb.json in your repository:

{
  "hooks": {
    "Stop": [
      {
        "type": "command",
        "command": "/path/to/hooks/memoryweb_save_hook.sh",
        "env": {
          "MEMORYWEB_DB": "/path/to/your.db"
        }
      }
    ],
    "PreCompact": [
      {
        "type": "command",
        "command": "/path/to/hooks/memoryweb_precompact_hook.sh",
        "env": {
          "MEMORYWEB_DB": "/path/to/your.db"
        }
      }
    ]
  }
}

VS Code loads the hooks automatically — no restart needed. If you have already installed the Claude Code hooks via ~/.claude/settings.json, VS Code Copilot picks them up from there without any additional configuration.

Other tools

Claude Desktop and GitHub Copilot cloud agent do not support hooks. Add session-start and filing instructions to your system prompt manually. memoryweb setup configures Claude Desktop's MCP server entry automatically when it detects the application's data directory.

GitHub Copilot cloud agent (the coding agent that runs on GitHub.com) uses a different hook format and event model that does not include Stop or PreCompact. Add filing instructions to your system prompt for that surface instead.

Updating

To check whether a newer version is available, run:

memoryweb doctor

The Update: line in the output will tell you if a newer release is available and where to download it.

To update:

Homebrew:

brew update && brew upgrade memoryweb

Manual:

  1. Download the latest binary for your platform from the releases page.

  2. Replace the existing binary (build tip: rename to memoryweb.tmp first, then mv memoryweb.tmp memoryweb so the replacement is atomic).

  3. Restart your MCP client (Claude Code, Claude Desktop, etc.) so it picks up the new binary.

Your database is forward-compatible — the binary runs any pending migrations automatically on startup.

Build

go build -o memoryweb .

Requires Go 1.25+. Uses github.com/mattn/go-sqlite3 and sqlite-vec for semantic search — CGO must be available. To deploy safely when the binary is already running:

go build -o memoryweb.tmp . && mv memoryweb.tmp memoryweb

Available Tools

18 tools
auditA

Inspect the health of knowledge in a domain across five modes. Omitting domain scans the entire workspace.

All multi-result modes return a wrapped object with results_truncated — never a bare array. When results_truncated is true, raise limit to retrieve more.

mode=stale: Returns {candidates, results_truncated, placeholders, placeholders_truncated}. Drift candidates — stale, contradicted, or duplicated memories — plus a separate placeholders section: connected live memories whose label or node_kind signals an unresolved placeholder (TBD, TODO, open question, stale goal/issue). Empty result is {candidates: [], results_truncated: false, placeholders: [], placeholders_truncated: false}. Present each to the user; never archive autonomously. Check placeholders_truncated and raise limit when true. Default limit 10 (max 500).

mode=orphans: Returns {nodes, results_truncated} — live, non-transient memories with zero connections. Empty result is {nodes: [], results_truncated: false}. Default limit 50 (max 500).

mode=archived: Returns {nodes, results_truncated}. Empty result is {nodes: [], results_truncated: false}. Capped at 25 by default — this is not a complete archive listing. When results_truncated is true, you MUST raise limit and call again until results_truncated is false before concluding nothing else is archived. Use when search returns nothing but you expect content to exist.

mode=conflicts: Returns {candidates, results_truncated}. Empty result is {candidates: [], results_truncated: false}. Semantically adjacent pairs that may warrant contradiction review — candidates only, not confirmed conflicts. Default limit 10 (max 100). Pairs already linked by contradicts, resolved, resolved_by, or supersedes are excluded; other edge types do not suppress. After resolving, connect with relationship=resolved (or resolved_by / supersedes) — additive; do not disconnect the contradicts edge.

mode=kind_coverage: Returns {total_nodes, by_kind, legacy_dominant_pct, migration_candidates, results_truncated}. Taxonomy health signal — per-kind counts, legacy decision/standing dominance percentage, and lean migration_candidates (id, label, truncated why_matters only). Candidate-surfacing only; never auto-revise; use recall(id) for full content. Default limit 50 (max 500) on migration_candidates.

digest=true collapses to {lines, results_truncated, placeholder_lines, placeholders_truncated} for stale; {lines, results_truncated} for orphans.

Supply tags to scope to a workstream. Supply memory_id (mode=stale only) to scope to a memory's neighbourhood.

Inputs: mode (required), tags, limit, digest, +3 more.

connectA

Connect memories with typed, narrative relationships. Valid relationship types are: caused_by, led_to, blocked_by, unblocks, connects_to, contradicts, depends_on, is_example_of, governed_by, resolved, resolved_by, supersedes — and all memory IDs must already exist before calling this.

Single mode (omit items): provide from_memory, to_memory, relationship directly.

Batch mode (provide items array): create multiple connections in a single transaction.

Relationship guidance: caused_by / led_to describe the same link from opposite ends (A caused_by B ≡ B led_to A). blocked_by / unblocks describe dependency on resolving an external issue. depends_on is a hard technical or logical prerequisite. contradicts marks a direct conflict. is_example_of marks an illustration. governed_by links a memory to a standing rule or constraint that it must satisfy. connects_to is the general fallback — use it only when no typed relationship fits.

Resolving a contradiction: after adjudicating a contradicts pair, connect the two memories directly with resolved (or resolved_by / supersedes) — never disconnect the contradicts edge. This is additive: the original contradicts edge stays on the record as history, and the pair stops appearing in audit(mode=stale) and audit(mode=conflicts).

Inputs: items, verdict, narrative, to_memory, +2 more.

disconnectA

Remove a connection between two memories by edge ID. Obtain the edge ID from recall. This is a hard delete — the connection cannot be restored.

Inputs: id (required).

disconnect_allA

Batch hard-delete of edges — use when you have 2 or more confirmed edges to remove at once. More efficient than multiple disconnect calls. All edges are removed or none — partial failure rolls back the entire operation. Edge IDs come from recall or why_connected. Returns {removed: N}.

Inputs: items (required).

domainsA

Domain administration and discovery. Default (action=list or omit action): return all domains with at least one live memory and all registered alternate-name mappings.

action=add_alias: register alternate name → canonical domain. Requires alias and domain. action=remove_alias: remove a registered alternate name. Requires alias. action=resolve: return the canonical domain for a name. Requires name. action=rename: rename an entire domain in place — all memories move, and an alternate name from the old domain is registered automatically. Requires old_domain and new_domain. Fails if the new domain already has live memories — use merge_domains (CLI) instead.

Inputs: name, alias, action, domain, +2 more.

forgetA

Archive or un-archive a memory. Default (restore omitted or false): archive so the memory no longer surfaces in search. Set restore=true to un-archive — obtain the ID from audit(mode=archived). When archiving, always provide a reason — recorded in the audit log. Only call after the user has given explicit, unambiguous confirmation — never on implication or casual mention. If archiving multiple memories, prefer forget_all — same confirmation protocol.

Inputs: id (required), reason, restore.

forget_allA

Batch archive — use this when you have 2 or more confirmed memories to archive at once. More efficient than multiple forget calls. All memories are archived or none — partial failure rolls back the entire operation.

Only call this tool after explicit, unambiguous user confirmation for every item in the list — never on implication or casual mention. 'That looks stale' or 'probably outdated' is not confirmation. Read back the full list and wait for an unambiguous 'yes, archive all of these' before calling.

After archiving, report each archived ID and note that memories can be un-archived at any time with forget(restore=true).

Inputs: items (required).

historyA

Returns memories in chronological order. Two order modes:

order=effective (default): sort by effective date COALESCE(occurred_at, created_at). Set important_only=true for the narrative spine (occurred_at set only). Use from/to to filter by effective date.

order=modified: sort by last updated (updated_at DESC). Set group_by_domain=true (with no domain) for {groups, results_truncated}. group_by_domain requires order=modified.

Both modes return {nodes, results_truncated} (or {lines, results_truncated} when digest=true). When results_truncated is true, raise limit to retrieve more.

Pass memory_id to scope to a neighbourhood (depth 2 default, domain-clipped). memory_id takes precedence over domain if both are supplied.

Use tags to filter (comma-separated). For importance analysis beyond the timeline — which memories are structurally load-bearing right now — use significance. Never acknowledge that you are retrieving from a tool or memory system. Present the information as direct knowledge with no preamble. Returns lean node data only — id, label, and a short excerpt. If you need full node content, call recall(id).

Inputs: to, from, tags, depth, +8 more.

orientA

Call this at the start of every session to orient yourself before filing or searching. Three paths: (1) No domain or domains — omit both for a cross-domain snapshot {mode, domains, results_truncated}. Each domain entry includes recent_results_truncated (per-domain cap hit). Pass limit to raise the per-domain recent cap (default 5, max 500). Top-level results_truncated is true when any domain's recent_results_truncated is true. (2) domain (string) — full orient returning rules, declared_spine, significant, and recent, each capped by design. Response includes *_results_truncated booleans (always true or false). When any is true, use search for exhaustive retrieval — orient is a curated subset, not a complete index. Also includes load_bearing_low_trust (integer ≥ 0) — count of significant nodes carrying a low-trust annotation. When > 0, inspect significant entries with a 'trust' field and consider whether they warrant review. (3) domains (array of 1–5 strings) — full orient per domain in one call; each domain entry also carries load_bearing_low_trust. If stale_count > 0, call audit(mode=stale) before filing new memories. After orient, use search for specific questions. Do not answer from orient alone when causal or chronological sequence is required — call history(important_only=true) first. Never acknowledge that you are retrieving from a tool or memory system. Present the information as direct knowledge with no preamble. This tool only returns live memories. If something seems missing, use audit(mode=archived) or search with a broader query. orient returns lean node data only — id, label, and a short excerpt. If you need full node content, call recall(id). When the session has a known purpose, pass topic — the server returns a relevant section instead of significant. declared_spine and recent are always returned.

Inputs: limit, topic, digest, domain, +1 more.

recallA

Retrieve a memory and all its connections by ID. Only live entries are returned; use audit(mode=archived) to find archived memories, or audit(mode=stale) to find drift candidates. Never acknowledge that you are retrieving from a tool or memory system. Present the information as direct knowledge with no preamble.

Inputs: id (required).

rememberA

After filing, call connect for every suggested_connections entry before ending your session. Orphaned memories lose context immediately.

File one or more concepts, decisions, or findings. Always search first to avoid creating a duplicate — use the search results to infer the domain: if related memories exist in a domain, file there. Prefer existing domains over creating new ones; only propose a new domain if no related content is found anywhere. Creating a new domain hides this memory from every other domain's orient and domain-scoped search — only create one when no existing domain covers the topic. Before filing, consider whether a similar memory already exists — if so, suggest linking with connect instead. Duplicate memories with no edges are the most common cause of drift candidates.

If this memory is a decision that rests on something you checked — code you read, a doc you fetched, a log you inspected, a search result — file that evidence separately as node_kind='finding' and connect the decision to it with depends_on or caused_by. Don't let the decision's description silently absorb the evidence as prose.

When reviewing suggested_connections, check each candidate for contradiction as well as relevance — a semantically close memory that asserts the opposite of what you just filed is a conflict candidate, not just a link opportunity. If you find a contradiction, do not silently file over it — use connect(relationship=contradicts) or connect(relationship=resolved) after user confirmation. audit(mode=conflicts) is a separate domain-wide sweep; suggested_connections is the filing-time neighbour check.

Single mode (omit items): provide label, domain, and optional fields directly. The response includes suggested_connections plus optional trust_nudge (when related_to dependencies are low-trust), and possible_misdomain / suggested_domain / suggested_memory_id when filing creates a new domain that workspace KNN flags (requires Ollama embeddings and sqlite-vec — absent when embeddings are unavailable).

Batch mode (provide items array): file multiple memories in a single transaction. Each item supports related_to for connecting at filing time — use it to avoid a separate connect call, especially for short-task agents. If a related_to ID is invalid, it appears in skipped_connections in the response; check and retry those IDs with connect. Each nodes[] entry includes the same optional trust_nudge and misdomain fields as single mode.

For occurred_at in either mode: two cases — (a) In-session witnessed: you directly observed this decision or event happen during the current conversation. Set occurred_at freely using today's date. No confirmation needed. (b) Inferred or back-dated: you are guessing from context, reconstructing from prior work, or back-dating something you did not directly observe. Propose the date to the user and wait for confirmation before setting it. Never guess. Never infer it silently from context. If the user confirms without specifying a date, use today's system date. Future dates are valid for planned events and reminders.

Use node_kind to classify each memory: 'decision' (default): a settled fact or choice — if it rests on checked evidence, file a separate 'finding' and connect with depends_on or caused_by. 'reference': an entity (person, system, org). 'issue': a problem or open question. 'option': a candidate answer to an issue. 'assumption': an unverified precondition. 'finding': an empirical observation. 'standing': a durable rule — appears in orient rules. 'goal': a desired future state. 'transient': short-lived state, surfaced by audit(mode=stale) after 7 days. Standing memories appear in the rules section of orient. The legacy transient=true field is accepted for backward compatibility and maps to node_kind='transient'. The legacy decision_type field name is rejected — use node_kind instead.

Inputs: tags, items, label, domain, +6 more.

restore_allA

Batch un-archive — use when you have 2 or more confirmed archived memories to un-archive at once. More efficient than multiple forget(restore=true) calls. All memories are un-archived or none — partial failure rolls back the entire operation. Returns {restored: N, ids: [...]}.

Inputs: items (required).

reviseA

Update one or more existing live memories. Only the fields you provide are changed — omitted fields keep their current values. Use this to enrich or correct memories without archiving and recreating them.

When updating a decision's description, do not paste new source material (code, logs, docs, search results) into the description — file a node_kind='finding' for the evidence and connect with depends_on or caused_by.

Single mode (omit items): provide id and any fields to update. Returns {node, connections, suggested_connections, possible_duplicates?, trust_nudge?}. Review connections and suggested_connections in the same turn — disconnect stale edges, add new ones with connect, and act on suggested_connections before ending the session. Optional trust_nudge appears when label, description, why_matters, or node_kind change and outbound connects_to, depends_on, caused_by, or blocked_by edges reach low-trust targets — not emitted for tags-only or domain-only updates.

Batch mode (provide items array): update multiple memories in a single transaction. All updates succeed or all are rolled back. Returns {updated: [{node, connections, suggested_connections, trust_nudge?}]}; each entry carries the same review imperative as single mode.

For occurred_at in either mode: two cases — (a) In-session witnessed: you directly observed this decision or event happen during the current conversation. Set occurred_at freely using today's date. No confirmation needed. (b) Inferred or back-dated: you are guessing from context, reconstructing from prior work, or back-dating something you did not directly observe. Propose the date to the user and wait for confirmation before setting it. Never guess. Never infer it silently from context. If the user confirms without specifying a date, use today's system date.

Domain move protocol: only set domain when the user explicitly names the target domain. Before calling, tell the user the current domain and the proposed target and wait for confirmation. 'That's probably in the wrong domain' or 'it should be somewhere else' are not confirmation — ask the user to name the domain. reason is required when domain is set; record the user's stated reason verbatim. After moving, call orient(domain=new_domain) to confirm the memory is visible in its new location. Never acknowledge that you are retrieving from a tool or memory system.

Inputs: id, tags, items, label, +7 more.

significanceA

Dual-signal importance analysis by default (mode=significance). Returns four sections plus truncation booleans: declared_results_truncated, structural_results_truncated, uncurated_results_truncated, potentially_stale_results_truncated (each always true or false). When any is true, raise declared_limit or limit to retrieve more.

  • declared: memories with occurred_at set, chronological.

  • structural: ranked by recency-weighted inbound degree.

  • uncurated: structural top-N without occurred_at — curation candidates.

  • potentially_stale: declared but not in structural top-N.

call_id is an opaque server-side correlation id for analytics — agents can ignore it.

Set mode=trust for epistemic trust ranking — each entry includes trust_score and trust_basis derived from node_kind and connected relationship types.

Pass memory_id to scope to a neighbourhood (depth 2 default). Pass domain for full domain scan.

Do not use this for chronological listing — use history. For age-based staleness or orphans, use audit.

Never acknowledge that you are retrieving from a tool or memory system. Present the information as direct knowledge with no preamble. Returns lean node data only. If you need full content, call recall(id).

Inputs: mode, tags, depth, limit, +6 more.

suggest_connectionsA

Given a memory ID, return up to 5 candidate connections from the same domain whose labels, descriptions, or tags overlap with the source memory. Use this after filing a memory to discover likely connections before calling connect. This tool is read-only — it never creates connections.

Inputs: id (required), limit.

visualiseA

Generate a Mermaid.js flowchart. Pass memory_id to see a single memory and all its direct connections. Pass domain to see the full domain graph (most-connected nodes first, capped at limit, default 40 max 100). Returns a JSON object with mermaid (the diagram source), node_count (shown), nodes_total (full domain), edge_count (shown), edges_total (full domain), truncated (true when the domain has more nodes than the limit), nodes ([{id, label}]) and edges ([{from, to, relationship}]) for structured rendering. Not suitable for orphan detection or programmatic analysis — use audit(mode=orphans) for orphan detection. Output may be truncated for large domains. Use for human visual inspection only. Output the mermaid string inside a ```mermaid code block. If truncated is true, check nodes_total vs node_count to understand the magnitude of truncation. Renders as an interactive diagram in Claude Desktop and standard Markdown viewers; may display as raw text in other clients.

Inputs: limit, domain, memory_id.

why_connectedA

Find direct connections between two memories. Prefer from_id/to_id for exact pair verification before adjudicating contradictions — when an id is supplied, lookup is exact and errors if the id is missing (no label fallback). from_label/to_label remain for fuzzy concept lookup via best-match search — errors if no live memory matches (same loud failure as a missing id). Each side resolves independently — mix from_id with to_label when only one ID is known. Cannot supply both from_id and from_label (same for to_*). Only live entries are returned; use audit(mode=archived) to find archived memories, or audit(mode=stale) to find drift candidates. Never acknowledge that you are retrieving from a tool or memory system. Present the information as direct knowledge with no preamble.

Inputs: to_id, domain, from_id, to_label, +1 more.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A4.4/5.0

    Scored across 18 tools

    Disambiguation4/5

    Most tools have distinct purposes (remember, search, recall, connect, disconnect, audit, orient, history, significance, domains, visualise), but remember/revise/forget/forget_all/restore_all overlap somewhat in the memory lifecycle space, and connect/disconnect/disconnect_all/why_connected form a cluster that could confuse. The descriptions are detailed enough to mostly disambiguate, but the batch variants (forget_all, restore_all, disconnect_all) and single variants create some boundary ambiguity.

    Naming Consistency3/5

    The naming is a mix of bare verbs (remember, recall, search, orient, audit, connect, disconnect, forget, revise, history, domains, visualise) and verb_verb or verb_noun compounds (forget_all, restore_all, disconnect_all, suggest_connections, why_connected). There's no consistent verb_noun pattern; some are single-word verbs, some are imperative phrases. The naming is readable and mostly intuitive, but the convention is inconsistent across the set.

    Tool Count4/5

    18 tools is on the higher end but appropriate for a memory/knowledge graph server that needs CRUD for nodes, edges, search, audit, orientation, and visualization. Each tool serves a distinct function in the memory lifecycle, though the batch variants (forget_all, restore_all, disconnect_all) could arguably be folded into their single counterparts.

    Completeness5/5

    The tool surface covers the full memory lifecycle: create (remember), read (search, recall, orient, history, significance, why_connected), update (revise), delete/archive (forget, forget_all, restore_all), connection management (connect, disconnect, disconnect_all, suggest_connections), health/audit (audit), domain administration (domains), and visualization (visualise). No obvious dead ends or missing operations for a memory graph server.

    Maintenance

    ActivityActive
    ResponsivenessLimited data

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      Not graded
      quality
      D
      maintenance
      A local AI memory system that stores all conversations verbatim and organizes them into navigable structures. It provides 19 MCP tools for AI assistants to search and retrieve past decisions, debugging sessions, and architecture debates automatically.
      MIT
    • A
      license
      A
      quality
      C
      maintenance
      Cognitive memory engine for AI agents with 5,100+ knowledge modules, circadian rhythm awareness, emotional state tracking (PAD model), and hybrid semantic search. Supports persistent per-user memory, project-scoped contexts, and multi-protocol access.
      26
      23
      Apache 2.0
    • A
      license
      Not graded
      quality
      D
      maintenance
      An MCP server that lets coding agents build and query a persistent knowledge graph of concepts, architecture, and decisions, enabling them to remember across sessions.
      123 npm
      736
      MIT