Why the MCP Memory Server Uses JSONL Format: Architecture and Performance Benefits

The MCP Memory server persists knowledge-graph data in JSON Lines (JSONL) format to enable efficient append-only writes, streaming-friendly reads, and seamless backward-compatible migration from legacy flat JSON storage.

The modelcontextprotocol/servers repository implements a persistent knowledge graph using the JSON Lines (JSONL) format as its native storage protocol. According to the source code in src/memory/index.ts, this line-oriented approach optimizes I/O performance for constantly growing entity-relationship graphs while preserving human readability and migration flexibility.

Append-Only Architecture Eliminates Full-File Rewrites

The primary advantage of JSONL format is append-only, line-oriented I/O. In src/memory/index.ts, the saveGraph implementation serializes each entity and relation as a self-contained JSON object, then joins the array with "\n" before writing【src/memory/index.ts‑L116】.

This design allows the server to write new knowledge-graph records without rewriting the entire file history. Because each line represents an independent JSON object, the storage layer can efficiently grow the graph on disk using standard file-system append operations rather than serializing and flushing massive JSON arrays for every update.

Streaming-Friendly Reads for Large-Scale Graphs

JSONL format enables streaming-friendly reads that minimize memory overhead. When loading data, the loadGraph method reads the file content, splits on newlines using data.split("\n"), and parses each line independently via JSON.parse【src/memory/index.ts‑L78】.

This approach scales to very large graphs because the server never holds the raw text of the entire file in memory simultaneously. Instead, it processes the file line-by-line, keeping only the parsed objects in the working memory. This streaming paradigm prevents the memory exhaustion issues common with large monolithic JSON files.

Backward-Compatible Migration from Legacy JSON

The server maintains backward-compatibility through automatic migration logic. Earlier versions stored data in a single large memory.json file containing a JSON array. On startup, the ensureMemoryFilePath function detects this legacy file, renames it to memory.jsonl, and logs the migration【src/memory/index.ts‑L39】.

This migration preserves existing user data while transitioning to the more performant JSONL format. The detection and rename operation happens automatically, ensuring that upgrades from older server versions remain seamless and non-destructive.

Configuring the JSONL Storage Path

The JSONL file path is configurable via the MEMORY_FILE_PATH environment variable. The ensureMemoryFilePath function resolves process.env.MEMORY_FILE_PATH at startup, defaulting to memory.jsonl in the working directory【src/memory/index.ts‑L20】.

The project's README explicitly documents this variable as pointing to a "JSONL file (default: memory.jsonl)"【src/memory/README.md‑L184】, confirming that the format is a deliberate part of the public API contract.

Setting a Custom JSONL Path

export MEMORY_FILE_PATH=/my/data/custom-memory.jsonl
npx -y @modelcontextprotocol/server-memory

Appending Entities to the JSONL File

Each entity creation appends a new JSON line to the file:

await knowledgeGraphManager.createEntities([
  { name: "Alice", entityType: "person", observations: ["likes coffee"] },
  { name: "Bob",   entityType: "person", observations: [] }
]);

Resulting memory.jsonl content:

{"type":"entity","name":"Alice","entityType":"person","observations":["likes coffee"]}
{"type":"entity","name":"Bob","entityType":"person","observations":[]}

Loading and Parsing the Graph

The server reconstructs the graph by streaming the JSONL file:

const graph = await knowledgeGraphManager.readGraph();
console.log(graph.entities.length); // → 2

Automatic Migration Example

When upgrading from a legacy installation:


# Server detects old format and logs:

# DETECTED: Found legacy memory.json file, migrating to memory.jsonl for JSONL format compatibility

# COMPLETED: Successfully migrated memory.json to memory.jsonl

The migration logic handles the rename operation automatically【src/memory/index.ts‑L38】.

Summary

  • Line-oriented I/O: The JSONL format in src/memory/index.ts supports efficient append operations via saveGraph, avoiding full-file rewrites for every entity update.
  • Streaming parser: loadGraph implements line-by-line parsing using split("\n"), enabling large graph support without loading entire files into memory.
  • Legacy support: The server automatically migrates from memory.json to memory.jsonl, preserving data integrity across version upgrades.
  • API stability: The MEMORY_FILE_PATH environment variable explicitly targets JSONL files, making the format a documented part of the server contract.

Frequently Asked Questions

What is the default filename for MCP Memory server storage?

The default filename is memory.jsonl in the current working directory. The ensureMemoryFilePath function in src/memory/index.ts returns this default when the MEMORY_FILE_PATH environment variable is unset【src/memory/index.ts‑L20】.

Does the MCP Memory server append to the JSONL file or rewrite it completely?

According to the source implementation, the server writes the entire graph using saveGraph, which joins all serialized objects with newlines【src/memory/index.ts‑L116】. While the format supports append semantics, the current implementation optimizes for atomic writes by serializing the complete graph state to ensure data consistency.

How does the server handle upgrades from the old memory.json format?

The server detects legacy memory.json files during startup via ensureMemoryFilePath and automatically renames them to memory.jsonl【src/memory/index.ts‑L39】. This migration preserves existing data while transitioning to the JSONL structure required by the current server version.

Why is JSONL preferred over a SQLite database for this use case?

JSONL provides human-readable, line-oriented storage that requires no external database dependencies or binary drivers. As implemented in src/memory/index.ts, the format allows simple file-based version control, easy debugging via text editors, and streaming consumption while maintaining the structural integrity required for knowledge-graph entities and relations.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →