
Memory MCP Server
- Updated March 1, 2026
- j0hanz/memory-mcp
Memory MCP Server is a MCP server that provides SQLite-backed persistent memory with full-text search and graph traversal for agents.
About
Memory MCP Server is a Model Context Protocol integration that stores agent-accessible memory in SQLite, combining full-text search with graph traversal so coding assistants can recall facts, link related entities, and navigate relationships over weeks of shipping. developers register @j0hanz/memory-mcp when chat context windows are insufficient for product decisions, integration quirks, or customer support playbooks that must persist across sessions. Version 1.7.0 uses stdio transport and suits Claude Code, Cursor, and other MCP clients as journey-wide infrastructure: you stand it up during Build agent-tooling, then lean on it during Operate iteration and Grow support when the agent needs institutional memory. It complements filesystem MCP (where files live) and fetch MCP (what you read from the web) by giving the agent a structured recall layer. Scope what you store and avoid secrets in plaintext; treat the SQLite file as part of your backup story.
- SQLite-backed persistent memory with full-text retrieval
- Graph traversal for linked entities and relationships
- npm package @j0hanz/memory-mcp v1.7.0 with stdio MCP transport
- Survives session restarts unlike ephemeral chat context alone
- Fits solo-builder stacks that track product decisions, customer notes, or architecture facts
Memory MCP Server by the numbers
- Data as of Jul 7, 2026 (Skillselion catalog sync)
claude mcp add memory-mcp -- npx -y @j0hanz/memory-mcpAdd your badge
Show developers this MCP server is listed on Skillselion. Paste this into your README.
| Package | @j0hanz/memory-mcp |
|---|---|
| Transport | STDIO |
| Auth | None |
| Last updated | March 1, 2026 |
| Repository | j0hanz/memory-mcp ↗ |
What it does
Persist decisions, entities, and relationships across agent sessions with SQLite-backed memory, search, and graph traversal.
Who is it for?
Best when you're running multi-week agent projects and need durable, queryable memory beyond the current chat thread.
Skip if: One-off scripts or teams that already centralize knowledge in a audited team wiki with strict compliance requirements only.
What you get
After install, agents can store, search, and traverse linked memories so long-running solo projects keep coherent context.
- Persistent memory records searchable via full-text MCP tools
- Linked entities traversable as a graph from agent sessions
- Reduced re-onboarding of project context after restarts
By the numbers
- Version 1.7.0, npm package @j0hanz/memory-mcp
- Storage: SQLite with full-text retrieval and graph traversal
- Transport: stdio per MCP server schema 2025-12-11
README.md
Memory MCP
A SQLite-backed MCP server for persistent memory storage, full-text retrieval, and relationship graph traversal.
Overview
Memory MCP provides a local, persistent memory layer for MCP-enabled assistants. It stores SHA-256-addressed memory items in SQLite with FTS5-powered full-text search, a directed relationship graph, BFS recall traversal, and token-budget-aware context retrieval — all accessible over stdio transport with no external dependencies.
Key Features
- 13 MCP tools for CRUD, batch operations, FTS5 search, BFS graph recall, token-budget context retrieval, relationships, and stats.
- Full-text search over content and tags via SQLite FTS5 with importance and type filters.
- Graph recall with BFS traversal, bounded frontier, and MCP progress notifications per hop.
- Token-budget retrieval (
retrieve_context) selects memories that fit a caller-specified token budget — no manual pagination needed. - Strict Zod input validation with typed output envelopes and SHA-256 hash addressing.
- Resource support with
internal://instructions(Markdown guide) andmemory://memories/{hash}URI template with hash auto-completion. - stdio transport with clean shutdown handling (
SIGINT,SIGTERM) and no HTTP endpoints. |
Requirements
- Node.js
>=24. - SQLite with FTS5 support (verified at startup).
- Any MCP client that supports stdio command servers.
Quick Start
Use the npm package directly with npx — no installation required:
{
"mcpServers": {
"memory-mcp": {
"command": "npx",
"args": ["-y", "@j0hanz/memory-mcp@latest"]
}
}
}
[!TIP] The server uses stdio transport only; no HTTP endpoint is exposed. Stdout must not be polluted by custom logging.
Or run with Docker:
docker run --rm -i ghcr.io/j0hanz/memory-mcp:latest
Client Configuration
Install in VS Code
Workspace file .vscode/mcp.json:
{
"servers": {
"memory-mcp": {
"command": "npx",
"args": ["-y", "@j0hanz/memory-mcp@latest"]
}
}
}
CLI:
code --add-mcp '{"name":"memory-mcp","command":"npx","args":["-y","@j0hanz/memory-mcp@latest"]}'
Install in VS Code Insiders
CLI:
code-insiders --add-mcp '{"name":"memory-mcp","command":"npx","args":["-y","@j0hanz/memory-mcp@latest"]}'
Install in Cursor
~/.cursor/mcp.json:
{
"mcpServers": {
"memory-mcp": {
"command": "npx",
"args": ["-y", "@j0hanz/memory-mcp@latest"]
}
}
}
Install in Claude Desktop / Claude Code
claude_desktop_config.json:
{
"mcpServers": {
"memory-mcp": {
"command": "npx",
"args": ["-y", "@j0hanz/memory-mcp@latest"]
}
}
}
CLI:
claude mcp add memory-mcp -- npx -y @j0hanz/memory-mcp@latest
Install in Windsurf
MCP config:
{
"mcpServers": {
"memory-mcp": {
"command": "npx",
"args": ["-y", "@j0hanz/memory-mcp@latest"]
}
}
}
Run with Docker
# Pull and run (stdio mode)
docker run --rm -i \
-e MEMORY_DB_PATH=/data/memory.db \
-v memory-data:/data \
ghcr.io/j0hanz/memory-mcp:latest
MCP client config:
{
"mcpServers": {
"memory-mcp": {
"command": "docker",
"args": [
"run",
"--rm",
"-i",
"-e",
"MEMORY_DB_PATH=/data/memory.db",
"-v",
"memory-data:/data",
"ghcr.io/j0hanz/memory-mcp:latest"
]
}
}
}
Documentation Maintenance
- Owner: maintainers updating MCP behavior in
src/must updateREADME.mdand affectedmcp/mirror pages in the same PR. - Link/version policy: use pinned
https://modelcontextprotocol.io/specification/2025-11-25/...links for protocol references; avoidlatestand mixed legacy targets. - Drift-check checklist:
- Re-verify capability declarations in
src/server.ts. - Reconcile tool/resource/prompt docs with
src/tools/index.ts,src/resources/index.ts, andsrc/prompts/index.ts. - Confirm limitations/gotchas in
src/instructions.mdmatch runtime behavior.
- Re-verify capability declarations in
- Validation commands:
npm run type-check,npm run test:fast,npm run build.
MCP Surface
Tools Summary
| Tool | Category | Notes |
|---|---|---|
store_memory |
Write | Idempotent by content+sorted tags hash |
store_memories |
Write | Batch (1–50), transaction-wrapped |
get_memory |
Read | Hash lookup |
update_memory |
Write | Returns old_hash + new_hash |
delete_memory |
Write | Cascades relationship deletion |
delete_memories |
Write | Batch (1–50), transaction-wrapped |
search_memories |
Read | FTS5 + importance/type filters + cursor |
create_relationship |
Write | Idempotent directed edge creation |
delete_relationship |
Write | Deletes exact directed edge |
get_relationships |
Read | Direction filter + linked memory fields |
recall |
Read | FTS5 seed + BFS traversal (depth 0–3) |
retrieve_context |
Read | Token-budget-aware context retrieval |
memory_stats |
Read | Store aggregates and type breakdown |
store_memory
Store a new memory with content, tags, and optional type/importance. Idempotent — storing the same content+tags returns the existing hash with created: false.
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
content |
string |
Yes | — | Memory content (1–100000 chars) |
tags |
string[] |
Yes | — | 1–100 tags, each max 50 chars, no whitespace |
memory_type |
enum | No | general |
general, fact, plan, decision, reflection, lesson, error, gradient |
importance |
integer |
No | 0 |
Priority 0–10 |
Returns: { hash, created }
store_memories
Store multiple memories in one transaction (max 50 items).
| Name | Type | Required | Description |
|---|---|---|---|
items |
Array<StoreMemoryItem> |
Yes | 1–50 items, each with content, tags, optional memory_type, optional importance |
Returns: { items, succeeded, failed }
get_memory
Retrieve one memory by its SHA-256 hash.
| Name | Type | Required | Description |
|---|---|---|---|
hash |
string |
Yes | 64-char lowercase SHA-256 hex |
Returns: Memory or { ok: false, error } on E_NOT_FOUND.
update_memory
Update content and optionally tags for an existing memory. Returns both hashes.
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
hash |
string |
Yes | — | Existing memory hash |
content |
string |
Yes | — | Replacement content |
tags |
string[] |
No | Existing tags | Replacement tags |
Returns: { old_hash, new_hash }
delete_memory
Delete one memory by hash. Cascades to related relationship rows.
| Name | Type | Required | Description |
|---|---|---|---|
hash |
string |
Yes | Memory hash |
Returns: { hash, deleted }
delete_memories
Delete multiple memories by hash in one transaction.
| Name | Type | Required | Description |
|---|---|---|---|
hashes |
string[] |
Yes | 1–50 memory hashes |
Returns: { items, succeeded, failed }
search_memories
Full-text search over memory content and tags using FTS5. Supports importance and type filters with cursor pagination.
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
query |
string |
Yes | — | Search text (1–1000 chars) |
limit |
integer |
No | 20 |
Results per page (1–100) |
cursor |
string |
No | — | Pagination cursor from previous response |
min_importance |
integer |
No | — | Only return memories with importance >= this value (0–10) |
max_importance |
integer |
No | — | Only return memories with importance <= this value (0–10) |
memory_type |
enum | No | — | Filter by memory type |
Returns: { memories, total_returned, nextCursor? }
create_relationship
Create a directed relationship edge between two memories. Idempotent.
Suggested relation_type values: related_to, causes, depends_on, parent_of, child_of, supersedes, contradicts, supports, references.
| Name | Type | Required | Description |
|---|---|---|---|
from_hash |
string |
Yes | Source memory hash |
to_hash |
string |
Yes | Target memory hash |
relation_type |
string |
Yes | Edge label (1–50 chars, no whitespace, free-form) |
Returns: { created }
delete_relationship
Delete one directed relationship edge.
| Name | Type | Required | Description |
|---|---|---|---|
from_hash |
string |
Yes | Source hash |
to_hash |
string |
Yes | Target hash |
relation_type |
string |
Yes | Relationship type |
Returns: { deleted } or { ok: false, error } on E_NOT_FOUND.
get_relationships
Retrieve relationships for a memory, with optional direction filter.
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
hash |
string |
Yes | — | Memory hash |
direction |
enum | No | both |
outgoing, incoming, or both |
Returns: { relationships, count }
Each relationship includes from_hash, to_hash, relation_type, created_at, linked_hash, linked_content, and linked_tags.
recall
Search memories by full-text query, then traverse the relationship graph up to depth hops via BFS. Emits MCP progress notifications per hop.
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
query |
string |
Yes | — | Seed search query (1–1000 chars) |
depth |
integer |
No | 1 |
BFS hops (0–3) |
limit |
integer |
No | 10 |
Seed memory count (1–50) |
cursor |
string |
No | — | Pagination cursor from previous response |
min_importance |
integer |
No | — | Seed filter: only memories with importance >= value (0–10) |
max_importance |
integer |
No | — | Seed filter: only memories with importance <= value (0–10) |
memory_type |
enum | No | — | Seed filter: only memories of this type |
Returns: { memories, graph, depth_reached, aborted?, nextCursor? }
Each item in graph uses the shape:
{ "from_hash": "...", "to_hash": "...", "relation_type": "..." }
[!NOTE]
aborted: trueindicates the traversal hit a safety limit (RECALL_MAX_FRONTIER_SIZE,RECALL_MAX_EDGE_ROWS, orRECALL_MAX_VISITED_NODES). Partial results are still returned.
retrieve_context
Search memories and return relevance-ranked results that fit within a caller-specified token budget. Eliminates manual pagination and token counting for context window management.
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
query |
string |
Yes | — | Search query (1–1000 chars) |
token_budget |
integer |
No | 4000 |
Maximum estimated tokens to return (100–200000) |
strategy |
enum | No | relevance |
Sort order: relevance (FTS rank), importance (highest first), recency (newest first) |
Returns: { memories, estimated_tokens, truncated }
[!TIP] Token estimation is approximate (content length ÷ 4).
truncated: truemeans the budget was reached before all candidates were included.
memory_stats
Return aggregate memory and relationship stats. Takes no input.
Returns:
{
"memories": {
"total": 0,
"oldest": null,
"newest": null,
"avg_importance": null
},
"relationships": { "total": 0 },
"by_type": {}
}
Resources
| URI | MIME | Description |
|---|---|---|
internal://instructions |
text/markdown |
Markdown usage guide for all tools and workflows |
memory://memories/{hash} |
application/json |
Returns one memory as JSON; hash completion supported |
Prompts
| Name | Arguments | Purpose |
|---|---|---|
get-help |
none | Returns full usage instructions for all tools |
Configuration
Environment Variables
| Variable | Description | Default | Required |
|---|---|---|---|
MEMORY_DB_PATH |
SQLite database file path | memory_db/memory.db |
No |
RECALL_MAX_FRONTIER_SIZE |
Max BFS frontier nodes per hop (100–50000) | 1000 |
No |
RECALL_MAX_EDGE_ROWS |
Max relationship rows fetched per traversal (100–50000) | 5000 |
No |
RECALL_MAX_VISITED_NODES |
Max visited nodes across entire traversal (100–50000) | 5000 |
No |
[!IMPORTANT] If
MEMORY_DB_PATHis relative (including the defaultmemory_db/memory.db), it resolves from the process working directory.
[!TIP] Add
memory_db/to your.gitignoreto keep the database out of version control — it contains local session data and should not be shared or committed.
Limits and Constraints
| Item | Value |
|---|---|
| Content length | 1–100000 chars |
| Tag count | 1–100 per memory |
| Tag length | 1–50 chars, no whitespace |
| Hash format | 64-char lowercase hex SHA-256 |
| Search query length | 1–1000 chars |
search_memories.limit |
1–100 (default 20) |
recall.depth |
0–3 (default 1) |
recall.limit |
1–50 (default 10) |
retrieve_context.token_budget |
100–200000 (default 4000) |
| Batch size | 1–50 items (store_memories, delete_memories) |
| Recall frontier guard | RECALL_MAX_FRONTIER_SIZE (default 1000 per hop) |
| SQLite busy timeout | 5000 ms |
[!NOTE] Cursor values are opaque base64url-encoded tokens. Treat them as opaque and do not parse them.
Security
- Transport is stdio-only (
StdioServerTransport) — no HTTP endpoints. - Fatal process errors are written to
stderr; stdout must remain clean for the MCP protocol. - All inputs are validated with strict Zod schemas and bounded field constraints before any database access.
- Hashes are validated against a lowercase 64-char SHA-256 hex regex.
- Search input is tokenized to alphanumeric terms before FTS
MATCHexecution (non-alphanumeric characters act as delimiters, preventing FTS injection). - SQLite foreign keys are enabled; relationship rows cascade-delete when a memory is removed.
Development
Install dependencies:
npm install
Core scripts:
| Script | Command | Purpose |
|---|---|---|
build |
npm run build |
Clean, compile, validate instructions, copy assets, chmod executable |
dev |
npm run dev |
TypeScript watch mode |
dev:run |
npm run dev:run |
Run built server with .env and file watch |
start |
npm run start |
Start built server |
test |
npm run test |
Full build + tests via task runner |
test:fast |
npm run test:fast |
Run TS tests directly with Node test runner |
lint |
npm run lint |
ESLint checks |
lint:fix |
npm run lint:fix |
ESLint auto-fix |
type-check |
npm run type-check |
Strict TypeScript checks |
format |
npm run format |
Prettier format |
inspector |
npm run inspector |
Build and open MCP Inspector against stdio server |
Inspect with MCP Inspector:
npx @modelcontextprotocol/inspector node dist/index.js
Build & Release
GitHub Actions release workflow (.github/workflows/release.yml) handles versioning, validation, and publishing via a single workflow_dispatch trigger:
workflow_dispatch (patch / minor / major / custom)
│
▼
release — bump package.json + server.json → lint → type-check → test → build → tag → GitHub Release
│
├──► publish-npm ──► publish-mcp (npm Trusted Publishing OIDC → MCP Registry)
│
└──► publish-docker (GHCR, linux/amd64 + linux/arm64)
Trigger a release:
gh workflow run release.yml -f bump=patch
Or use the GitHub UI: Actions → Release → Run workflow.
[!NOTE] npm publishing uses OIDC Trusted Publishing — no
NPM_TOKENsecret required. MCP Registry uses GitHub OIDC. Docker uses the built-inGITHUB_TOKEN.
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
| Startup fails with FTS5 error | Node.js build without FTS5 | Use Node.js 24+ with SQLite FTS5 support |
E_NOT_FOUND on get_memory |
Hash doesn't exist | Verify via search_memories first |
E_INVALID_CURSOR |
Stale or malformed cursor | Retry the request without the cursor parameter |
| MCP client can't connect | Custom stdout logging added | Ensure nothing writes to stdout in the server process |
aborted: true in recall |
Traversal hit a safety limit | Reduce depth, or tune RECALL_MAX_* env vars |
| Database locked errors | High concurrent write load | SQLite busy timeout is 5000 ms; reduce concurrent writes |
License
MIT
Recommended MCP Servers
How it compares
Persistent memory MCP with FTS and graphs, not a vector SaaS RAG platform or a simple notes markdown skill.
FAQ
Who is memory-mcp for?
Developers and agent-first workflows that need cross-session recall of decisions, entities, and relationships via MCP.
When should I use memory-mcp?
Use it when the same project spans many sessions and you want the agent to remember facts, link concepts, and full-text search prior notes.
How do I add memory-mcp to my agent?
Install @j0hanz/memory-mcp from npm, register the stdio server in your MCP client, and point it at a persistent SQLite storage location per the repo README.