You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
feat(memory): declare idempotentHint on create_entities, create_relations and add_observations - #5349
create_entities, create_relations and add_observations now declare idempotentHint: true, matching the three delete tools. Each already skips what is stored: an existing entity name, an existing relation, an observation the entity already has. So repeating a call with the same arguments has no additional effect on the graph, which is how the spec defines the hint. A repeat returns [], or skipped / empty addedObservations, rather than the items, and that does not break the hint.
The hint holds across repeated identical calls. It says nothing about duplicates inside a single call. That add_observations keeps a content repeated within one call is #5201, a separate PR. Skipping saveGraph on a no-op repeat (today the file is rewritten with identical content) is out of scope here.
Server Details
Server: memory
Changed: the annotations of three tools (idempotentHint false → true). No change to behavior, schemas or descriptions.
Motivation and Context
See #5153. The annotations under-reported what the tools do, so a client could not tell they are safe to repeat. (The spec still tells clients not to make decisions from an untrusted server's annotations alone.)
How Has This Been Tested?
Unit / protocol tests. In src/memory/__tests__/tools.test.ts, the writeAnnotations fixture now expects idempotentHint: true, and the lists the nine tools with their schemas and annotations test pins it. A new test, changes nothing when a write tool is repeated with the same arguments (#5153), runs each of the three write calls twice through an SDK client and checks that the graph after the repeat equals the graph after the first round. npm run local:gate exits 0.
Inspector CLI (@modelcontextprotocol/inspector@2.12.0 --cli node src/memory/dist/index.js -e MEMORY_FILE_PATH=<tmp>), run with both --protocol-era legacy (2025-11-25) and --protocol-era modern (2026-07-28). Both eras gave identical output:
tools/list → before (v2/main): idempotentHint: false on all three. After:
create_entities with Alice, twice → {"entities":[Alice]}, then {"entities":[],"skipped":["Alice"]}
add_observationsplays chess on Alice, twice → addedObservations:["plays chess"], then addedObservations:[]
read_graph → Alice with ["likes tea","plays chess"] exactly once each
LLM client (Claude Code claude -p, with only this build's memory server configured). Prompt: "create an entity Alice (person) with observation 'likes tea'. Then add the observation 'plays chess' to Alice. Then perform exactly the same create_entities call and the same add_observations call a second time. Finally read the graph." The model made all five calls. The repeats returned {"entities":[],"skipped":["Alice"]} and {"results":[{"entityName":"Alice","addedObservations":[]}]}, and its summary was: "Both repeated calls changed nothing, so the graph ends up with Alice and exactly two observations." The graph file held one Alice line with the two observations. (Claude Code does not show annotations to the model, so the hint itself comes from the Inspector tools/list above.)
Breaking Changes
None. No client configuration changes.
Types of changes
Bug fix (non-breaking change which fixes an issue)
New feature (non-breaking change which adds functionality)
Breaking change (fix or feature that would cause existing functionality to change)
Documentation update
Checklist
I have read the MCP Protocol Documentation (ToolAnnotations: idempotentHint is defined by repeated calls having no additional effect on the environment)
My changes follow MCP security best practices
I have updated the server's README accordingly (not applicable: the README does not state tool annotations)
I have added a changeset (npm run changeset) if this changes what a TypeScript server publishes (.changeset/memory-5153-idempotent-write-hints.md, patch)
I have tested this with an LLM client
My code follows the repository's style guidelines
New and existing tests pass locally
I have added appropriate error handling (not applicable: annotations only, no new code paths)
I have documented all environment variables and configuration options (not applicable: none added)
create_entities, create_relations and add_observations already skip what
is stored, so repeating a call with the same arguments has no additional
effect on the graph. Declare idempotentHint: true, as the delete tools
do, update the annotations fixture, and add a protocol-level test that a
repeat of each call leaves the graph unchanged.
Closes#5153
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
This PR addresses #5153 by declaring the memory server’s three additive write tools idempotent, matching their existing behavior without changing schemas or runtime logic.
Changes:
Sets idempotentHint: true on create_entities, create_relations, and add_observations.
Updates annotation expectations and adds a protocol-level repeated-call test.
Adds a patch changeset for the memory package.
File
Description
src/memory/index.ts
Enables the idempotency hint on three write tools.
src/memory/__tests__/tools.test.ts
Updates expected annotations and tests repeated calls.
.changeset/memory-5153-idempotent-write-hints.md
Records the annotation changes for a patch release.
A single comparison after all three repeats could miss a repeat that
changed the graph if a later repeat undid it. Compare before and after
each repeat, and assert the initial calls succeeded.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
tools.test.ts repeated-call test: one comparison after all three repeats could hide a repeat that changed the graph if a later repeat undid the change. Fixed in a41492e. The initial calls now assert success, and the graph is compared before and after each repeat on its own. Gate green.
The reason will be displayed to describe this comment to others. Learn more.
🔵 Needs a closer look
The new idempotent hints are missing from the memory server README, despite the documentation requirement for tool changes.
No open issues 🎉
1 previously missed issue
In code that hasn't changed since last review
Document idempotent hints for graph mutation tools
src/memory/index.ts:856
The new client-visible hints are not documented in src/memory/README.md, although AGENTS.md:421–422 requires a server README update when its tools change. Add a short note that create_entities, create_relations, and add_observations now advertise idempotentHint: true because identical repeated calls leave the graph unchanged.
Copilot round 2 (on a41492e): no open issues. The round-1 finding is listed as resolved.
Declined: "Document idempotent hints for graph mutation tools" (previously missed, README; no thread, so answered here).src/memory/README.md documents each tool's inputs and behavior. It states no tool's annotations, the delete tools' idempotentHint: true included, and the behavior these hints describe (an existing entity, relation or observation is skipped) is already documented there. This PR leaves those behaviors alone, so the README is still accurate. Documenting annotations for every tool would be a new README section beyond what memory: create_entities, create_relations and add_observations could declare idempotentHint: true #5153 asks for. The checklist marks the README item "not applicable" for that reason.
That makes the round "out of scope only", so the review loop stops here.
…rs#5153
The maintainers merged modelcontextprotocol/servers#5349 into v2/main on
2026-10-29, declaring idempotentHint: true on create_entities,
create_relations and add_observations, and closed the issue as completed.
The in-call duplicate noted in the review was fixed separately (#5357).
The audit itself still describes the pinned commit bbb701e.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #5153
Description
create_entities,create_relationsandadd_observationsnow declareidempotentHint: true, matching the three delete tools. Each already skips what is stored: an existing entity name, an existing relation, an observation the entity already has. So repeating a call with the same arguments has no additional effect on the graph, which is how the spec defines the hint. A repeat returns[], orskipped/ emptyaddedObservations, rather than the items, and that does not break the hint.The hint holds across repeated identical calls. It says nothing about duplicates inside a single call. That
add_observationskeeps a content repeated within one call is #5201, a separate PR. SkippingsaveGraphon a no-op repeat (today the file is rewritten with identical content) is out of scope here.Server Details
annotationsof three tools (idempotentHintfalse → true). No change to behavior, schemas or descriptions.Motivation and Context
See #5153. The annotations under-reported what the tools do, so a client could not tell they are safe to repeat. (The spec still tells clients not to make decisions from an untrusted server's annotations alone.)
How Has This Been Tested?
Unit / protocol tests. In
src/memory/__tests__/tools.test.ts, thewriteAnnotationsfixture now expectsidempotentHint: true, and thelists the nine tools with their schemas and annotationstest pins it. A new test,changes nothing when a write tool is repeated with the same arguments (#5153), runs each of the three write calls twice through an SDK client and checks that the graph after the repeat equals the graph after the first round.npm run local:gateexits 0.Inspector CLI (
@modelcontextprotocol/inspector@2.12.0 --cli node src/memory/dist/index.js -e MEMORY_FILE_PATH=<tmp>), run with both--protocol-era legacy(2025-11-25) and--protocol-era modern(2026-07-28). Both eras gave identical output:tools/list→ before (v2/main):idempotentHint: falseon all three. After:create_entitieswith Alice, twice →{"entities":[Alice]}, then{"entities":[],"skipped":["Alice"]}add_observationsplays chesson Alice, twice →addedObservations:["plays chess"], thenaddedObservations:[]read_graph→ Alice with["likes tea","plays chess"]exactly once eachLLM client (Claude Code
claude -p, with only this build's memory server configured). Prompt: "create an entity Alice (person) with observation 'likes tea'. Then add the observation 'plays chess' to Alice. Then perform exactly the same create_entities call and the same add_observations call a second time. Finally read the graph." The model made all five calls. The repeats returned{"entities":[],"skipped":["Alice"]}and{"results":[{"entityName":"Alice","addedObservations":[]}]}, and its summary was: "Both repeated calls changed nothing, so the graph ends up with Alice and exactly two observations." The graph file held one Alice line with the two observations. (Claude Code does not show annotations to the model, so the hint itself comes from the Inspectortools/listabove.)Breaking Changes
None. No client configuration changes.
Types of changes
Checklist
idempotentHintis defined by repeated calls having no additional effect on the environment)npm run changeset) if this changes what a TypeScript server publishes (.changeset/memory-5153-idempotent-write-hints.md, patch)Additional context
Part of the memory v2.3.0 tracker #5273.
🤖 Generated with Claude Code