Token-lean memory for AI agents: a knowledge graph searched cheaply. Drop-in for server-memory.
Runs on your machine from its package; the steps are below.
Not assessed yet.
Odel charges nothing per call. The publisher may charge for its own service.
Runs locally over stdio
This server isn't hosted — your MCP client launches it from a package registry. Use one of the commands below, or drop the config into your client (e.g. Claude Desktop).
Run
npx -y memory-lean
MCP client config
{
"mcpServers": {
"memory-lean": {
"command": "npx",
"args": [
"-y",
"memory-lean"
]
}
}
}
Long-term memory for AI coding agents that doesn't burn the context window.
Quick start · What the agent sees · Why it stays lean · Tools · Agent protocol · Settings · Contributing
memory-lean is an MCP server that gives Claude
Code, Claude Desktop, Cursor and any other MCP client a knowledge graph that
persists between sessions. It is a drop-in replacement for the reference memory
server (@modelcontextprotocol/server-memory):
same memory.jsonl file, same nine tool names, plus two extras. What changes is
how much the tools send back.
| Call, on a real graph of 237 entities | Reference server | memory-lean | |
|---|---|---|---|
read_graph | ~77,800 tokens | ~2,000 tokens | 40× smaller |
search_nodes (average of 5 common words) | ~31,000 tokens | ~770 tokens | 40× smaller |
One file. No dependencies. Nothing to build.
Claude Code: install the plugin. It adds the server, a skill with the agent instructions, and a short reminder at the start of each session.
/plugin marketplace add zamansheikh/memory-lean
/plugin install memory-lean@memory-lean
Any other agent: add the server to the agent's MCP config, then give the agent the instructions.
{
"mcpServers": {
"memory": { "command": "npx", "args": ["-y", "memory-lean"] }
}
}
npx -y memory-lean --protocol >> AGENTS.md # into the rules file your agent reads
The config file and its exact shape differ per agent.
Copy-paste setup for each agent is in docs/SETUP.md:
| Agent | Server config | Instructions |
|---|---|---|
| Claude Code | plugin | included in the plugin |
| Xiaomi MiMo Code | mimocode.jsonc | skill or AGENTS.md |
| opencode | opencode.json | AGENTS.md |
| OpenAI Codex CLI | codex mcp add | AGENTS.md |
| Cursor | .cursor/mcp.json | AGENTS.md or a rule |
| VS Code (Copilot) | .vscode/mcp.json | copilot-instructions.md |
| Gemini CLI | settings.json | GEMINI.md |
| Windsurf | mcp_config.json | a rule |
| Cline | cline_mcp_settings.json | .clinerules/ |
| Zed | settings.json | AGENTS.md or .rules |
| JetBrains IDEs | AI Assistant settings | a rule or guidelines |
| Claude Desktop | claude_desktop_config.json | project instructions |
The graph is created on the first write at ~/.claude/memory-graph/memory.jsonl,
whichever agent writes to it, so several agents can share one memory. Set
MEMORY_FILE_PATH to keep it somewhere else.
git clone https://github.com/zamansheikh/memory-lean.git
claude mcp add --scope user memory -- node /absolute/path/to/memory-lean/server/memory-lean.mjs
No npm install is needed.
The reference server answers a search with every matching entity in full, as pretty-printed JSON. memory-lean answers with a ranked list of names and the lines that matched:
> search_nodes { "query": "deploy" }
57 match "deploy", top 10 shown (narrow the query or raise limit). open_nodes for full entities.
- shop-backend [service] 12 obs, 6 rel
› 2026-03-02: deployed 2.4.0 to production
› deploy with scripts/release.sh, never by hand
- PENDING shop-backend 2.4.0 [pending] 2 obs, 3 rel
› …mobile apps still call the old endpoint until the deploy of 2.4.0 reaches them
The agent then opens only what it needs:
> open_nodes { "names": ["shop-backend"] }
## shop-backend [service]
- NestJS API behind api.example.com
- 2026-03-02: deployed 2.4.0 to production
## relations
shop-app -talks_to-> shop-backend
PENDING shop-backend 2.4.0 -blocks-> shop-app
That is the whole pattern: search, then open.
A knowledge graph is only useful if the agent can afford to look at it, and a graph that every session appends to grows without limit. memory-lean limits both what it returns and what it stores.
| Limit | What it means |
|---|---|
| Small answers | search_nodes returns at most 10 names with snippets, read_graph returns an index of names, and only open_nodes returns full entities. |
| Short facts | An observation longer than 300 characters is rejected, with a message telling the agent to split it or put the detail in the repo. |
| A cap per entity | An entity keeps 15 observations. Past that, the oldest dated ones move to archive/<entity>.md next to the graph. Nothing is deleted: the agent can list and restore them, and undated observations (the identity facts) always stay. |
| Multi-word search that works | Every word must match somewhere in the entity, so adding a word narrows the result. The reference server looks for the query as one exact phrase. |
And it is careful with the file:
| Safeguard | What it means |
|---|---|
| Safe to share | Writers take a lock file, so several agent sessions can use one graph without overwriting each other. Every write replaces the file atomically. |
| Daily backups | A copy goes to backups/ once a day; the last 7 are kept. |
| Damaged lines are kept | A line that cannot be read is moved to memory.jsonl.unreadable on the next write and reported, never silently dropped. |
| Plain files | The graph is JSON lines, archives are Markdown, backups are copies. You can read, grep and edit all of it by hand. |
From a clone of this repo:
node tools/bench.mjs # read_graph + your five most common words
node tools/bench.mjs deploy "api v2" # your own queries
It is read-only and prints sizes, never content. Tokens are estimated as characters ÷ 4. A narrow search that matches one or two entities saves much less, because there was little to trim.
| Tool | What it returns |
|---|---|
search_nodes | Ranked list of entity names with counts and up to two matching snippets each. Every word must match the name, type, an observation, or the type of a relation touching the entity. |
open_nodes | The full entities you name, as compact text, with every relation touching them. Unknown names come back with "did you mean" suggestions. |
read_graph | An index: entity names grouped by type, with observation counts. Never the observations. |
create_entities | Creates entities; existing names are skipped. |
create_relations | Creates relations between existing entities; duplicates are skipped. |
add_observations | Adds facts to an entity, enforcing the length limit and the per-entity cap. |
rename_entity | Renames an entity, keeping its observations, relations and archive. Not in the reference server. |
archived_observations | Lists what was archived for an entity, optionally filtered, and can restore chosen observations. Not in the reference server. |
delete_observations | Removes observations by exact text. |
delete_relations | Removes specific relations. |
delete_entities | Removes entities and every relation touching them. |
The three read tools are marked read-only, so clients that support it can run them without asking.
A memory server only helps if the agent reads it before working and writes to it
when something changes. docs/AGENT-PROTOCOL.md is a
ready-made set of instructions: what to look up at the start of a task, what to
record, how to name things, and what never to store. The Claude Code plugin
includes it. For every other agent, one command installs it:
npx -y memory-lean --protocol >> AGENTS.md # into a rules file: always on
npx -y memory-lean --skill .agents/skills # as an Agent Skill: loaded when relevant
Adjust the entity types and names in it to your own work.
Point MEMORY_FILE_PATH at your existing memory.jsonl and swap the command. The
file format is identical, so you can switch back at any time. Existing
observations longer than 300 characters are kept as they are; only new writes are
checked.
To see what in an existing graph is over budget, and optionally fix it:
npx -y memory-lean --lint # report only
npx -y memory-lean --compact # back up, then move overflow to archive/
All optional, set as environment variables on the server:
| Variable | Default | Meaning |
|---|---|---|
MEMORY_FILE_PATH | ~/.claude/memory-graph/memory.jsonl | Where the graph lives |
MEMORY_OBS_MAX_CHARS | 300 | Longest observation accepted |
MEMORY_OBS_MAX | 15 | Observations per entity before the oldest dated ones are archived |
MEMORY_SEARCH_LIMIT | 10 | Default number of search results |
MEMORY_BACKUPS_KEPT | 7 | Daily backups kept |
rename_entity, keeping relations intactIdeas, bug reports and pull requests are welcome. The whole server is one file
with no dependencies, and npm test runs in about a second, so a first change is
quick to make. CONTRIBUTING.md has the layout, the ground rules
and a list of good first contributions.
If you try memory-lean on your own graph, the output of tools/bench.mjs makes a
useful issue post. And if it saves you tokens, a ⭐ helps other people find it.
memory-lean is free and MIT licensed. If it is useful to you, you can support the work:
Created and maintained by Zaman Sheikh at Silifton.
Built on the file format and tool names of the Model Context Protocol reference memory server.
MIT © 2026 Zaman Sheikh. Free to use, change and share, including commercially; keep the copyright notice.