Skip to main content
Glama
Knowledge Graph Memory Server

Knowledge Graph Memory Server

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 identifier

        • entityType (string): Type classification

        • observations (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 (use add_observations to extend an existing entity)

  • create_relations

    • Create multiple new relations between entities

    • Input: relations (array of objects)

      • Each object contains:

        • from (string): Source entity name

        • to (string): Target entity name

        • relationType (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 entity

        • contents (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 entity

        • observations (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 name

        • to (string): Target entity name

        • relationType (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

    • Optional input:

      • entityTypes (string[], at least one): return only entities of these types, and the relations that touch one of them

      • observationLimit (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 an observationCount with its total. observationLimit: 0 returns names, types and counts only: a cheap overview of a large graph, from which open_nodes reads 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 them

      • observationLimit (integer, 0 or more): as for read_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 for read_graph

Resources

  • knowledge-graph (memory://knowledge-graph)

    • The full knowledge graph as a readable MCP Resource

    • MIME type: application/json

    • Returns the same shape as read_graph (entities and relations)

    • Mutation tools (create_entities, create_relations, add_observations, delete_entities, delete_observations, delete_relations) emit notifications/resources/updated for this URI, so subscribed clients see live changes

    • How a client subscribes depends on its protocol version: a 2026-07-28 client names the URI in the resourceSubscriptions of its subscriptions/listen request and gets the updates on that stream; a 2025-era client calls resources/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.jsonl in 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_modules directory, 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.break file.

  • 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:

Install with NPX in VS Code Install with NPX in VS Code Insiders

Install with Docker in VS Code 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 observations

Building

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 tools
add_observationsAdd ObservationsB

Add new observations to existing entities in the knowledge graph

NameRequiredDescriptionDefault
observationsYes

Output Schema

NameRequiredDescription
resultsYes

TDQS

B3.2/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare this is a non-read-only, non-destructive, non-idempotent write, so the safety profile is covered. The description adds the useful constraint that target entities must already exist, but says nothing about duplicate accumulation (relevant given idempotentHint=false) or error behavior for unknown entities.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single efficient sentence with the resource and scope front-loaded. Nothing is wasted, but at ten words it is close to under-specified rather than optimally concise.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

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 mutation tool with an unannotated parameter structure and a non-idempotent flag, the description should at least cover append semantics and the failure mode when the named entity does not exist.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Reported schema description coverage is 0%, and the description contains no parameter guidance at all — nothing about the observations array, its entityName/contents fields, or the fact that observations are appended rather than replaced. The nested schema properties carry some of this, but the description 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.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb + resource: 'Add new observations to existing entities in the knowledge graph.' The qualifier 'existing' implicitly separates it from create_entities, though the sibling is never named explicitly.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is only implied: the tool is for appending observations to entities that already exist. There is no explicit when/when-not guidance or routing to siblings like create_entities (for new entities) or 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.

NameRequiredDescriptionDefault
entitiesYes

Output Schema

NameRequiredDescription
skippedNo
entitiesYes

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only cover the generic write profile (readOnlyHint=false, idempotentHint=false, destructiveHint=false). The description adds genuinely non-obvious behavior: duplicate names within the call or against the graph are skipped rather than erroring, their observations are dropped, and skipped names surface in a `skipped` result field. It does not mention failure modes or auth, keeping it short of a 5.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences, zero padding, front-loaded with the action before the conflict semantics and the sibling pointer. Every clause adds information an agent needs.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

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 the description still usefully flags the `skipped` field. Combined with annotations covering the write profile, the definition is close to complete; only the entity object structure is left to the schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is reported at 0% (the top-level `entities` array is undocumented), so the description has to carry some of the load. It conveys that multiple entities with observations are passed and hints at the duplicate-name semantics, but never describes the entity object's name/entityType/observations shape. Partial compensation only.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

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 distinguishes itself from add_observations, the sibling used for existing entities. An agent can route between create_entities and add_observations without opening either schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Clearly states the alternative for the adjacent case: 'Use add_observations to add observations to an existing entity.' It does not spell out a when-not-to-use clause or contrast with create_relations, but the primary routing decision is covered.

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

NameRequiredDescriptionDefault
relationsYes

Output Schema

NameRequiredDescription
relationsYes

TDQS

B3.2/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=false and destructiveHint=false, so the mutation/safety profile is covered. The description adds one genuinely useful domain convention (relations in active voice) that the annotations do not carry, but it is silent on non-idempotency — whether re-submitting the same relation creates duplicates or errors — which is the key behavioral risk here.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences, front-loaded with the action, with no filler. The active-voice rule is stated tersely, though it arrives as an orphan second sentence rather than being attached to the relationType field it governs.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

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 the safety profile. What remains missing for a batch, non-idempotent graph mutation — duplicate handling, partial-failure semantics, and whether `from`/`to` entities must already exist — is not addressed anywhere.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Top-level schema description coverage is 0% and the description adds no meaning for the single `relations` parameter: it never explains that the argument is an array of {from, to, relationType} objects, nor whether entity names must match existing entities. Only the nested item-level field descriptions in the schema carry any semantics, and the description does not leverage or extend them.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

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 relations") plus the domain scope ("between entities in the knowledge graph"). It is clearly distinguishable in kind from siblings like delete_relations and create_entities, though it never names them explicitly.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is only implied by the verb: call this when adding new relations. There is no statement of when-not to use it, no mention of the create_entities prerequisite, and no routing guidance versus siblings. The "active voice" sentence is a formatting convention rather than 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 EntitiesA
DestructiveIdempotent

Delete multiple entities and their associated relations from the knowledge graph

NameRequiredDescriptionDefault
entityNamesYesAn array of entity names to delete

Output Schema

NameRequiredDescription
messageYes
successYes

TDQS

A3.8/5.0
Behavior4/5

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 structurally. The description adds genuinely new behavioral context: deletion is both batched and cascading, taking associated relations with it. It does not describe partial-failure behavior, which keeps it from a 5.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single sentence that front-loads the action and packs the two salient facts (batch scope, relation cascade) with no filler. Nothing to trim and nothing buried.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

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 annotations carry the destructive/idempotent profile. The cascade is called out, leaving only edge behavior (nonexistent names, partial results) unaddressed.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With one parameter at 100% schema description coverage, the schema already fully documents entityNames. The description only echoes the batch nature ("multiple entities") and adds no format, naming, or matching semantics beyond what the schema states.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description gives a specific verb (Delete) and resource (entities), plus batch scope ("multiple") and the cascade effect ("their associated relations"), which meaningfully separates it from delete_relations and delete_observations. It stops short of explicitly naming a sibling to route against, so it does not reach a 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The scope term "multiple" implies this is the bulk deletion path, but the description never states when to prefer it over delete_relations or how to remove individual entities. Usage is inferred rather than instructed, and no prerequisites or warnings are given.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

delete_observationsDelete ObservationsC
DestructiveIdempotent

Delete specific observations from entities in the knowledge graph

NameRequiredDescriptionDefault
deletionsYes

Output Schema

NameRequiredDescription
messageYes
successYes

TDQS

C2.8/5.0
Behavior2/5

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 fully covered by structured data. The description adds nothing beyond restating the operation: it does not say the deletion is permanent, whether missing observations are silently skipped, or what happens on partial failure across multiple entities.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single, front-loaded sentence with no filler or repetition. It is efficiently sized for the operation, though the brevity reflects under-specification rather than disciplined concision.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool is low-complexity (one parameter) and has an output schema plus destructive/idempotent annotations, so the missing return-value and safety detail is largely covered elsewhere. The remaining real gap is routing guidance among the many sibling mutation tools, which the description leaves unaddressed.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0% at the parameter level, and the description does not compensate by explaining the 'deletions' array shape, batching semantics, or match requirements. Only the nested entityName/observations fields carry schema descriptions, so the description contributes almost no additional parameter meaning.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (delete) and resource (observations belonging to entities), which distinguishes it from delete_entities and delete_relations by the level of granularity. However it does not explicitly name those siblings or contrast scope, so an agent must infer the distinction from the resource noun alone.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No when-to-use guidance, no prerequisites, and no mention of the sibling tools (add_observations to reverse, delete_entities for whole entities). The agent is left to infer timing entirely from the verb and resource.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

delete_relationsDelete RelationsC
DestructiveIdempotent

Delete multiple relations from the knowledge graph

NameRequiredDescriptionDefault
relationsYesAn array of relations to delete

Output Schema

NameRequiredDescription
messageYes
successYes

TDQS

C2.9/5.0
Behavior2/5

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 beyond that: no note on partial failure behavior, whether missing relations are silently ignored, or any auth requirement.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single front-loaded sentence with zero filler; the verb and resource lead. It is efficient, though its brevity borders on under-specification rather than true economy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

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 single parameter is fully documented in the schema. However, for a destructive batch operation the description leaves behavioral and routing questions entirely to annotations.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and the nested relation object's from/to/relationType fields are each documented in the schema, so the description need not compensate. It adds no syntax or format detail beyond the schema, which is the expected baseline.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

Names a specific verb (Delete), resource (relations), batch scope (multiple), and domain (knowledge graph). This distinguishes it from delete_entities and delete_observations, though the description never explicitly contrasts 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.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides no when-to-use guidance, no prerequisites, and no mention of alternatives such as delete_entities or delete_observations for removing other graph elements. The agent must infer usage purely from the name.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

open_nodesOpen NodesB
Read-onlyIdempotent

Open specific nodes in the knowledge graph by their names

NameRequiredDescriptionDefault
namesYesAn array of entity names to retrieve

Output Schema

NameRequiredDescription
entitiesYes
relationsYes

TDQS

B3.2/5.0
Behavior3/5

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, so the safety profile is fully covered. The description adds only the name-based scope, saying nothing about behavior with missing/nonexistent names; with annotations carrying the burden, a baseline 3 is appropriate.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single front-loaded sentence with no filler; nothing is repeated or wasted. It is not padded, though it is arguably too terse to be maximally informative.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return format need not be explained, and the single-param schema is well documented. However, for a tool with close siblings search_nodes and read_graph, the description gives the agent no basis for choosing among them, leaving a real contextual gap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Single parameter with 100% schema description coverage ('An array of entity names to retrieve'), so the schema already carries the semantics. The description's 'by their names' merely echoes this without adding format, batching, or matching-behavior detail, matching the baseline 3 for high schema coverage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a verb ('Open') and resource ('specific nodes in the knowledge graph') scoped by name, which distinguishes it from the broad read_graph and the query-based search_nodes. The verb 'Open' is slightly unconventional for a retrieval operation, but the schema's 'retrieve' wording and the name-scoped phrasing make the intent discernible.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No explicit when-to-use guidance or named alternatives, even though the sibling set (search_nodes, read_graph) makes the selection question real. The agent must infer that you call this only when you already know the entity names.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

read_graphRead GraphA
Read-onlyIdempotent

Read the entire knowledge graph

NameRequiredDescriptionDefault

No parameters

Output Schema

NameRequiredDescription
entitiesYes
relationsYes

TDQS

A3.7/5.0
Behavior3/5

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 by structured data. The description's contribution is the 'entire' scope, which warns that the whole graph is returned (potentially large), but it says nothing about size, performance, or pagination.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single five-word sentence that front-loads the verb and scope with zero filler. Nothing could be removed without losing meaning.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a no-parameter, read-only tool with an output schema (so return values need not be described) and full annotation coverage, the description is nearly sufficient. The only missing piece is a note on expected payload size or when to prefer a scoped sibling.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool takes zero parameters, so the baseline is 4. There is nothing for the description to disambiguate, and it correctly avoids inventing parameters.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (Read) and resource (knowledge graph) with an explicit scope qualifier (entire), so the agent knows this is a full-graph fetch rather than a filtered one. It does not name search_nodes or open_nodes, but 'entire' implicitly distinguishes it from those subset readers.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is only implied: 'entire' hints that this is for whole-graph retrieval versus the targeted sibling tools (search_nodes, open_nodes), but there is no explicit when-to-use or when-not-to-use statement. The agent must infer the tradeoff itself.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

search_nodesSearch NodesC
Read-onlyIdempotent

Search for nodes in the knowledge graph based on a query

NameRequiredDescriptionDefault
queryYesThe search query to match against entity names, types, and observation content

Output Schema

NameRequiredDescription
entitiesYes
relationsYes

TDQS

C2.9/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint, and openWorldHint=false, so safety and repeatability are covered. The description adds nothing beyond that — no matching behavior (fuzzy vs exact), ranking, or result limit context — so it neither contradicts nor enriches the structured data.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

One short, front-loaded sentence with no filler. It is efficient, though its brevity is also the source of the missing guidance rather than a virtue of tight editing.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return structure need not be explained, and with one fully documented parameter the surface is small. Still, the description omits how search results are matched or ordered, which matters for a search tool with several retrieval siblings.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and the single parameter is fully documented in the schema (matching names, types, and observation content). The description only restates that a query drives the search, adding no syntax or format detail. Baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('Search for nodes in the knowledge graph') with the query basis made explicit. However, it offers no differentiation from siblings like open_nodes or read_graph, so an agent cannot tell from the description alone which retrieval tool fits which situation.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no guidance on when to use search over alternatives such as open_nodes (direct lookup) or read_graph (full dump). No exclusions or preconditions are stated; the agent must infer the use case.

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.

  1. 9 tool updatesv2.0.0
    • Changedadd_observations2 fields changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • changedOutput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
    • Changedcreate_entities2 fields changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • changedOutput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
    • Changedcreate_relations2 fields changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • changedOutput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
    • Changeddelete_entities2 fields changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • changedOutput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
    • Changeddelete_observations2 fields changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • changedOutput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
    • Changeddelete_relations2 fields changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • changedOutput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
    • Changedopen_nodes2 fields changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • changedOutput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
    • Changedread_graph2 fields changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • changedOutput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
    • Changedsearch_nodes2 fields changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • changedOutput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
  2. 9 tool updates
    • Changedadd_observations2 fields changed
      • addedInput schema / $schema
        Added value: +"http://json-schema.org/draft-07/schema#"
      • changedOutput 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"
        +}
    • Changedcreate_entities2 fields changed
      • addedInput schema / $schema
        Added value: +"http://json-schema.org/draft-07/schema#"
      • changedOutput 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"
        +}
    • Changedcreate_relations2 fields changed
      • addedInput schema / $schema
        Added value: +"http://json-schema.org/draft-07/schema#"
      • changedOutput 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"
        +}
    • Changeddelete_entities2 fields changed
      • addedInput schema / $schema
        Added value: +"http://json-schema.org/draft-07/schema#"
      • changedOutput 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"
        +}
    • Changeddelete_observations2 fields changed
      • addedInput schema / $schema
        Added value: +"http://json-schema.org/draft-07/schema#"
      • changedOutput 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"
        +}
    • Changeddelete_relations2 fields changed
      • addedInput schema / $schema
        Added value: +"http://json-schema.org/draft-07/schema#"
      • changedOutput 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"
        +}
    • Changedopen_nodes2 fields changed
      • addedInput schema / $schema
        Added value: +"http://json-schema.org/draft-07/schema#"
      • changedOutput 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"
        +}
    • Changedread_graph2 fields changed
      • addedInput schema / $schema
        Added value: +"http://json-schema.org/draft-07/schema#"
      • changedOutput 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"
        +}
    • Changedsearch_nodes3 fields changed
      • addedInput schema / $schema
        Added value: +"http://json-schema.org/draft-07/schema#"
      • addedInput schema / properties / query / maxLength
        Added value: +2048
      • changedOutput 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"
        +}
  3. 9 tool updatesv1.0.0
    • First observedadd_observations
    • First observedcreate_entities
    • First observedcreate_relations
    • First observeddelete_entities
    • First observeddelete_observations
    • First observeddelete_relations
    • First observedopen_nodes
    • First observedread_graph
    • First observedsearch_nodes

TDQS

A3.5/5.0

Scored across 9 tools

Disambiguation4/5

Each tool targets a distinct operation on a distinct object type (entities, relations, observations), and descriptions actively disambiguate (create_entities points to add_observations for existing entities). The only mild overlap is among the retrieval trio read_graph/search_nodes/open_nodes, though their query-vs-names-vs-full-graph semantics differ.

Naming Consistency4/5

Names consistently use snake_case verb_noun form (create_entities, delete_relations, search_nodes, open_nodes). The only minor deviation is mixing 'create_' for entities/relations with 'add_' for observations, which is a small vocabulary inconsistency rather than a structural one.

Tool Count5/5

Nine tools is well-scoped for a knowledge graph memory server, covering create/read/delete/search across the three graph primitives without redundancy. Each tool earns its place.

Completeness4/5

The surface covers creation, retrieval, deletion, and search for entities, relations, and observations. The main gap is the absence of true update operations (e.g. renaming an entity or editing an observation), which is only partially mitigated by delete-and-recreate or add_observations.

Maintenance

ActivityActive
ResponsivenessSyncing

Related MCP Connectors

Related MCP Servers