Content
<p align="center">
<img src="assets/images/anchormind_logo.png" width="400" alt="AnchorMind Logo">
</p>
<p align="center">
<a href="https://github.com/JinHo-von-Choi/anchormind/releases">
<img src="https://img.shields.io/github/v/release/JinHo-von-Choi/anchormind?style=flat&label=release&color=4c8bf5" alt="GitHub Release" />
</a>
<a href="https://github.com/JinHo-von-Choi/anchormind/stargazers">
<img src="https://img.shields.io/github/stars/JinHo-von-Choi/anchormind?style=flat&color=f5c542" alt="GitHub Stars" />
</a>
<a href="LICENSE">
<img src="https://img.shields.io/badge/license-Apache%202.0-blue?style=flat" alt="License" />
</a>
<a href="https://lobehub.com/mcp/jinho-von-choi-memento-mcp">
<img src="https://lobehub.com/badge/mcp/jinho-von-choi-memento-mcp" alt="MCP Badge" />
</a>
</p>
<p align="center">
<a href="README.en.md">📖 English Documentation</a>
</p>
# Tool List
> AI에게 기억을 줍니다. 그리고 그 기억을 발판으로 성장하게 합니다.
Imagine a new employee whose memory resets every morning. They forget what you taught them yesterday, the problems they solved last week, and even their personal preferences. AnchorMind gives this new employee memories.
AnchorMind is an MCP (Model Context Protocol) based agent long-term memory server. It retains important facts, decisions, error patterns, and procedures even after a session ends and restores them in the next session.
> This project started as memento-mcp. I still think it's a fitting name for a project that deals with memory, but there are many projects with similar names, so I changed it to AnchorMind. It means to anchor and fix memories that are worth keeping in the flow of conversation, and it also matches the concept of anchor fragments in this system.
It's not just a library of memories. As feedback accumulates, connections become stronger, experiences are repeated, patterns are abstracted, and stories are created. It aims for an AI that grows from experience, not just remembers.
> [!TIP]
> If you're not comfortable with manual installation and configuration, you can use AI assistants like Claude Code, Cursor, or Codex to do it for you.
>
> > "Install the AnchorMind repository in my environment, read `docs/INSTALL.md` and `SKILL.md`, and apply the recommended settings."
>
> The AI will guide you through dependency installation, `.env` configuration, MCP registration, and health checks. For detailed delegation procedures, refer to [`docs/INSTALL.md`](docs/INSTALL.md#ai%EC%98%98%EA%B2%8C-%EB%A7%88%EA%B8%B0%EA%B8%B0).
## 30-second Experience
Here's a flow where you make an AI remember something and recall it in the next session:
```
[Session 1]
User: "Our project uses PostgreSQL 15, and our tests are run with Vitest"
→ AI calls remember → 2 fragments saved
[Session 2 — next day]
→ AI calls context → "Using PostgreSQL 15", "Vitest tests" automatically restored
User: "How do I run the tests again?"
→ AI calls recall → returns "Run Vitest" fragment
→ AI: "This project uses Vitest. Run with `npx vitest`."
```
You don't need to repeat the same explanations every session.
## Installation
Required: Node.js 20+, PostgreSQL (with pgvector extension)
```bash
cp .env.example.minimal .env
# edit .env values and reflect them in your shell
export $(grep -v '^#' .env | grep '=' | xargs)
npm install
npm run migrate
node server.js
```
To use local embeddings without OpenAI API, add `EMBEDDING_PROVIDER=transformers` to `.env`. It automatically downloads the `Xenova/multilingual-e5-small` model at startup. However, if you're already using OpenAI embeddings, make sure to migrate to a new DB to avoid dimension mismatch.
After the server starts, verify its operation with [First Memory Flow](docs/getting-started/first-memory-flow.md).
For other platform settings, refer to the [Compatible Platforms](#compatible-platforms) table.
### Update
```bash
cd ~/memento-mcp
git pull origin main
npm install
npm run migrate
# restart service (depending on your environment)
```
- `npm run migrate` automatically uses the DB settings from `.env`. No need to manually specify `DATABASE_URL`.
- pgvector schema is automatically detected. `PGVECTOR_SCHEMA` setting is usually unnecessary.
### Claude Code Integration
Register with `claude mcp add` CLI:
```bash
claude mcp add memento http://localhost:57332/mcp \
--transport http \
--scope user \
--header "Authorization: Bearer YOUR_ACCESS_KEY"
```
Registration is stored in `~/.claude.json`. Verify:
```bash
claude mcp list
# memento: http://localhost:57332/mcp (HTTP) - ✓ Connected
```
For project-wide sharing, add it to `.mcp.json` in the repository root. For detailed settings, refer to [Claude Code Configuration](docs/getting-started/claude-code.md).
### Codex Desktop Integration
Some MCP clients, like Codex Desktop, use deferred/lazy tool discovery. If `recall` doesn't appear, search with a broader query and a limit of 20 or more.
### Supported Environments
| Environment | Recommendation | Getting Started |
| --- | --- | --- |
| Linux / macOS | Recommended | [Quick Start](docs/getting-started/quickstart.md) |
| Windows + WSL2 | Most Recommended | [Windows WSL2 Setup](docs/getting-started/windows-wsl2.md) |
| Windows + PowerShell | Limited Support | [Windows PowerShell Setup](docs/getting-started/windows-powershell.md) |
## Compatible Platforms
AnchorMind is a standard MCP (Model Context Protocol) server. It can be used with any AI platform that supports MCP.
| Platform | Settings Location | Connection Method |
| --- | --- | --- |
| Claude Code | `claude mcp add` CLI (`~/.claude.json`) or `.mcp.json` | Streamable HTTP |
| Claude Desktop | claude_desktop_config.json | Streamable HTTP |
| Claude.ai Web | Settings > Integrations | OAuth (RFC 7591) |
| Cursor | .cursor/mcp.json | Streamable HTTP |
| Windsurf | ~/.codeium/windsurf/mcp_config.json | Streamable HTTP |
| GitHub Copilot | VS Code MCP Marketplace | Streamable HTTP |
| Codex CLI | ~/.codex/config.toml | Streamable HTTP |
| ChatGPT Desktop | Developer Mode > Apps | OAuth (RFC 7591) |
| Continue | config.json | Streamable HTTP |
Common settings: server URL `http://localhost:57332/mcp`, Authorization header with `Bearer YOUR_ACCESS_KEY`.
Claude.ai Web / ChatGPT integration uses OAuth. Enter the issued API key (`mmcp_xxx`) as `client_id` for dynamic client registration (RFC 7591) without additional steps. Trusted domains (claude.ai, chatgpt.com) have automatic redirect URI approval.
For platform-specific settings, refer to [Integration Guides](docs/getting-started/).
## 7 Fragment Types
| Type | Description | Use Case |
| --- | --- | --- |
| `fact` | Fact | Objective information like settings, paths, and versions |
| `decision` | Decision | Architecture choices, technology stack decisions, and reasoning |
| `error` | Error | Occurred errors, causes, and solutions |
| `preference` | Preference | User styles, coding rules, and work methods |
| `procedure` | Procedure | Repeatable steps like deployment, build, and testing |
| `relation` | Relation | Entity connections, dependencies, and ownership relationships |
| `episode` | Episode | Narrative memories with context (1000 characters, others 300 characters) |
## Core Features
| Feature | Description |
| --- | --- |
| `remember` | Stores important information as atomic fragments. With `MEMENTO_REMEMBER_ATOMIC=true`, quota check and INSERT are atomicized in a single transaction. |
| `recall` | Returns only necessary memories with keyword + semantic 3-layer search. `SearchScope` applies scope matching across L1~L3 layers. |
| `context` | Automatically restores core context at session start |
| Auto-整理 | Duplicate merging, contradiction detection, importance attenuation, and TTL-based forgetting |
| Storage adapter layer | `lib/storage/` has a storage abstraction layer. `getStorage()` factory returns `PgVectorStore` (default) or `SqliteVecStore` (stub, not implemented) based on `MEMENTO_STORAGE` ENV. |
| Link re-integration | `tool_feedback` feedback reflects on fragment_links' weight/confidence in real-time (ReconsolidationEngine). Contradictory links are automatically quarantined. |
| Spreading activation | When `recall` is called with `contextText`, it pre-boosts related fragments' activation_score for high-context relevance (SpreadingActivation). |
| Episode continuity | Automatically generates `preceded_by` edges between episode fragments for experience flow graph preservation (EpisodeContinuityService). |
| Management console | Memory exploration, knowledge graph, statistics dashboard, API key group/state filter, and daily-limit inline editing |
| OAuth integration | RFC 7591 Dynamic Client Registration, Claude.ai / ChatGPT Web integration support |
| Workspace isolation | Memories are separated by project, job, or client within the same key. Automatically tagged with `api_keys.default_workspace` and filtered during search. |
| Batch processing | `batch_remember` uses multi-row single INSERT (256KB or 500-row chunk) + async queue worker (BatchRememberWorker) for non-blocking execution. With `async: true`, it guarantees at-least-once processing with ack, retry (max 3), dead-letter, and startup recovery (RPOPLPUSH reliable queue). `batch_status(jobId)` tool for status query. Always returns standard single JSON-RPC response (`stream` deprecated). `reflect` delegates 5 categories in a single batch call. EmbeddingWorker processes queue bundles with generateBatchEmbeddings and multi-row UPDATE. |
| Consistency Gate | Tracks morpheme index completion with `fragments.morpheme_indexed` column. Incomplete fragments are automatically excluded from L3 morpheme search paths. |
| Mode preset | `recall-only` / `write-only` / `onboarding` / `audit` JSON preset. Limits tool exposure range with `X-Memento-Mode` header or `api_keys.default_mode`. |
| Affective tagging | `fragments.affect` column (neutral / frustration / confidence / surprise / doubt / satisfaction). Filtering with emotional labels during remember/recall. |
| Local embedding | Uses `@huggingface/transformers` pipeline-based embedding with `EMBEDDING_PROVIDER=transformers` (384d default, `Xenova/multilingual-e5-small`). |
| Migration lint | Automatically checks new migration file number conflicts and convention violations with `npm run lint:migrations` before commit. |
For the full MCP tool list, refer to [SKILL.md](SKILL.md).
## CLI
You can directly manipulate a remote MCP server without a local node. Specify with `--remote URL --key KEY` global flags or `MEMENTO_CLI_REMOTE` / `MEMENTO_CLI_KEY` environment variables.
```bash
# Recall on a remote server (using environment variables)
MEMENTO_CLI_REMOTE=https://example.com/mcp MEMENTO_CLI_KEY=mmcp_xxx memento-mcp recall "query"
# Recall on a remote server (using flags)
memento-mcp recall "query" --remote https://example.com/mcp --key mmcp_xxx
# Table output, 5 results
memento-mcp recall "query" --format table --limit 5
# Prevent duplicate storage with idempotency key
memento-mcp remember "content" --topic project_name --idempotency-key k1
```
Choose output format with `--format table|json|csv`, and 14 subcommands support `--help`/`-h`. Detailed flags are in [docs/cli.md](docs/cli.md).
## API Response Meta
`recall` / `context` responses include the `_meta: { searchEventId, hints, suggestion, serverTime }` field. `serverTime` exposes the server's current time in every response to prevent time anchoring during LLM client training.
```json
{
"fragments": [...],
"_meta": {
"searchEventId": "evt-abc123",
"hints": { "signal": "consider_context" },
"suggestion": { "code": "large_limit_no_budget", "message": "..." },
"serverTime": {
"iso" : "2026-05-15T06:32:11.000Z",
"epoch_ms" : 1747291931000,
"display_kst": "2026-05-15 (Thu) 15:32",
"timezone" : "Asia/Seoul"
}
}
}
```
`remember` / `link` / `forget` / `amend` can be executed without side effects by setting the `dryRun: true` parameter. All responses include the `X-RateLimit-Limit` / `X-RateLimit-Remaining` / `X-RateLimit-Resource` headers, which can be omitted when using a master key or setting `limit=null`. `recall` allows limiting return fields to a whitelist of 17 fields using the `fields` array. `remember` / `batchRemember` prevent duplicate storage within the same `idempotencyKey` range (up to 128 characters). `remember` / `batchRemember` items and `amend` `content` are rejected with a JSON-RPC -32602 error if exceeding 4000 characters. This is in addition to the fragment-type-specific truncation (1000 characters / 300 characters) applied at the receiving gate; `batchRemember` only fails for excess items, while the rest of the batch proceeds.
## Security
- RBAC default-deny: Tool names not in the `TOOL_PERMISSIONS` map are immediately denied, regardless of permissions.
- Tenant isolation: `forget` / `amend` / `link` / `fragment_history` use SQL-level `key_id` conditions to prevent access to fragments from other tenants. "None" and "no permission" are treated as the same message to prevent exposure of existence.
- `injectSessionContext`: Re-injects internal fields like `_keyId` and `_permissions` sent by the client as server authentication results to prevent session context tampering.
- Admin rate limit: IP-based rate limiting for `/auth`, `/keys` POST, and `/import` POST.
- OpenAPI: `GET /openapi.json` endpoint (with `ENABLE_OPENAPI=true`). Master keys return the full path, while API keys return permission filter specifications.
## Symbolic Verification Layer
Optional explainability, advisory link integrity, polarity conflict detection, and soft gating of policy rules. 9 core modules + 5 rule files. All flags are disabled by default.
## Smart Recall
- ProactiveRecall: Automatic linking of similar fragments based on keyword overlap when `remember()` is called.
- CaseRewardBackprop: Automatic backpropagation of importance for evidence fragments during case verification events.
- SearchParamAdaptor: Automatic optimization of search thresholds based on usage patterns.
- CBR (Case-Based Reasoning): Searching for similar cases with `recall(caseMode=true)` to reuse past solution patterns.
- `depth` filter: Controlling search depth by Planner/Executor roles (`"high-level"` / `"detail"` / `"tool-level"`).
- `recall` response `key_id`: Includes the owning tenant identifier in returned fragments.
- Reconsolidation: Real-time updates of `fragment_links` weights/confidence based on `tool_feedback` (with `ENABLE_RECONSOLIDATION=true`).
- Spreading Activation: Pre-activation of related fragments using ema_activation when passing `recall(contextText=...)` (with `ENABLE_SPREADING_ACTIVATION=true`).
`fragments.id` is in the format of `frag-{16-character hex}`. It is not a UUID, so exercise caution when generating or parsing IDs externally.
The `/metrics` endpoint exposes metrics in Prometheus-compatible format. Collection and visualization are freely configurable by the user.
## Memory vs. Rules
AnchorMind-injected memory fragments have lower priority than system prompts. Factual memories like "We use PostgreSQL 15" work well, but behavioral rules like "Always use the Given-When-Then pattern when writing tests" may be ignored if conflicting with system prompts.
Behavioral rules are recommended to be set in higher-priority channels like CLAUDE.md, AGENTS.md, hooks, and skills.
## Benchmark
[LongMemEval-S](https://arxiv.org/abs/2407.15460) performance with 500 questions:
| Metric | Score | Comparison |
|--------|-------|------------|
| Search recall@5 | 88.3% | +8~18pp compared to LongMemEval paper Stella 1.5B |
| QA accuracy | 45.4% | With temporal metadata (baseline 40.4%) |
| Fragment throughput | 89,006 fragments / 27 seconds | Entire pipeline including ingestion + embedding + search |
Search achieves over 80% recall in 5 out of 6 question types. However, there is a significant gap between search recall (88.3%) and QA accuracy (45.4%), mainly due to limitations in the reader stage that synthesizes answers from retrieved fragments, particularly noticeable in multi-session reasoning and temporal reasoning.
For detailed analysis, refer to the [Benchmark Report](docs/benchmark.md).
## Usage Patterns
AnchorMind is optimized for factual memory (fact cache). For scenarios where context is crucial:
- Store narratives in `episode` type to restore the context of decisions.
- Store `contextSummary` alongside to include context in recall responses.
- A two-tiered structure with main memory systems (MEMORY.md, etc.) and AnchorMind for factual search and context restoration can be effective.
## Who is it for?
- Developers who use AI agents like Claude Code, Cursor, or Windsurf daily.
- Those tired of repeating the same explanations for each session.
- Individuals who want AI to remember their project context.
## Directory Structure
```
lib/
memory/
read/ # FragmentSearch, SearchScope, SearchSideEffects, CaseRecall, etc.
write/ # MemoryRememberer, BatchRememberProcessor, etc.
link/ # MemoryLinker, ReconsolidationEngine, etc.
consolidate/ # MemoryConsolidator
embedding/ # EmbeddingWorker, EmbeddingCache, MorphemeIndex
signals/ # SpreadingActivation, CaseRewardBackprop, etc.
processors/ # facade — MemoryRecaller, MemoryReflector, etc.
storage/ # PgVectorStore (default), SqliteVecStore (stub, not implemented) adapter layer
llm/ # dispatchChain, provider implementations
symbolic/ # SymbolicVerificationLayer (opt-in)
docs/
getting-started/ # Platform-specific installation guides
operations/ # Operation guides (llm-providers, symbolic-hard-gate, etc.)
features.md # Module ledger
configuration.md # Complete reference of environment variables
```
## Further Reading
| Document | Content |
|----------|---------|
| [Quick Start](docs/getting-started/quickstart.md) | Detailed installation guide |
| [Architecture](docs/architecture.md) | System structure, DB schema, 3-tier search, TTL |
| [Configuration](docs/configuration.md) | Environment variables, MEMORY_CONFIG, embedding providers |
| [API Reference](docs/api-reference.md) | HTTP endpoints, prompts, resources |
| [CLI](docs/cli.md) | Terminal commands |
| [Internals](docs/internals.md) | Evaluators, integrators, contradiction detection |
| [Benchmark](docs/benchmark.md) | Detailed analysis of LongMemEval-S benchmark |
| [Features](docs/features.md) | Module ledger, experimental flags, ENV mapping |
| [SKILL.md](SKILL.md) | Complete MCP tool reference |
| [INSTALL.md](docs/INSTALL.md) | Migration, hook settings, detailed installation |
| [CHANGELOG](CHANGELOG.md) | Version-by-version changes |
## Operations
- `/health`: Comprehensive health check for DB, Redis, pgvector, and worker status. Returns degraded responses in case of partial failures.
- Rate Limiting: 100 requests/minute per API key, 30 requests/minute per IP. Configurable via environment variables.
- Worker recovery: Embedding and evaluation workers retry with exponential backoff (1s→60s) in case of errors.
- Graceful Shutdown: Waits for ongoing workers to complete (30 seconds) and then auto-reflects sessions upon receiving SIGTERM.
- OAuth endpoint: Returns `WWW-Authenticate` header upon authentication failure to allow OAuth clients to initiate the authentication flow automatically. The default session TTL is 240 minutes.
- Migration lint: Checks for ID collisions and convention violations before committing with `npm run lint:migrations`.
- Operation guide: [docs/operations/](docs/operations/) — LLM provider chains, symbolic hard gate, agent worktree, upstream porting, etc.
- External exposure checks: Follow the "External Exposure Check" procedure in `docs/operations/maintenance.md` to verify listen addresses, authentication keys, and Origin allowlists.
## Known Limitations
- L1 Redis cache only supports API key-based isolation. Isolation between agents in multi-agent environments is applied at L2/L3.
- Automatic quality evaluation only targets `decision`, `preference`, and `relation` types. `fact`, `procedure`, and `error` are excluded from the evaluation queue.
- If `MEMENTO_ACCESS_KEY` is not set, authentication is disabled. It must be set in externally exposed environments.
- `ALLOWED_ORIGINS` — Whitelist for browser-based MCP clients. If not set, all Origins are allowed. In externally exposed environments, set `MCP_STRICT_ORIGIN=true` and register only actual browser Origins used.
Desktop/CLI/IDE extensions (Claude Code, Cursor, Windsurf, Continue, Cline, Zed, gemini CLI, etc.) do not send Origin headers, so whitelisting is not necessary.
Browser candidates: claude.ai, claude.com, chatgpt.com, chat.openai.com, copilot.microsoft.com,
gemini.google.com, aistudio.google.com, www.perplexity.ai, cursor.com, codeium.com,
windsurf.com, sourcegraph.com, typingmind.com (selectively filter actual callers).
- `ADMIN_ALLOWED_ORIGINS` — Whitelist for Admin UI call origins. If not set, all Origins are allowed. In externally exposed environments, specify or restrict access to the management console Origin using a reverse proxy/firewall.
- `TRUST_PROXY_HOPS` — Number of trusted reverse proxy hops. If not set, existing behavior is maintained (first item of XFF).
Set to 0 for direct exposure, 1 for a single proxy hop.
- `OAUTH_TRUSTED_ORIGINS` — Whitelist for origins that automatically approve consent. If multiple apps are hosted on the same origin, use full URI matching of `OAUTH_ALLOWED_REDIRECT_URIS`.
## Tech Stack
- Node.js 20+
- PostgreSQL 14+ (with pgvector extension)
- Redis 6+ (optional)
- OpenAI Embedding API (optional) or `EMBEDDING_PROVIDER=transformers` (local low-cost mode)
- garu-ko / natural PorterStemmer / @node-rs/jieba / kuromoji (local morpheme analysis, language-specific CPU routing; default with `MEMENTO_MORPHEME_TOKENIZER=local`)
- Gemini CLI / Codex CLI / GitHub Copilot CLI (quality evaluation, automatic reflect; optional, configured with LLM_PRIMARY / LLM_FALLBACKS)
- @huggingface/transformers + ONNX Runtime (NLI contradiction classification + local embedding, CPU-only)
- MCP Protocol 2025-11-25
Core functionality works with PostgreSQL alone. Adding Redis enables L1 cache search and SessionActivityTracker, while adding OpenAI API or setting `EMBEDDING_PROVIDER=transformers` enables L3 semantic search and automatic linking.
## Motivation
<details>
<summary>Expand/Collapse</summary>
In practice, using AI daily, I felt inefficiencies in repeatedly explaining the same context. While trying methods like adding notes to system prompts, limitations were clear. As the number of fragments grew, management became difficult, search functionality failed, and old and new information conflicted.
The biggest issue was making AI repeat explanations endlessly. Even with authentication information, some settings weren't applied. Thorough disproof was needed to make AI listen, but it only lasted until the next session. Restarting the session repeated the same issues. It felt like being an educational supervisor for a new employee whose brain resets daily.
"Hey, do you remember me?" — Without cues, nothing comes to mind, but a single phrase like "My elementary school buddy" brings up everything. AI works similarly. Yesterday's bug fixes, last week's decisions, and preferred coding styles. Instead of resetting each session, AnchorMind remembers.
This pain led to designing a system that breaks down memories into atomic units, searches them hierarchically, and naturally forgets over time.
</details>
License
Apache 2.0
---
<p align="center">
Made by <a href="mailto:jinho.von.choi@nerdvana.kr">Jinho Choi</a> |
<a href="https://buymeacoffee.com/jinho.von.choi">Buy me a coffee</a>
</p>
MCP Config
Below is the configuration for this MCP Server. You can copy it directly to Cursor or other MCP clients.
mcp.json
Connection Info
You Might Also Like
No recommendations available