Knowledge Graph Memory Server
The Knowledge Graph Memory Server provides persistent memory for Claude using a local knowledge graph, enabling memory across chats. With this server, you can:
Create entities: Add nodes with unique names, types, and observations
Create relations: Define directed relationships between entities
Add observations: Append new facts to existing entities
Delete entities: Remove nodes and their associated relations
Delete observations: Remove specific facts from entities
Delete relations: Remove specific connections between entities
Read graph: Retrieve the entire knowledge graph structure
Search nodes: Find entities by querying names, types, or observation content
Open nodes: Retrieve specific entities and their relations by name
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Knowledge Graph Memory Serverremember that I'm allergic to peanuts and prefer video calls over meetings"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
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"
]
}Related MCP server: Loc Knowledge Graph Memory Server
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 entities and their relations
Input:
entityNames(string[])Cascading deletion of associated relations
No 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
Input:
relations(array of objects)Each object contains:
from(string): Source entity nameto(string): Target entity namerelationType(string): Relationship type
No error if a relation doesn't exist; the response reports how many were deleted
read_graph
Read the entire knowledge graph
No input required
Returns complete graph structure with all entities and relations
search_nodes
Search for nodes based on query
Input:
query(string)Searches across:
Entity names
Entity types
Observation content
Returns matching entities and their relations
open_nodes
Retrieve specific nodes by name
Input:
names(string[])Returns:
Requested entities
Relations between requested entities
Silently skips non-existent nodes
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 changes
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)
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:
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 . For Awareness: a prior mcp/memory volume contains an index.js file that could be overwritten by the new container. If you are using a docker volume for storage, delete the old docker volume's index.js file before starting the new container.
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.
Available Tools
9 toolsadd_observationsAdd ObservationsB
Add new observations to existing entities in the knowledge graph
| Name | Required | Description | Default |
|---|---|---|---|
| observations | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| results | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations cover the safety profile (readOnlyHint=false, destructiveHint=false, idempotentHint=false, openWorldHint=false), so the description need not restate that this is a non-destructive write. It adds one piece of context beyond the annotations - additions target existing entities - but stays silent on whether duplicates are appended or deduplicated, which matters given idempotentHint=false, and on failure behavior for unknown entity names.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single front-loaded sentence with no filler. It is appropriately sized for the operation, though the brevity doubles as under-specification rather than pure economy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be explained. However, for a non-idempotent mutation with an undocumented nested parameter shape, the description should say more about duplicate handling, entity-not-found behavior, and batch semantics to be complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0% at the top level; the sole 'observations' parameter is an array of objects with no description, and the description does not explain its structure or the entityName/contents pairing. The schema at least documents the nested fields, but the description does nothing to compensate for the coverage gap.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Clear verb+resource: adds observation contents to entities in the knowledge graph. It also constrains scope to 'existing entities.' It does not explicitly contrast itself with siblings like create_entities or delete_observations, but the resource overlap is small enough to be inferable.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The phrase 'existing entities' implies a precondition (the entity must already exist) but never states it as a rule, nor what to do otherwise. No alternative is named, so an agent must infer that create_entities is for new entities and delete_observations for removal.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_entitiesCreate EntitiesA
Create multiple new entities in the knowledge graph. An entity whose name already exists, or repeats an earlier entity in the same call, is skipped and its observations are not added; the result lists the skipped names in skipped. Use add_observations to add observations to an existing entity.
| Name | Required | Description | Default |
|---|---|---|---|
| entities | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| skipped | No | |
| entities | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (not read-only, not destructive, not idempotent, closed world). The description goes further by disclosing the duplicate-skip semantics and that skipped names are reported in the `skipped` result field, which is real behavioral context not present in the annotations. It does not explain permission requirements or the effect on relations, leaving some room.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tightly packed sentences: purpose first, then the duplicate-handling rule, then the alternative tool. No filler, and the most decision-relevant information is front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return-value detail is not required, yet the description helpfully names the `skipped` field. Combined with annotations covering the write profile, an agent has enough to call it correctly; only the entity payload shape is left entirely to the schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is reported at 0%, so the description must carry more weight than it does. It adds the crucial uniqueness constraint on entity names and clarifies that observations attach to the entity, but it never explains the entity object's fields (name/entityType/observations) or their expected format. Baseline 3 for a single top-level parameter with partial compensation.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Create multiple new entities in the knowledge graph') and explicitly contrasts itself with the sibling add_observations. An agent can distinguish it from create_relations or add_observations without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The final sentence routes the agent to add_observations for adding observations to an existing entity, which is genuine when-to-use guidance. It stops short of stating an explicit exclusion (e.g. 'do not use this to modify existing entities'), but the context is clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_relationsCreate RelationsB
Create multiple new relations between entities in the knowledge graph. Relations should be in active voice
| Name | Required | Description | Default |
|---|---|---|---|
| relations | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| relations | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare the safety profile (non-read-only, non-destructive, non-idempotent, closed-world), so the description only needs to add context. It adds the bulk-creation and active-voice convention, but says nothing about what happens on partial failure, duplicates, or missing entities — relevant given idempotentHint=false.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences, scope front-loaded, no filler. Minor looseness in the trailing convention sentence, but nothing wasted.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be explained. However, dependencies (entities must pre-exist), duplicate handling, and batch failure behavior are unaddressed for a non-idempotent write tool, leaving the agent to guess.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage of the top-level parameter is 0% (the nested from/to/relationType fields do carry descriptions). The active-voice note adds useful meaning for relationType formatting, but the description never explains the array-of-objects shape or batch semantics beyond what the schema shows.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (create) and resource (relations between entities in the knowledge graph), plus the bulk nature ('multiple'). It is distinguishable from create_entities/add_observations by resource, though it never explicitly contrasts itself with those siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No when-to-use guidance, no alternative named, and no prerequisites such as whether the referenced entities must already exist. 'Relations should be in active voice' is a content convention, not invocation guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
delete_entitiesDelete EntitiesBDestructiveIdempotent
Delete multiple entities and their associated relations from the knowledge graph
| Name | Required | Description | Default |
|---|---|---|---|
| entityNames | Yes | An array of entity names to delete |
Output Schema
| Name | Required | Description |
|---|---|---|
| message | Yes | |
| success | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true, idempotentHint=true and readOnlyHint=false, so the safety profile is covered. The description adds the non-obvious destruction scope — that associated relations are removed too — which is exactly the kind of context annotations cannot convey. It still omits permission requirements and behavior for non-existent entity names.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single sentence with zero filler, and the resource plus cascade behavior are front-loaded. It is efficient, though arguably truncated given the destructive bulk nature of the operation.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The output schema exists, so return values need no explanation, and the cascade is disclosed. Missing are the failure semantics an agent needs for a destructive bulk delete — what happens when some entity names don't exist, and whether the operation is irreversible/requires confirmation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
One parameter at 100% schema description coverage ('An array of entity names to delete'), so the schema already does the work. The description adds no batching limits, name-matching semantics, or partial-failure behavior, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (delete) and resource (entities) plus a scope qualifier (multiple) and the cascade ('their associated relations'). It implicitly separates it from delete_relations and delete_observations, but never names those siblings, so the distinction requires inference.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No when-to-use guidance, no when-not-to-use, no mention of alternatives such as delete_relations for removing only the relationships. The agent must infer selection from the sibling names alone.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
delete_observationsDelete ObservationsCDestructiveIdempotent
Delete specific observations from entities in the knowledge graph
| Name | Required | Description | Default |
|---|---|---|---|
| deletions | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| message | Yes | |
| success | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true, idempotentHint=true, and readOnlyHint=false, so the safety profile is covered. The description adds nothing behavioral beyond this: it does not say whether deleting all observations removes the entity, how unmatched observations or entity names are handled, or what permissions are required for a destructive mutation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single tight sentence with the verb and scope front-loaded and no filler. It is efficient, though its brevity is also what leaves the guidance gaps noted elsewhere.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a destructive, multi-target mutation with 0% schema coverage and nested batch input, the description is too thin: it omits error/idempotency behavior (does re-deleting a missing observation fail?), permission requirements, and how batch entries are processed. The existing output schema covers return values, but the invocation semantics remain under-documented.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0% at the top level; the only parameter, 'deletions', is an array-of-objects whose grouping semantics (multiple entity/observation pairs in one call) are never explained in the description. The phrase 'specific observations from entities' only loosely hints at the entityName+observations shape already present in the schema, so it does not compensate for the coverage gap.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (Delete) and a specific resource (observations) scoped to entities in the knowledge graph, which cleanly separates it from delete_entities and delete_relations. It stops short of explicitly naming those siblings or contrasting scope, but an agent can infer the distinction from the resource noun.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no guidance on when to choose this over delete_entities, delete_relations, or add_observations. Prerequisites (entity must already exist, observations must be attached) and the alternative of overwriting via add_observations are never mentioned.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
delete_relationsDelete RelationsBDestructiveIdempotent
Delete multiple relations from the knowledge graph
| Name | Required | Description | Default |
|---|---|---|---|
| relations | Yes | An array of relations to delete |
Output Schema
| Name | Required | Description |
|---|---|---|
| message | Yes | |
| success | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true, idempotentHint=true, and readOnlyHint=false, so the safety profile is covered. The description adds the useful fact that this operates in batch ('multiple') and targets the knowledge graph, but says nothing about irreversibility consequences, permission requirements, or whether missing relations cause errors. With annotations carrying the safety burden, this is adequate but thin.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single efficient sentence with the verb and scope front-loaded and no filler. It is appropriately sized for a one-parameter tool, though it is so terse that it verges on under-specification rather than optimized conciseness.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists so return values need not be explained, and annotations cover safety. However, for a destructive, non-readonly mutation, the description omits any caveat about unrecoverable deletion or partial-failure behavior across a batch, leaving a real gap for an agent deciding whether to call it.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and the single nested parameter's fields (from, to, relationType) are all documented in the schema. The description only echoes the batch nature of the array and adds no format or matching semantics, so baseline 3 applies since the schema does the heavy lifting.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb (delete) plus resource (relations) and notes batch semantics ('multiple'), which distinguishes it from siblings like delete_entities and delete_observations. It does not explicitly name those alternatives, but the resource noun is unambiguous enough for an agent to route correctly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no guidance on when to use this tool instead of delete_entities/delete_observations, no mention of prerequisites, and no note about what happens when a specified relation does not exist. The agent must infer usage purely from the name and resource.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
open_nodesOpen NodesARead-onlyIdempotent
Open specific nodes in the knowledge graph by their names
| Name | Required | Description | Default |
|---|---|---|---|
| names | Yes | An array of entity names to retrieve |
Output Schema
| Name | Required | Description |
|---|---|---|
| entities | Yes | |
| relations | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, destructiveHint=false and openWorldHint=false, fully covering the safety profile. The description adds nothing beyond that profile — no statement about missing names, partial matches, or return behavior — so it earns only baseline credit.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single front-loaded sentence with no filler, correctly sized for a one-parameter tool. It is slightly under-specified rather than padded, which is the only reason it does not score a 5.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present and annotations covering safety and idempotency, the description does not need to explain return values. It is nearly complete for a simple exact-name retrieval, missing only the sibling differentiation needed to fully disambiguate from search_nodes and read_graph.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and the single 'names' parameter is documented in the schema as an array of entity names. The description's 'by their names' merely restates the parameter without adding format, matching, or ambiguity guidance, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (open/retrieve) and resource (nodes) plus the lookup key (names), so the operation is identifiable. However, it never differentiates itself from sibling read tools like search_nodes or read_graph, leaving the agent to infer the distinction from the word 'names' alone.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
'by their names' implicitly signals exact-name lookup as opposed to the fuzzy matching implied by search_nodes, which is a usable usage hint. There is no explicit when-to-use/when-not guidance and no sibling is named as an alternative.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
read_graphRead GraphARead-onlyIdempotent
Read the entire knowledge graph
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| entities | Yes | |
| relations | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations already declare readOnlyHint=true, idempotentHint=true, destructiveHint=false and a closed-world scope, so the safety profile is fully covered. The description adds only the 'entire graph' scope and says nothing about cost, size, or pagination, which is a notable omission for a tool that returns the whole graph.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single front-loaded sentence with no filler; the operation and its scope are stated immediately.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so the description need not explain return values, and the safety semantics come from annotations. The only real gap is the absence of any hint about the volume/cost of reading an entire graph.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so there is nothing for the description to disambiguate; the baseline for a parameterless tool applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('Read') and resource ('the entire knowledge graph'), with 'entire' communicating full-graph scope. This implicitly separates it from the partial-retrieval siblings search_nodes and open_nodes, though none is named explicitly, which keeps it just short of a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no when-to-use guidance and no mention of alternatives, even though search_nodes and open_nodes exist as obvious partial-access siblings. The agent must infer that this is the bulk/whole-graph option purely from the word 'entire'.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_nodesSearch NodesBRead-onlyIdempotent
Search for nodes in the knowledge graph based on a query
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | The search query to match against entity names, types, and observation content |
Output Schema
| Name | Required | Description |
|---|---|---|
| entities | Yes | |
| relations | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, destructiveHint=false and openWorldHint=false, so the safety profile is fully covered and the description only needs to add non-redundant context. It confirms the operation is query-based over the knowledge graph but says nothing about matching semantics (substring vs fuzzy), ranking, or result limits, so it is adequate rather than informative.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
One compact sentence with no filler, and the resource and input are front-loaded. It is efficient but leaves obvious room to add the differentiating clause about when to prefer it over read_graph.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need no explanation, and the annotations cover the safety profile. What is missing is the positioning among the nine sibling graph tools, which matters for a search entry point in a graph API.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and the single 'query' parameter is fully documented in the schema as matching entity names, types, and observation content. The description adds no syntax, format, or matching details beyond that, so the baseline of 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific verb (Search) and resource (nodes in the knowledge graph) with a clear input basis (a query). It does not, however, distinguish this from siblings like read_graph or open_nodes, which also retrieve node data, so the agent cannot tell them apart from the description alone.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no when-to-use guidance and no mention of alternatives such as read_graph (whole graph) or open_nodes (direct lookup by name). The agent must infer from the tool name alone that this is the query-matching retrieval path.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
9 tool updates
- Changed
add_observations2 fields changed- added
Input schema / $schemaAdded value: +"http://json-schema.org/draft-07/schema#" - changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "results": { + "items": { + "additionalProperties": false, + "properties": { + "addedObservations": { + "items": { + "type": "string" + }, + "type": "array" + }, + "entityName": { + "type": "string" + } + }, + "required": [ + "entityName", + "addedObservations" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "results" + ], + "type": "object" +}
- Changed
create_entities2 fields changed- added
Input schema / $schemaAdded value: +"http://json-schema.org/draft-07/schema#" - changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "entities": { + "items": { + "additionalProperties": false, + "properties": { + "entityType": { + "description": "The type of the entity", + "type": "string" + }, + "name": { + "description": "The name of the entity", + "type": "string" + }, + "observations": { + "description": "An array of observation contents associated with the entity", + "items": { + "type": "string" + }, + "type": "array" + } + }, + "required": [ + "name", + "entityType", + "observations" + ], + "type": "object" + }, + "type": "array" + }, + "skipped": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "required": [ + "entities" + ], + "type": "object" +}
- Changed
create_relations2 fields changed- added
Input schema / $schemaAdded value: +"http://json-schema.org/draft-07/schema#" - changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "relations": { + "items": { + "additionalProperties": false, + "properties": { + "from": { + "description": "The name of the entity where the relation starts", + "type": "string" + }, + "relationType": { + "description": "The type of the relation", + "type": "string" + }, + "to": { + "description": "The name of the entity where the relation ends", + "type": "string" + } + }, + "required": [ + "from", + "to", + "relationType" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "relations" + ], + "type": "object" +}
- Changed
delete_entities2 fields changed- added
Input schema / $schemaAdded value: +"http://json-schema.org/draft-07/schema#" - changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "message": { + "type": "string" + }, + "success": { + "type": "boolean" + } + }, + "required": [ + "success", + "message" + ], + "type": "object" +}
- Changed
delete_observations2 fields changed- added
Input schema / $schemaAdded value: +"http://json-schema.org/draft-07/schema#" - changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "message": { + "type": "string" + }, + "success": { + "type": "boolean" + } + }, + "required": [ + "success", + "message" + ], + "type": "object" +}
- Changed
delete_relations2 fields changed- added
Input schema / $schemaAdded value: +"http://json-schema.org/draft-07/schema#" - changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "message": { + "type": "string" + }, + "success": { + "type": "boolean" + } + }, + "required": [ + "success", + "message" + ], + "type": "object" +}
- Changed
open_nodes2 fields changed- added
Input schema / $schemaAdded value: +"http://json-schema.org/draft-07/schema#" - changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "entities": { + "items": { + "additionalProperties": false, + "properties": { + "entityType": { + "description": "The type of the entity", + "type": "string" + }, + "name": { + "description": "The name of the entity", + "type": "string" + }, + "observations": { + "description": "An array of observation contents associated with the entity", + "items": { + "type": "string" + }, + "type": "array" + } + }, + "required": [ + "name", + "entityType", + "observations" + ], + "type": "object" + }, + "type": "array" + }, + "relations": { + "items": { + "additionalProperties": false, + "properties": { + "from": { + "description": "The name of the entity where the relation starts", + "type": "string" + }, + "relationType": { + "description": "The type of the relation", + "type": "string" + }, + "to": { + "description": "The name of the entity where the relation ends", + "type": "string" + } + }, + "required": [ + "from", + "to", + "relationType" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "entities", + "relations" + ], + "type": "object" +}
- Changed
read_graph2 fields changed- added
Input schema / $schemaAdded value: +"http://json-schema.org/draft-07/schema#" - changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "entities": { + "items": { + "additionalProperties": false, + "properties": { + "entityType": { + "description": "The type of the entity", + "type": "string" + }, + "name": { + "description": "The name of the entity", + "type": "string" + }, + "observations": { + "description": "An array of observation contents associated with the entity", + "items": { + "type": "string" + }, + "type": "array" + } + }, + "required": [ + "name", + "entityType", + "observations" + ], + "type": "object" + }, + "type": "array" + }, + "relations": { + "items": { + "additionalProperties": false, + "properties": { + "from": { + "description": "The name of the entity where the relation starts", + "type": "string" + }, + "relationType": { + "description": "The type of the relation", + "type": "string" + }, + "to": { + "description": "The name of the entity where the relation ends", + "type": "string" + } + }, + "required": [ + "from", + "to", + "relationType" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "entities", + "relations" + ], + "type": "object" +}
- Changed
search_nodes3 fields changed- added
Input schema / $schemaAdded value: +"http://json-schema.org/draft-07/schema#" - added
Input schema / properties / query / maxLengthAdded value: +2048 - changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "entities": { + "items": { + "additionalProperties": false, + "properties": { + "entityType": { + "description": "The type of the entity", + "type": "string" + }, + "name": { + "description": "The name of the entity", + "type": "string" + }, + "observations": { + "description": "An array of observation contents associated with the entity", + "items": { + "type": "string" + }, + "type": "array" + } + }, + "required": [ + "name", + "entityType", + "observations" + ], + "type": "object" + }, + "type": "array" + }, + "relations": { + "items": { + "additionalProperties": false, + "properties": { + "from": { + "description": "The name of the entity where the relation starts", + "type": "string" + }, + "relationType": { + "description": "The type of the relation", + "type": "string" + }, + "to": { + "description": "The name of the entity where the relation ends", + "type": "string" + } + }, + "required": [ + "from", + "to", + "relationType" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "entities", + "relations" + ], + "type": "object" +}
9 tool updates
v1.0.0- First observed
add_observations - First observed
create_entities - First observed
create_relations - First observed
delete_entities - First observed
delete_observations - First observed
delete_relations - First observed
open_nodes - First observed
read_graph - First observed
search_nodes
TDQS
Scored across 9 tools
Each tool targets a distinct resource and action: entities, relations, or observations with create/delete/add operations, plus read, search, and open for retrieval. The descriptions clarify boundary cases, such as create_entities skipping existing entities and add_observations handling existing entities.
All names use consistent snake_case with a clear verb_noun pattern: delete_entities, create_relations, add_observations, read_graph, search_nodes, open_nodes. The few variations (add vs create) are semantically appropriate and do not break consistency.
Nine tools is well-scoped for a knowledge graph memory server, covering the essential create, delete, and retrieval operations without redundancy. Every tool appears to earn its place.
The surface covers entity, relation, and observation creation/deletion plus graph read, node search, and node opening. Minor gaps exist, such as no direct update or rename operation, but these can be worked around by deleting and recreating entities or relations.
Maintenance
Related MCP Connectors
- GoMindOAuthcom.gominddb
Persistent knowledge graph for AI agents. Remember, recall, and forget facts.
Persistent memory for AI agents across Claude, ChatGPT and any MCP client.
- TaprootOAuthcom.taproothq
Persistent memory layer for AI tools. Save and recall notes across Claude and other MCP clients.
Personal wiki and memory layer for AI assistants. Persistent, structured memory across sessions.
Related MCP Servers
- AlicenseBqualityFmaintenanceA persistent memory implementation using a local knowledge graph that lets Claude remember information about users across conversations.96MIT
- AlicenseNot gradedqualityDmaintenanceEnables Claude to remember information about users across conversations by storing and retrieving data as entities, relations, and observations in a persistent local knowledge graph.207,413 npm-
- AlicenseNot gradedqualityDmaintenanceEnables Claude to remember information about users across chats using a persistent local knowledge graph that stores entities, relationships, and observations.207,413 npm-
- FlicenseAqualityDmaintenanceEnables Claude to maintain persistent memory across conversations using a local knowledge graph with fuzzy search capabilities, allowing it to remember and recall information about users, relationships, and context.9-