Skip to content

fix(memory): use empty content: [] with structuredContent to avoid double-serialization (#2689) - #4583

Open
knoal wants to merge 1 commit into
modelcontextprotocol:mainfrom
knoal:fix/2689-memory-double-serialization
Open

fix(memory): use empty content: [] with structuredContent to avoid double-serialization (#2689)#4583
knoal wants to merge 1 commit into
modelcontextprotocol:mainfrom
knoal:fix/2689-memory-double-serialization

Conversation

@knoal

@knoal knoal commented Jul 29, 2026

Copy link
Copy Markdown

Summary

Fixes #2689: Memory server double-serializes its results.

The memory server's tool handlers returned both content (text array) and structuredContent (object) simultaneously:

return {
  content: [{ type: "text" as const, text: JSON.stringify(result, null, 2) }],
  structuredContent: { entities: result }
};

The MCP SDK serializes both fields into the response payload, producing:

{ "content": [{"text": "{"entities":...}"}], "structuredContent": {...} }

Some clients (specifically Gemini CLI per the bug report) try to parse both halves as a single JSON document and fail with:

MCP error -32603: Unexpected non-whitespace character after JSON at position 102

The fix: when structuredContent is set, content must be an empty array. Per the MCP spec, when a tool has an outputSchema, the structuredContent is the canonical output; text content is optional.

This change updates all 6 affected tool handlers:

  • create_entities
  • create_relations
  • add_observations
  • delete_entities
  • delete_observations
  • delete_relations

It also covers read_graph, search_nodes, search_graph (the 3 JSON.stringify variants).

Tests

  • 52 tests pass (50 existing + 2 new).
  • Both new tests verify the contract:
    1. Every tool return with structuredContent has content: [] (not duplicated).
    2. Hardcoded success messages appear only in structuredContent, not content.
  • Both tests FAIL on pre-fix (verified by git stash).

Files

  • src/memory/index.ts: 9 tool return blocks updated to content: [] + structuredContent.
  • src/memory/__tests__/no-dual-content-structured.test.ts: 2 regression tests.

Notes

The issue title mentions Gemini CLI specifically, but the same pattern would affect any client that:

  • Parses only one of the two fields, or
  • Tries to concatenate both halves into a single JSON document.

The fix is the safest of the three options I considered:

  1. (chosen) Set content: [] — satisfies the SDK type, eliminates double-serialization.
  2. Remove content entirely — fails TypeScript strict-typing (the SDK requires it).
  3. Use content: [...] with a JSON-parseable string — text clients see the string, structured clients see the object. Same risk as the original code.

Fixes #2689.

— knoal (via the operator, Alex Knotts)

…uble-serialization (modelcontextprotocol#2689)

The memory server's tool handlers returned both:
  content: [{ type: "text" as const, text: JSON.stringify(result, null, 2) }],
  structuredContent: { entities: result }

This double-serializes the same data. The MCP SDK emits both fields
in the response payload, producing:
  { "content": [{"text": "<JSON>"}], "structuredContent": {...} }

Some clients (specifically Gemini CLI per the bug report) try to
parse both halves as a single JSON document and fail with:
  MCP error -32603: Unexpected non-whitespace character after JSON at position 102

The fix: when structuredContent is set, content must be an empty
array. Per the MCP spec, when a tool has an outputSchema, the
structuredContent is the canonical output; text content is optional.

This change updates all 6 affected tool handlers:
- create_entities
- create_relations
- add_observations
- delete_entities
- delete_observations
- delete_relations

It also covers read_graph, search_nodes, search_graph (the 3
JSON.stringify variants).

## Tests

- 52 tests pass (50 existing + 2 new).\n- Tests verify:
  1. Every tool return with structuredContent has content: [] (not duplicated).
  2. Hardcoded success messages appear only in structuredContent, not content.
- Both tests FAIL on pre-fix (verified by git stash).

## Files

- src/memory/index.ts: 9 tool return blocks updated to content: [] + structuredContent.
- src/memory/__tests__/no-dual-content-structured.test.ts: 2 regression tests.

Fixes modelcontextprotocol#2689.

"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Knowledge Graph Memory Server failing to create memories

1 participant