Repository navigation
Description
Which server?
memory (@modelcontextprotocol/server-memory)
Protocol era
Modern (2026-07-28)
MCP client
No response
The problem
This is a characterization proposal, not a bug report. The unreadable-line preservation cases from #4885 pin that a schema-invalid record is skipped on read and written back verbatim on save — deliberately, per the comment at src/memory/index.ts:440-444, so data is never silently dropped. What is not pinned is the consequence: because the record does not exist in the graph, deleting it by name is a no-op, so the record persists forever and no tool surface can remediate it — only a text editor can. Pinning that consequence makes the state of affairs explicit, and if a remediation path is ever added, this test is the one that visibly changes.
Case
Write a file with one valid entity line and one schema-invalid entity line (missing entityType). Confirm the invalid record is invisible in readGraph. Call deleteEntities(["Broken"]) — it completes without error. Trigger an unrelated save. Assert the invalid line is still in the file verbatim, and the graph shows only the valid records. Mechanism: loadGraphWithUnreadable (index.ts:442-502) holds unreadable lines apart and saveGraph (:558) writes them back; deletion acts only on graph entities.
Solution you have in mind (optional)
Proposed test
For the ghost-line describe in src/memory/__tests__/knowledge-graph.test.ts:
it("cannot remove a schema-invalid record through any tool", async () => {
const ghost = JSON.stringify({
type: "entity",
name: "Broken",
observations: ["missing entityType"],
});
const lines = [
JSON.stringify({
type: "entity",
name: "Alice",
entityType: "person",
observations: [],
}),
ghost,
];
await fs.writeFile(testFilePath, lines.join("\n") + "\n");
const manager = new KnowledgeGraphManager(testFilePath);
const before = await manager.readGraph();
expect(before.entities.map((e) => e.name)).toEqual(["Alice"]);
await manager.deleteEntities(["Broken"]);
await manager.createEntities([
{ name: "Carol", entityType: "person", observations: [] },
]);
const saved = (await fs.readFile(testFilePath, "utf-8")).split("\n");
expect(saved).toContain(ghost);
const after = await manager.readGraph();
expect(after.entities.map((e) => e.name)).toEqual(["Alice", "Carol"]);
});Which MCP feature does it demonstrate? (optional)
No response
Alternatives or workarounds you have tried
Closest existing issue is #4885, which is the origin of the preservation behaviour itself — this proposal pins its consequence and is not a duplicate. No tool surface can remove such a record today; only a text editor can.
Already built it locally?
Verification
Ran against a byte-identical copy of v2/main @ 6cfff62: passed (with the expected "Skipping invalid entity" log on stderr). Full memory suite: 241 passed + 1 skipped. Framed as characterization of the current contract — it asserts today's behaviour, and takes no position on whether a remediation tool should exist; that call is the maintainers'.
Prompt used
"In src/memory's knowledge-graph tests, the unreadable-line preservation cases (#4885) pin that an invalid record is skipped on read and written back on save. Add the consequence case: write a file with one valid entity and one schema-invalid entity line, delete the invalid record BY NAME, trigger an unrelated save, and assert the invalid line is still in the file verbatim and the graph shows only valid records. Frame it as characterization of the current contract — no tool can remediate such a record today; only a text editor can."
Before you submit
- I searched existing issues and this is not a duplicate.
- This is a request for this repository or one of its servers, not a new server, the MCP specification or an SDK.
Activity