Knowledge Graph Memory Server
Memory serverOfficial Model Context Protocol project
Created by Model Context Protocol
Published in modelcontextprotocol/servers. Publisher page
91,920 GitHub stars
What it is
MCP server for enabling memory for Claude through a knowledge graph
AutoGineer overview, from the brain’s own files
This memory server enables AI agents, specifically those using the Model Context Protocol, to maintain persistent information across sessions. It structures data as a knowledge graph consisting of entities, relations, and observations. Entities represent distinct nodes, relations define directed connections between them, and observations store atomic facts about specific entities. The system supports full CRUD operations on the graph, allowing agents to create, search, and delete nodes and connections. It stores data in a local JSONL file and includes locking mechanisms to ensure data integrity when accessed by multiple processes.
How it works
Memory model: Knowledge graph
AutoGineer overview, from the brain’s own files
The system operates as an MCP server that manages a knowledge graph stored in a local JSONL file. It provides tools for agents to create entities with types and observations, establish directed relations between entities, and perform granular updates or deletions of facts. The server exposes the entire graph as an MCP resource, allowing agents to read, search, and modify the graph structure dynamically. It handles concurrent access through file-based locking and ensures atomic saves by writing updates to temporary files before renaming them.
| Folder | Role | Files |
|---|---|---|
| src/memory/__tests__ | tests | 17 |
The agent reads
- search_nodes evidence: src/memory/README.md
Requirements
Apps: Docker
Runtimes: Node.js >=24
Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Google Antigravity, Kiro, OpenCode, Amp, Roo Code, Cline, JetBrains Junie, Devin (ex-Windsurf)
Set it up
This brain runs code automatically: 1 script. Review src/memory/package.json before opening the folder in Claude Code. No step below turns a hook on for you.
src/memory/package.json:npm run build
- Not scanned by AutoGineerThe author’s MCP configuration (src/memory/README.md) also starts it in a way AutoGineer does not offer. Read that file: AutoGineer did not scan that path; what it runs is listed under “This brain runs”. https://github.com/modelcontextprotocol/servers/blob/e1dc4b18dbb948921da37f3d4224a628730b43b0/src/memory/README.md
- Not scanned by AutoGineerIts dependencies are installed by npm when you run it and were not scanned by AutoGineer (2 declared). https://www.npmjs.com/package/@modelcontextprotocol/server-memory
Created by Model Context Protocol. Published in modelcontextprotocol/servers. Licence: Apache License 2.0.
Usage
AutoGineer overview, from the brain’s own files
- Configure the server in the Claude Desktop or VS Code MCP settings.
- Use the provided tools to create entities for people, organizations, or events.
- Define relations between entities to map connections.
- Add atomic observations to entities to store specific facts.
- Search or read the graph to retrieve relevant context for agent interactions.
- Delete specific observations or entities to manage memory size and relevance.
- “Create an entity for 'John Smith' with the observation 'Speaks fluent Spanish'.”
- The agent calls create_entities to add John Smith to the knowledge graph with the specified observation.
- “Connect 'John Smith' to 'Anthropic' with the relation 'works_at'.”
- The agent calls create_relations to establish a directed link between the two entities.
Documentation by Model Context Protocol
Knowledge Graph Memory Server
A basic implementation of persistent memory using a local knowledge graph. This lets Claude remember information about the user across chats.
Published on npm as @modelcontextprotocol/server-memory.
Core Concepts
Entities
Entities are the primary nodes in the knowledge graph. Each entity has:
A unique name (identifier)
An entity type (e.g., "person", "organization", "event")
A list of observations
Example:
{
"name": "John_Smith",
"entityType": "person",
"observations": ["Speaks fluent Spanish"]
}Relations
Relations define directed connections between entities. They are always stored in active voice and describe how entities interact or relate to each other.
Example:
{
"from": "John_Smith",
"to": "Anthropic",
"relationType": "works_at"
}Observations
Observations are discrete pieces of information about an entity. They are:
Stored as strings
Attached to specific entities
Can be added or removed independently
Should be atomic (one fact per observation)
Example:
{
"entityName": "John_Smith",
"observations": [
"Speaks fluent Spanish",
"Graduated in 2019",
"Prefers morning meetings"
]
}API
Tools
create_entities
Create multiple new entities in the knowledge graph
Input:
entities(array of objects)Each object contains:
name(string): Entity identifierentityType(string): Type classificationobservations(string[]): Associated observations
Ignores entities with existing names (and repeats of a name earlier in the same call); their observations are not added
Returns the created entities. When any were skipped, the structured result also lists their names in
skipped, and a second text item says which were skipped (useadd_observationsto extend an existing entity)
create_relations
Create multiple new relations between entities
Input:
relations(array of objects)Each object contains:
from(string): Source entity nameto(string): Target entity namerelationType(string): Relationship type in active voice
Skips duplicate relations
Fails if either the source or target entity doesn't exist
add_observations
Add new observations to existing entities
Input:
observations(array of objects)Each object contains:
entityName(string): Target entitycontents(string[]): New observations to add
Returns added observations per entity
Fails if entity doesn't exist
delete_entities
Remove whole entities, with all their observations
Input:
entityNames(string[])Cascading deletion of every relation that points to or from a deleted entity
To remove a link between two entities and keep both, use
delete_relations; to remove facts from an entity, usedelete_observationsNo error if an entity doesn't exist; the response reports which names were not found
delete_observations
Remove specific observations from entities
Input:
deletions(array of objects)Each object contains:
entityName(string): Target entityobservations(string[]): Observations to remove
No error if an observation doesn't exist; the response reports how many were deleted
delete_relations
Remove specific relations from the graph, keeping the entities they connect (to remove an entity itself, use
delete_entities)Input:
relations(array of objects)Each object contains:
from(string): Source entity nameto(string): Target entity namerelationType(string): Relationship type
A relation is deleted only when
from,toandrelationTypeall match a stored one exactly; read the storedrelationTypewithopen_nodes(orsearch_nodes) first if unsureNo error if a relation doesn't exist; the response reports how many were deleted
read_graph
Read the entire knowledge graph
Optional input:
entityTypes(string[], at least one): return only entities of these types, and the relations that touch one of themobservationLimit(integer, 0 or more): see below
Returns complete graph structure with all entities and relations
With
observationLimit, each entity carries at most that many observations (the first ones, in the order they were added) and anobservationCountwith its total.observationLimit: 0returns names, types and counts only: a cheap overview of a large graph, from whichopen_nodesreads the entities you need in full
search_nodes
Search for nodes based on query
Input:
query(string, at most 2048 characters; a longer query is rejected)Searches across:
Entity names
Entity types
Observation content
Returns matching entities and their relations
Optional input:
limit(integer, 1 or more): return at most this many matches (the first, in stored order), with the relations that touch themobservationLimit(integer, 0 or more): as forread_graph
open_nodes
Retrieve specific nodes by name
Input:
names(string[])Returns:
Requested entities
Relations between requested entities
Silently skips non-existent nodes
Optional input:
observationLimit(integer, 0 or more), as forread_graph
Resources
knowledge-graph (
memory://knowledge-graph)The full knowledge graph as a readable MCP Resource
MIME type:
application/jsonReturns the same shape as
read_graph(entities and relations)Mutation tools (
create_entities,create_relations,add_observations,delete_entities,delete_observations,delete_relations) emitnotifications/resources/updatedfor this URI, so subscribed clients see live changesHow a client subscribes depends on its protocol version: a 2026-07-28 client names the URI in the
resourceSubscriptionsof itssubscriptions/listenrequest and gets the updates on that stream; a 2025-era client callsresources/subscribe
Protocol versions
The server serves both protocol eras on stdio from the same process. The client's first message picks the era of the connection: a 2026-07-28 client opens with server/discover and sends its protocol version, identity and capabilities with each request, and a 2025-era client opens with the initialize handshake. The tools and the resource are the same on both.
Requirements
Node.js 24 or later, when the server runs through npx or from source.
Usage with Claude Desktop
Setup
Add this to your claude_desktop_config.json:
Docker
{
"mcpServers": {
"memory": {
"command": "docker",
"args": ["run", "-i", "-v", "claude-memory:/app/dist", "--rm", "mcp/memory"]
}
}
}NPX
{
"mcpServers": {
"memory": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-memory"
]
}
}
}On Windows, use cmd /c to launch npx:
{
"mcpServers": {
"memory": {
"command": "cmd",
"args": [
"/c",
"npx",
"-y",
"@modelcontextprotocol/server-memory"
]
}
}
}NPX with custom setting
The server can be configured using the following environment variables:
{
"mcpServers": {
"memory": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-memory"
],
"env": {
"MEMORY_FILE_PATH": "/path/to/custom/memory.jsonl"
}
}
}
}On Windows, use:
{
"mcpServers": {
"memory": {
"command": "cmd",
"args": [
"/c",
"npx",
"-y",
"@modelcontextprotocol/server-memory"
],
"env": {
"MEMORY_FILE_PATH": "/path/to/custom/memory.jsonl"
}
}
}
}MEMORY_FILE_PATH: Path to the memory storage JSONL file (default:memory.jsonlin the server directory). A leading~expands to your home directory; a relative path resolves against the server directory. Set it to an absolute path you own; see Choosing where the graph is stored.
When MEMORY_FILE_PATH is not set and the server directory still holds a legacy memory.json but no memory.jsonl, the server renames memory.json to memory.jsonl at startup. If that rename fails, the server exits with an error naming both paths and the cause, rather than starting on an empty graph; fix the cause (a permission problem, say) and restart, or set MEMORY_FILE_PATH to choose a file explicitly.
Choosing where the graph is stored
Set MEMORY_FILE_PATH to an absolute path you own, such as ~/memory.jsonl, as in the configuration above. The default memory.jsonl sits in the server's own directory, next to its code. Under npx or an npm install, that directory is inside a node_modules tree, which npm manages as its own: reinstalling or updating the server, or clearing the npx cache, can delete the file and the knowledge graph in it. A relative MEMORY_FILE_PATH resolves against that same directory, so it has the same problem.
When the memory file it resolves is inside a
node_modulesdirectory, the server prints a warning on stderr at startup naming the file; most clients show a server's stderr in its log. Move the file to the new path when you set the variable, or the server starts on an empty graph.The directory must already exist: the server creates the memory file, not the directories above it.
The default stays where it is so that existing graphs keep loading. The Docker setup above keeps it in a named volume mounted over
/app/dist, so the graph there survives restarts and draws no warning.
Saves are atomic. Every write tool writes the whole graph to a temporary file in the same directory and renames it over the memory file, so a server stopped or killed mid-save leaves the previous graph intact rather than a half-written file. The file's permission bits are kept across the rename. Writes from several processes are serialized by a lock, described next.
Sharing one memory file between clients
Each MCP client starts its own server process, so two clients using the same MEMORY_FILE_PATH (or both using the default) are two processes writing one file. Every write tool takes an exclusive lock file, <memory file>.lock, next to the memory file while it reads, changes and saves the graph, so writes from different processes take turns and none is lost. The lock file exists only while a write is in progress, so the directory holding the memory file must be writable (it already must be, for the atomic save).
A lock left behind by a server that crashed mid-write is removed automatically: at once if its process is known to have exited on the same machine, otherwise once it has gone 30 seconds without being refreshed (a server holding the lock refreshes it every 15 seconds while it works). Only one waiting server breaks a stale lock at a time, guarded by a momentary
<memory file>.lock.breakfile.A write that cannot get the lock within 60 seconds fails with a tool error rather than overwriting the file.
The lock relies on exclusive file creation, which local filesystems provide; a network filesystem that does not honour it cannot be shared safely this way.
VS Code Installation Instructions
For quick installation, use one of the one-click installation buttons below:
Image: Install with NPX in VS Code Image: Install with NPX in VS Code Insiders
Image: Install with Docker in VS Code Image: Install with Docker in VS Code Insiders
For manual installation, you can configure the MCP server using one of these methods:
Method 1: User Configuration (Recommended)
Add the configuration to your user-level MCP configuration file. Open the Command Palette (Ctrl + Shift + P) and run MCP: Open User Configuration. This will open your user mcp.json file where you can add the server configuration.
Method 2: Workspace Configuration
Alternatively, you can add the configuration to a file called .vscode/mcp.json in your workspace. This will allow you to share the configuration with others.
For more details about MCP configuration in VS Code, see the official VS Code MCP documentation.
NPX
{
"servers": {
"memory": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-memory"
]
}
}
}On Windows, use:
{
"servers": {
"memory": {
"command": "cmd",
"args": [
"/c",
"npx",
"-y",
"@modelcontextprotocol/server-memory"
]
}
}
}Docker
{
"servers": {
"memory": {
"command": "docker",
"args": [
"run",
"-i",
"-v",
"claude-memory:/app/dist",
"--rm",
"mcp/memory"
]
}
}
}System Prompt
The prompt for utilizing memory depends on the use case. Changing the prompt will help the model determine the frequency and types of memories created.
Here is an example prompt for chat personalization. You could use this prompt in the "Custom Instructions" field of a Claude.ai Project.
Follow these steps for each interaction:
1. User Identification:
- You should assume that you are interacting with default_user
- If you have not identified default_user, proactively try to do so.
2. Memory Retrieval:
- Always begin your chat by saying only "Remembering..." and retrieve all relevant information from your knowledge graph
- Always refer to your knowledge graph as your "memory"
3. Memory
- While conversing with the user, be attentive to any new information that falls into these categories:
a) Basic Identity (age, gender, location, job title, education level, etc.)
b) Behaviors (interests, habits, etc.)
c) Preferences (communication style, preferred language, etc.)
d) Goals (goals, targets, aspirations, etc.)
e) Relationships (personal and professional relationships up to 3 degrees of separation)
4. Memory Update:
- If any new information was gathered during the interaction, update your memory as follows:
a) Create entities for recurring organizations, people, and significant events
b) Connect them to the current entities using relations
c) Store facts about them as observationsBuilding
Docker:
docker build -t mcp/memory -f src/memory/Dockerfile . Upgrading a Docker install
The Docker setup mounts the named volume claude-memory over /app/dist, the image's code directory, so the volume holds the server's code (index.js, version.js) next to your memory.jsonl. Docker copies an image's files into a named volume only while the volume is empty. Once the volume holds your graph, a newer image never reaches it: the container keeps running the code from the image that first filled the volume, which may not even start against the newer image's dependencies. Deleting index.js from the volume does not help; it leaves /app/dist with no entry point.
To upgrade, build or pull the new mcp/memory image, quit the MCP clients that start it, then replace the code in the volume with the new image's, keeping memory.jsonl:
docker run --rm -v claude-memory:/volume --user root --entrypoint sh mcp/memory \
-c 'rm -f /volume/*.js && cp /app/dist/*.js /volume/ && chown -R node:node /volume'The volume is mounted at /volume rather than /app/dist, so the image's own /app/dist stays visible to copy from. Only the .js files are replaced; memory.jsonl (or a legacy memory.json) is left as it is. Repeat this after every image update.
The image runs the server as the unprivileged node user, not root, so it must own the volume to save the graph. A volume an older image created, which ran as root, is owned by root, and without the chown above the server fails to save with EACCES. That is why this step runs as --user root and ends by giving the volume to node.
Alternative: keep the graph in a volume of its own
Mounting a volume on a directory of its own and pointing MEMORY_FILE_PATH at it keeps the code out of the volume, so a new image takes effect with no copying step:
{
"mcpServers": {
"memory": {
"command": "docker",
"args": ["run", "-i", "-v", "claude-memory-data:/data", "-e", "MEMORY_FILE_PATH=/data/memory.jsonl", "--rm", "mcp/memory"]
}
}
}To move an existing graph from the claude-memory volume into the new one, quit the MCP clients that start the server, then run:
docker run --rm -v claude-memory:/old -v claude-memory-data:/data \
--entrypoint cp mcp/memory /old/memory.jsonl /data/memory.jsonlIf the old volume holds only a legacy memory.json, copy /old/memory.json to /data/memory.jsonl instead. Once the server has started on the new volume with your graph, you can remove the old volume with docker volume rm claude-memory.
License
This MCP server is licensed under the MIT License. This means you are free to use, modify, and distribute the software, subject to the terms and conditions of the MIT License. For more details, please see the LICENSE file in the project repository.
30 files · 25 not served here
- src/memory/ATTRIBUTION.md
- src/memory/AUTOGINEER-RUNS.md
- src/memory/CHANGELOG.md
- src/memory/Dockerfile (not served here)
- src/memory/Dockerfile.dockerignore (not served here)
- src/memory/LICENSE
- src/memory/README.md
- src/memory/__tests__/atomic-save.test.ts (not served here)
- src/memory/__tests__/create-reporting.test.ts (not served here)
- src/memory/__tests__/entry-point.test.ts (not served here)
- src/memory/__tests__/eras.test.ts (not served here)
- src/memory/__tests__/extra-fields.test.ts (not served here)
- src/memory/__tests__/file-lock.test.ts (not served here)
- src/memory/__tests__/file-path.test.ts (not served here)
- src/memory/__tests__/helpers.ts (not served here)
- src/memory/__tests__/input-descriptions.test.ts (not served here)
- src/memory/__tests__/knowledge-graph.test.ts (not served here)
- src/memory/__tests__/persistence.test.ts (not served here)
- src/memory/__tests__/read-options.test.ts (not served here)
- src/memory/__tests__/resource.test.ts (not served here)
- src/memory/__tests__/server-version.test.ts (not served here)
- src/memory/__tests__/stdio-smoke.test.ts (not served here)
- src/memory/__tests__/tool-descriptions.test.ts (not served here)
- src/memory/__tests__/tools.test.ts (not served here)
- src/memory/index.ts (not served here)
- src/memory/package.json (not served here)
- src/memory/tsconfig.json (not served here)
- src/memory/tsconfig.test.json (not served here)
- src/memory/version.ts (not served here)
- src/memory/vitest.config.ts (not served here)
Advantages
- Supports atomic saves to prevent data corruption during interruptions. evidence: src/memory/README.md
- Includes a locking mechanism to allow safe sharing of the memory file between multiple client processes. evidence: src/memory/README.md
Limitations
- The server does not automatically create the directory for the memory file; the directory must exist beforehand. evidence: src/memory/README.md
- The memory file cannot be shared safely across network filesystems that do not support exclusive file creation. evidence: src/memory/README.md
Security
Risk level: Medium risk
This brain runs
MCP servers (6)
src/memory/README.md(memory):docker run -i -v claude-memory:/app/dist --rm mcp/memorysrc/memory/README.md(memory):npx -y @modelcontextprotocol/server-memorysrc/memory/README.md(memory):cmd /c npx -y @modelcontextprotocol/server-memorysrc/memory/README.md(memory):npx -y @modelcontextprotocol/server-memorysrc/memory/README.md(memory):cmd /c npx -y @modelcontextprotocol/server-memorysrc/memory/README.md(memory):docker run -i -v claude-memory-data:/data -e MEMORY_FILE_PATH=/data/memory.jsonl --rm mcp/memory
Package scripts (1)
src/memory/package.json(prepare):npm run build
- Medium risk: runs-mcp-server-unpinned-runner (src/memory/README.md:178)
- Medium risk: runs-mcp-server-unpinned-runner (src/memory/README.md:214)
Attribution and licence
- Created by
- Model Context Protocol
- Declared authors
- Model Context Protocol a Series of LF Projects, LLC. (declared in src/memory/package.json)
- Publisher
- Model Context Protocol (Official Model Context Protocol project)
- Source
- modelcontextprotocol/servers · src/memory · commit e1dc4b1
- Licence
- Apache License 2.0 (files served here)
- src/memory/LICENSE (added by AutoGineer from LICENSE)
- src/memory/ATTRIBUTION.md (written by AutoGineer)
- Synced
AutoGineer is not affiliated with or endorsed by Model Context Protocol.
Install from source
25 of its files are not served here, so there is no ZIP. modelcontextprotocol/servers at e1dc4b1