Persistent long-term memory for AI agents — a standalone MCP server that gives LLMs something they fundamentally lack: the ability to remember, learn, and evolve across conversations.
Built for the Forkscout autonomous agent. Works with any MCP-compatible client (VS Code Copilot, Claude Desktop, Cursor, custom agents).
Every time you start a conversation with an LLM, it starts from zero. It doesn't know:
- What you told it yesterday
- What project you're working on
- What mistakes it made before and how it fixed them
- Who you are or what you prefer
- What decisions were already made and why
The standard "solutions" don't actually solve this:
| Approach | What it does | Why it fails |
|---|---|---|
| System prompts | Static instructions pasted at the top | Doesn't learn. Same instructions forever. Can't adapt. |
| Conversation history | Sends previous messages in context | Limited by context window. Gone after session ends. Cross-project noise. |
| RAG / Vector DB | Embeds documents, retrieves by similarity | Designed for documents, not beliefs. No confidence, no contradiction handling, no forgetting. Returns stale chunks alongside fresh ones with no way to distinguish. |
| Fine-tuning | Trains weights on data | Expensive, slow, can't un-learn mistakes, not per-user. |
| Chat memory plugins | Stores key-value pairs or summaries | Flat structure, no relationships, no confidence, no scoping, no evolution tracking. |
The core issue: none of these systems model knowledge the way intelligence actually works. They store data. They don't maintain beliefs.
forkscout-memory-mcp is a belief maintenance system disguised as an MCP server. It gives LLMs:
Every fact has a confidence score, source count, and temporal metadata:
"TypeScript is the primary language" → confidence: 0.92, sources: 5, last confirmed: 2h ago
"Port is 3211" → confidence: 0.85, sources: 2, last confirmed: 3d ago
"Uses webpack for bundling" → confidence: 0.31, sources: 1, last confirmed: 90d ago ← stale
Confidence is auto-calculated from evidence strength + recency. Facts confirmed by multiple sources rank higher. Old unconfirmed facts decay — but never below their evidence floor (a fact stated once still scores 0.30 even after a year).
Why this matters: When the LLM retrieves memory, it gets a ranked view of what it's most confident about — not a flat list of everything ever recorded.
When new information contradicts old information, the old fact isn't deleted — it's superseded:
✓ Active: "Project uses AI SDK v6" (confidence: 0.95)
⤷ Superseded: "Project uses AI SDK v5" → replaced by "Project uses AI SDK v6" (2025-12-15)
⤷ Superseded: "Project uses AI SDK v4" → replaced by "Project uses AI SDK v5" (2025-09-01)
The full correction history is preserved. The LLM can inspect how its beliefs evolved — which past mistakes it made, what corrected them, and when.
Why this matters: RAG and vector DBs keep stale chunks forever alongside correct ones. The LLM has no way to know which version is current. Here, only active facts surface in search, but the learning history is always available on demand.
Adding "port is 8080" when "port is 3211" already exists triggers a warning:
⚠️ CONTRADICTIONS DETECTED:
• "port is 3211" vs "port is 8080" — Number/version conflict
Three detection strategies:
- Negation patterns — "uses X" vs "does not use X"
- Number/version conflicts — same context, different values
- Topic overlap divergence — high word overlap but different key terms (Jaccard similarity)
Contradicted facts are automatically superseded. The LLM is warned so it can reason about the conflict.
Recall uses two search layers running in parallel:
- BM25 (lexical) — exact keyword matching, term frequency, fast
- Semantic (vector) — meaning-based matching via
Xenova/all-MiniLM-L6-v2(384-dim, quantized ONNX, runs locally, no API key needed)
Results are merged with a tunable alpha weight (default: 60% semantic, 40% BM25). This means:
- Searching "database port" also finds "3211 listen address" (semantic)
- Searching "libsimdjson" finds exact matches even with no semantic neighbors (BM25)
- Both signals reinforce each other for common queries
Embeddings are computed on-demand and cached in memory-embeddings.json. The Xenova model auto-downloads on first startup (~23MB) and is saved to TRANSFORMERS_CACHE (default: /data/.cache in Docker).
The #1 problem with shared memory across projects: search returns noise from unrelated projects.
Every entity and exchange can be tagged:
{
"tags": {
"project": "forkscout",
"scope": "universal",
"category": "debugging"
}
}Search uses smart filtering:
- Searching with
project: "forkscout"returns:- ✅ Items tagged
project: "forkscout"(project-specific) - ✅ Items tagged
scope: "universal"(cross-project knowledge) - ✅ Items with no tags (backwards compatible, legacy data)
- ❌ Items tagged
project: "other-project"(filtered out)
- ✅ Items tagged
Why this matters: An agent that works on forkscout on Monday and future-gain on Tuesday needs its TypeScript debugging patterns (universal) but not future-gain's database schema (project-specific). The tag filter does this automatically without requiring the LLM to manually filter results.
Entities are connected by typed, weighted relationships:
forkscout-memory-mcp ──uses──▶ TypeScript (weight: 0.95, 5x confirmed)
forkscout-memory-mcp ──uses──▶ Bun (weight: 0.80, 3x confirmed)
forkscout-memory-mcp ──part-of──▶ Forkscout (weight: 0.90, 4x confirmed)
30 entity types spanning cognition (goal, task, plan, hypothesis, decision), experience (event, outcome, failure, success), and environment (resource, state, signal).
120+ relation types organized across 15 categories including structural, intentional, causal, temporal, and learning dimensions. Relations are reinforced by repeated evidence — the more times a connection is independently stated, the higher its weight.
The agent maintains a self-entity where it records observations about its own behavior:
Forkscout Agent (agent-self):
• [95%] Prefer spawn_agents for parallel research tasks
• [88%] Always check memory before starting work
• [72%] When debugging, reproduce the error first before reading code
These self-observations accumulate across sessions. The agent literally learns how to be a better agent — what debugging strategies work, what communication patterns the user prefers, what mistakes to avoid.
Conversation exchanges are stored and searchable:
observe("How do I fix port conflict?", "Check if port 3211 is in use with lsof -i :3211...")
→ importance auto-calculated from message length + keyword density
→ deduplication: similar exchanges (>0.85 similarity) are merged, not duplicated
→ hot tier: last 500 exchanges in full
→ archive tier: older exchanges indexed by embedding only
Exchanges can be tagged by project for scoped recall. On search, both lexical and semantic matching run against the exchange history.
In-session working memory (recent actions, decisions, errors) is persisted across server restarts:
"workingMemorySessions": {
"session_abc": [
{ "content": "Started migrating schema to v7", "event_type": "action", "timestamp": 1708600000000 },
{ "content": "Found contradiction in port facts", "event_type": "observation" }
]
}The last 25 events per session are kept. On restart, the agent can recall exactly where it left off mid-task.
Tasks survive server restarts:
⚡ Running: "Implement multi-dimensional tagging" (task_abc123) — 45min, P80
✓ Completed: "Fix planner duplicate processing" — 12min
✗ Aborted: "Migrate to Rust" — Deprioritized
Auto-expiry after 2 hours prevents zombie tasks. Similar task detection prevents duplicates.
┌─────────────────────────────────────────────────────────┐
│ Traditional RAG │
│ │
│ Documents → Chunker → Embeddings → Vector DB → Search │
│ │
│ ✗ No confidence ✗ No contradiction handling │
│ ✗ No belief evolution ✗ No project scoping │
│ ✗ Stale = Fresh ✗ No relationships │
└─────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────┐
│ forkscout-memory-mcp │
│ │
│ Facts → Confidence + Sources → Contradiction Check → │
│ Knowledge Graph (entities + relations) → │
│ Tag-filtered Hybrid Search (BM25 + Semantic) → │
│ Ranked results (confidence × recency × access) → │
│ Supersession chains (belief evolution history) │
│ │
│ ✓ Confidence scoring ✓ Automatic contradiction │
│ ✓ Non-destructive ✓ Multi-project isolation │
│ ✓ Self-identity ✓ Task tracking │
│ ✓ Relationship graph ✓ Two-tier consolidation │
│ ✓ Hybrid search ✓ Working memory persistence │
│ ✓ Exchange memory ✓ Interactive visualizer │
└─────────────────────────────────────────────────────────┘
bun install
bun --watch src/server.ts # watch mode, auto-reload on changesNote: Bun is required. The Xenova/all-MiniLM-L6-v2 model (~23MB) auto-downloads on first start into
TRANSFORMERS_CACHE. Subsequent starts are instant.
bun run src/server.ts # Bun runs TypeScript natively — no build stepdocker build -t forkscout-memory-mcp .
docker run -d -p 3211:3211 -v memory-data:/data forkscout-memory-mcp
# or with docker compose
docker compose up -ddocker pull ghcr.io/martianacademy/forkscout-memory-mcp:latest
docker run -d -p 3211:3211 -v memory-data:/data ghcr.io/martianacademy/forkscout-memory-mcpAdd to .vscode/mcp.json:
{
"servers": {
"forkscout-memory": {
"type": "http",
"url": "http://localhost:3211/mcp"
}
}
}| Variable | Default | Description |
|---|---|---|
MEMORY_PORT |
3211 |
HTTP server port |
MEMORY_HOST |
0.0.0.0 |
Bind address |
MEMORY_STORAGE |
.forkscout (local) / /data (Docker) |
Directory for memory.json and memory-embeddings.json |
MEMORY_OWNER |
Admin |
Owner name used in the self-entity |
SELF_ENTITY_NAME |
Forkscout Agent |
Name of the agent's self-identity entity |
CONSOLIDATION_INTERVAL_MS |
86400000 (24h) |
Full consolidation interval |
VERIFY_FILES |
true |
Verify file entities against filesystem |
TRANSFORMERS_CACHE |
/data/.cache (Docker) |
Where Xenova model weights are cached |
CORS_ORIGIN |
* |
CORS allowed origin(s) |
| Method | Path | Description |
|---|---|---|
GET |
/health |
Health check — entity/relation/exchange/task counts |
GET |
/ |
Same as /health |
GET |
/api/memory |
Raw memory JSON (full MemoryData dump — use for debugging) |
GET |
/visualizer |
Interactive knowledge graph visualizer (infinite canvas) |
POST |
/mcp |
MCP JSON-RPC endpoint (Streamable HTTP with SSE responses) |
Store facts on a named entity. New facts are merged. Contradictions trigger warnings and auto-supersede the old fact.
| Param | Type | Required | Description |
|---|---|---|---|
name |
string | ✓ | Entity name (exact match merges, new name creates) |
type |
enum | ✓ | Entity type — see Entity Types below |
facts |
string[] | ✓ | Facts to add / merge. Pass [] + supersede to remove a fact |
supersede |
string | — | Substring of the fact to replace with facts[0] |
tags |
object | — | Scoped tags e.g. { "project": "forkscout", "scope": "universal" } |
{
"name": "forkscout-memory-mcp",
"type": "service",
"facts": ["HTTP port is 3211", "runs on Bun 1.3.9"],
"tags": { "project": "forkscout" }
}Five retrieval modes covering all memory layers.
| Param | Type | Required | Description |
|---|---|---|---|
mode |
enum | — | search (default) · entity · history · relations · exchanges |
query |
string | * | Search text (required for search and exchanges modes) |
name |
string | * | Entity name (required for entity and history modes) |
limit |
number | — | Max results (default: 5) |
project |
string | — | Project tag for scoped filtering |
include_history |
bool | — | Include superseded facts in entity mode (default: false) |
Modes:
search— BM25 + semantic hybrid search across entities + exchangesentity— get one entity by exact name;include_history: trueshows supersession chainhistory— belief evolution: what was corrected and when (requiresname)relations— all knowledge graph edges; optionalnamerestricts to one entityexchanges— search conversation history by keyword
Record a significant conversation into long-term memory AND push to working memory.
| Param | Type | Required | Description |
|---|---|---|---|
user |
string | ✓ | User message |
assistant |
string | ✓ | Assistant response |
sessionId |
string | ✓ | Session identifier |
importance |
number | — | Significance 0–1 (auto-calculated if omitted) |
project |
string | — | Project tag for scoped recall |
Importance is auto-calculated from message length and keyword density if omitted. Deduplication runs at 0.85 similarity threshold — duplicates are merged, not appended.
Only record exchanges with non-trivial decisions, root causes, or earned insights. Skip routine tool output.
Create a typed edge between two entities.
| Param | Type | Required | Description |
|---|---|---|---|
from |
string | ✓ | Source entity name |
to |
string | ✓ | Target entity name |
type |
enum | ✓ | Relation type — see Relation Types below |
Duplicate edges auto-merge and gain confidence weight. Missing entities are auto-created as type other.
Rule: Run
recall(mode="search")on both names first to confirm they exist and avoid creating duplicate entities.
In-RAM, session-scoped working memory. Track what you are doing right now: actions taken, decisions made, errors hit.
| Param | Type | Required | Description |
|---|---|---|---|
action |
enum | ✓ | push · get · clear |
session_id |
string | ✓ | Session identifier |
content |
string | * | [push] What happened / decided / failed |
event_type |
enum | — | [push] action · observation · decision · error · fact |
limit |
number | — | [get] Recent events to return (default: 10) |
Keeps the last 25 events per session. Call at session start with action: "get" to recall where you left off. Working memory is persisted to memory.json across server restarts.
Tasks survive server restarts and provide chronological tracking.
| Param | Type | Required | Description |
|---|---|---|---|
action |
enum | ✓ | start · done · abort · list |
title |
string | * | [start] Short label (3–7 words) |
goal |
string | * | [start] What you are trying to accomplish |
successCondition |
string | — | [start] How to know when done |
priority |
number | — | [start] Priority 0–1 |
importance |
number | — | [start] Long-term importance 0–1 |
taskId |
string | * | [done/abort] Task ID returned by start |
result |
string | — | [done] Outcome summary |
reason |
string | * | [abort] Why the task was stopped |
start: detects similar existing tasks to avoid duplicates. ReturnstaskId.done: marks complete + auto-saves a success record for future recall.abort: stops + saves a failure post-mortem for future learning.list: shows all active and paused tasks with elapsed durations.
Auto-expiry after 2 hours prevents zombie tasks.
Get statistics and identify stale or volatile facts. Run at session startup.
| Param | Type | Required | Description |
|---|---|---|---|
view |
enum | — | stats · stale · gaps · all (default: stats) |
limit |
number | — | Max results for stale/gaps (default: 20) |
types |
array | — | [stale] Filter by entity type |
Views:
stats— entity/relation/exchange counts and type breakdownstale— entities not accessed recently (candidates for verification or pruning)gaps— volatile facts (versions, ports, paths, env vars) that may be outdatedall— combined report — recommended at session startup
Refresh confidence scores, prune stale facts, remove empty entities, clean orphan relations, archive old data, detect near-duplicates.
| Param | Type | Required | Description |
|---|---|---|---|
archiveDays |
number | — | Min age before superseded facts are archived (default: 180) |
maxStaleDays |
number | — | Max age for low-confidence facts before pruning (default: 60) |
minConfidence |
number | — | Min confidence to keep active fact (default: 0.15) |
Run periodically or when memory grows large. Superseded (historical) facts are only archived after archiveDays to preserve learning history.
Supersede a fact from an entity by substring match.
| Param | Type | Required | Description |
|---|---|---|---|
name |
string | ✓ | Entity name |
factSubstring |
string | ✓ | Substring of the fact to supersede |
The fact is superseded (not hard-deleted) — history is preserved. Use recall(mode="entity", include_history: true) to see superseded facts.
Every fact's confidence is auto-calculated:
confidence = sourceBase + recencyBonus
sourceBase (permanent floor):
1 source → 0.30
2 sources → 0.42
3 sources → 0.50
5+ sources → 0.60
recencyBonus (decays over 90 days):
just confirmed → +0.30
30 days ago → +0.21
90 days ago → +0.11
180 days ago → +0.04
Key design decision: Long-term knowledge never decays to zero. A fact stated once still scores 0.30 after years. Only the recency bonus decays — the evidence floor is permanent. This prevents the common RAG problem where valid but old information gets garbage-collected.
Protected entity types are never pruned regardless of confidence: agent-self, person, project, preference, decision, organization, skill, constraint.
Every search call runs two engines in parallel, then merges results:
Query: "database port configuration"
│
┌────┴─────────────┐
│ │
BM25 Semantic
(keyword) (vector)
│ │
Finds: Finds:
"database" "listen address 3211"
"port" "server bind config"
"configuration" "networking setup"
│ │
└────┬─────────────┘
│
Merge (alpha=0.6)
→ 60% semantic score + 40% BM25 score
│
Rerank by confidence × recency
│
Top-K results
| BM25 alone | Semantic alone |
|---|---|
| Misses synonyms and paraphrases | Misses exact version strings |
| "3211 port" ≠ "listen address" | "libsimdjson" has no semantic neighbors |
| Fast, no model needed | Requires embedding computation |
Together they cover both ends: exact technical strings AND conceptual meaning.
Embeddings are computed lazily on first access and cached in memory-embeddings.json. Cache is invalidated when entities change.
- Confidence score refresh on all active facts
- Confidence refresh across all entities
- Archive superseded facts older than 180 days
- Prune stale low-confidence active facts on non-protected entities (>60 days, <0.30 confidence)
- Remove empty entities (no active facts)
- Clean orphan relations (referencing deleted entities)
- Detect near-duplicate entities (Jaccard similarity >0.70 on same type)
- Archive old exchanges from hot tier (500 cap) to archive tier
- Verify file entities against filesystem (optional)
Open http://localhost:3211/visualizer in a browser to explore the knowledge graph interactively.
- Infinite canvas — pan freely in any direction, no bounds. Dot-grid SVG background extends infinitely.
- Zoom-proof scaling — nodes, labels, and edges maintain minimum on-screen size at any zoom level:
nodeRadius = max(base / zoom^1.25, 9px / zoom) → always ≥9px on screen fontSize = max(base / zoom^1.15, 10px / zoom) → always ≥10px on screen edgeWidth = max(base / zoom^0.95, 0.8px / zoom) → always visible - Radial layout by degree — entities with the most relations are placed at the outer ring; isolated nodes cluster near center:
pct = 1 - rank / (N-1) // rank 0 (most connected) → pct=1 → outermost r = maxRadius × (0.12 + pct × 0.88) - Node dragging — drag any node to a custom position, saved to localStorage (key:
v4) and restored on next visit. - Fullscreen mode — expand to full viewport, borderless infinite canvas.
- Smart limits — displays up to 300 nodes and 600 edges without performance degradation.
| Interaction | Action |
|---|---|
| Scroll | Zoom in / out |
| Drag canvas (empty) | Pan infinitely in any direction |
| Drag node | Reposition node (saved to localStorage) |
| Double-click canvas | Fit all nodes to view |
| Double-click node | Highlight node + its direct relations |
| Click entity in list | Zoom to and highlight that node |
| Expand button (↗) | Fullscreen infinite canvas mode |
| Color | Entity category |
|---|---|
| Blue | Service / Technology |
| Green | Person / Organization |
| Purple | Project / Goal / Plan |
| Orange | Task / Decision / Constraint |
| Red | Failure / Problem |
| Teal | Concept / Skill / Preference |
| Gray | File / Other |
| Gold border | Agent-self entity |
memory.json — MemoryData v7 (structured facts with confidence, versioning, multi-dimensional tags, and working memory sessions):
{
"version": 7,
"entities": [
{
"name": "forkscout-memory-mcp",
"type": "service",
"facts": [
{
"content": "TypeScript MCP server with JSON persistence",
"confidence": 0.92,
"sources": 3,
"firstSeen": 1708000000000,
"lastConfirmed": 1708600000000,
"status": "active"
},
{
"content": "Uses MemoryData v5 schema",
"confidence": 0.65,
"sources": 1,
"firstSeen": 1707000000000,
"lastConfirmed": 1707000000000,
"status": "superseded",
"supersededBy": "Schema v7 with multi-dimensional tags",
"supersededAt": 1708600000000
}
],
"lastSeen": 1708600000000,
"accessCount": 42,
"tags": { "project": "forkscout", "scope": "project" }
}
],
"relations": [
{
"from": "forkscout-memory-mcp",
"to": "TypeScript",
"type": "uses",
"weight": 0.95,
"evidenceCount": 5,
"lastValidated": 1708600000000,
"createdAt": 1707000000000
}
],
"exchanges": [
{
"id": "ex_1708600000000_a1b2",
"user": "How does contradiction detection work?",
"assistant": "Three strategies: negation patterns, number/version conflicts, and topic overlap divergence...",
"timestamp": 1708600000000,
"sessionId": "session_abc",
"importance": 0.8,
"tags": { "project": "forkscout" }
}
],
"activeTasks": [
{
"id": "task_1708600000000_x1y2",
"title": "Implement tagging system",
"goal": "Add multi-dimensional tags to entities and exchanges",
"status": "completed",
"startedAt": 1708600000000,
"lastStepAt": 1708603600000,
"priority": 0.8,
"importance": 0.9
}
],
"workingMemorySessions": {
"session_abc": [
{
"content": "Started migrating schema to v7",
"event_type": "action",
"timestamp": 1708600000000
},
{
"content": "Found contradiction in port facts — resolved to 3211",
"event_type": "observation",
"timestamp": 1708600100000
}
]
}
}The server auto-migrates on startup:
- v4 → v7: Plain string facts → structured facts with confidence, versioning, and tags
- v5 → v7: Add fact status (
active/superseded), clean[SUPERSEDED]text prefixes, add tags - v6 → v7: Add
tagsto entities and exchanges, addworkingMemorySessions
Migration is non-destructive. All data is preserved.
Core: person · project · technology · preference · concept · file · service · organization · agent-self · other
Cognition: goal · task · plan · skill · problem · hypothesis · decision · constraint
Experience: event · episode · outcome · failure · success
Environment: resource · state · signal
Structural:
uses · owns · works-on · prefers · knows · depends-on · created · related-to · part-of · manages · dislikes · learned · improved
Intentional:
pursues · plans · executes · blocks · requires · prioritizes
Temporal/Causal:
causes · results-in · leads-to · precedes · follows
Learning:
observed · predicted · confirmed · contradicted · generalizes · derived-from
Performance:
succeeded-at · failed-at · improved-by · degraded-by
Memory:
remembers · forgets · updates · replaces
Communication:
discusses · mentions · references · quotes · summarizes · clarifies · asks-about · answers
Social:
collaborates-with · reports-to · reviews · approves · delegates-to · advises · teaches · learns-from
Technical:
implements · extends · overrides · calls · imports · exports · configures · deploys · monitors · tests · documents · generates · parses · validates · transforms
State/Lifecycle:
initializes · activates · deactivates · pauses · resumes · completes · fails · retries · cancels · schedules
Spatial/Organizational:
contains · located-in · belongs-to · groups · categorizes · indexes · archives
Comparative:
similar-to · different-from · better-than · worse-than · equivalent-to · alternative-to · complement-to
Causal-Extended:
enables · prevents · triggers · mitigates · amplifies · constrains · supports · contradicts-with
Epistemic:
believes · doubts · assumes · hypothesizes · verifies · refutes · questions · trusts
Goal/Motivation:
motivates · discourages · aligns-with · conflicts-with · depends-on-goal
MCP over Streamable HTTP (stateless mode):
POST /mcp— JSON-RPC 2.0 request- Response: SSE-wrapped (
event: message\ndata: {json}\n\n) - Notifications (no
id): HTTP202 Accepted - Methods:
initialize,tools/list,tools/call
No persistent connections. No WebSocket. One request = one response. Trivially deployable behind any reverse proxy or load balancer.
forkscout-memory-mcp/
├── src/
│ ├── server.ts # HTTP server, MCP transport, consolidation timer, graceful shutdown
│ ├── store.ts # MemoryStore — CRUD, search, contradiction detection, consolidation, tag filtering
│ ├── tasks.ts # TaskManager — active task tracking, auto-expiry, similarity detection
│ ├── tools.ts # 9 MCP tool registrations with Zod schemas
│ ├── types.ts # Type definitions (MemoryData v7, Entity, Fact, Relation, Exchange, etc.)
│ ├── embeddings.ts # Xenova/all-MiniLM-L6-v2 embedding + BM25 hybrid search engine
│ ├── working-memory.ts # Session-scoped working memory (push/get/clear, last 25 events)
│ └── visualizer.ts # Infinite canvas knowledge graph visualizer (SVG, radial layout)
├── Dockerfile # Single-stage: oven/bun:1 (Debian) — runs TypeScript natively, no build step
├── docker-compose.yml # Volume: memory-data → /data, network: forkscout_default
├── package.json
├── tsconfig.json
└── .dockerignore
Docker base image: Uses
oven/bun:1(Debian), not Alpine. Alpine was dropped due to musl libc incompatibilities with the Xenova ONNX runtime.
Vector databases (Pinecone, Chroma, Weaviate) are excellent for document retrieval. They are the wrong tool for agent memory.
| Feature | Vector DB | forkscout-memory-mcp |
|---|---|---|
| Storage unit | Document chunks | Structured facts with metadata |
| Confidence | None — all results are equal | 0–1 score per fact, auto-calculated |
| Contradiction handling | None — old and new coexist | Automatic detection + supersession |
| Belief evolution | Not possible | Full history with supersession chains |
| Cross-project isolation | Namespace-only | Smart scoping (project + universal + untagged) |
| Relationship modeling | None | Weighted, typed knowledge graph (120+ types) |
| Self-identity | Not applicable | Built-in agent self-entity |
| Working memory | Not applicable | Session-scoped, persisted across restarts |
| Exchange memory | Not applicable | Full conversation recall with hybrid search |
| Forgetting | Manual deletion | Confidence decay + consolidation |
| Visualizer | External tooling needed | Built-in infinite canvas at /visualizer |
| Search | Vector only | Hybrid BM25 + semantic (local, no API needed) |
| Setup | Managed service or heavy infra | Single JSON file, zero external dependencies |
| Cost | Per-query pricing or hosting | Free, runs locally |
The right mental model: a vector DB is a library (stores documents for lookup). forkscout-memory-mcp is a brain (maintains beliefs, learns from corrections, tracks confidence, remembers conversations, and visualizes the full knowledge graph in a browser).
The basic unit of relational knowledge is a triple: Subject → Predicate → Object
forkscout-memory-mcp → uses → TypeScript
In this project: { from: "forkscout-memory-mcp", type: "uses", to: "TypeScript" }
RDF is the formal standard for triples using URIs and shared vocabularies. This project is triple-like but not RDF — no SPARQL, no ontology layer, no URI requirement. Intentionally lightweight for fast agent workflows.
Graph DBs (Neo4j, JanusGraph) store nodes and edges optimized for traversal queries at scale. This project uses a graph-shaped model stored in JSON — not a high-scale graph engine, but trivially portable and zero-dependency.
forkscout-memory-mcp is a hybrid agent memory system layered on top of a graph:
- Graph layer — entities + typed relations (120+ types)
- Belief layer — facts with confidence, recency, and source counts
- Revision layer — old beliefs become superseded instead of deleted
- Conversation layer — important exchanges stored + searchable via hybrid search
- Executive layer — active tasks survive across sessions
- Working layer — short-term session context persisted across restarts
| Model | Best unit of knowledge | Best for | Missing vs this project |
|---|---|---|---|
| Semantic triples | Subject → Predicate → Object |
Clean relational statements | No confidence, no history, no task/exchange memory |
| RDF | Standardized triples with URIs | Interoperability, formal semantics | Too rigid/heavy for fast agent memory workflows |
| Graph DB | Nodes + edges + traversal queries | Large-scale graph analytics | Doesn't model belief revision, confidence, or exchanges |
| forkscout-memory-mcp | Graph + facts + exchanges + tasks | Persistent agent memory + learning | Not formal RDF, not a high-scale graph engine |
In one line: this is not just an SPO graph — it is an SPO graph plus confidence, recency, contradiction handling, correction history, conversation memory, working memory, task tracking, and a built-in visualizer.
MIT