create_relations silently creates dangling edges to nonexistent entities in @modelcontextprotocol/server-memory
Reproduced failure: dangling relations in @modelcontextprotocol/server-memory v0.6.3
Surface: @modelcontextprotocol/server-memory v0.6.3 via npx -y @modelcontextprotocol/server-memory (stdio)
The bug
create_relations accepts relations that reference entities that do not exist in the graph. No error, no warning — the relation is silently persisted. Meanwhile, add_observations correctly rejects nonexistent entity references with "Entity with name X not found".
Repro trace
→ {"jsonrpc":"2.0","id":9,"method":"tools/call","params":{"name":"create_relations","arguments":{"relations":[{"from":"ghost_a","to":"ghost_b","relationType":"haunts"}]}}}
← {"result":{"content":[{"type":"text","text":"[{\"from\":\"ghost_a\",\"to\":\"ghost_b\",\"relationType\":\"haunts\"}]"}],"structuredContent":{"relations":[{"from":"ghost_a","to":"ghost_b","relationType":"haunts"}]}}}
→ {"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"read_graph","arguments":{}}}
← entities: ["tani"] relations: [{"from":"ghost_a","to":"ghost_b","relationType":"haunts"}]The graph now has a relation between ghost_a and ghost_b, but neither entity exists. search_nodes cannot find these orphan relations because it only matches against entity names/types/observations.
Inconsistency with add_observations
→ {"jsonrpc":"2.0","id":10,"method":"tools/call","params":{"name":"add_observations","arguments":{"observations":[{"entityName":"nonexistent_entity","contents":["some observation"]}]}}}
← {"result":{"content":[{"type":"text","text":"Entity with name nonexistent_entity not found"}],"isError":true}}add_observations validates entity existence. create_relations does not.
Impact for agents
Any agent building a knowledge graph incrementally (where entity creation and relation creation happen in separate steps or across sessions) can silently accumulate orphan relations due to typos, race conditions, or stale references. These dangling edges are invisible to search_nodes and can only be found by read_graph + manual inspection.
Additional edge case
create_entities also accepts empty-string names (name: "", entityType: ""), creating phantom entities that are hard to address.