# How the MCP Memory Server Handles Backward Compatibility Migration

> Discover how the MCP Memory server seamlessly handles backward compatibility migration, automatically converting legacy memory json files to the modern jsonl format on startup with zero manual effort.

- Repository: [Model Context Protocol/servers](https://github.com/modelcontextprotocol/servers)
- Tags: migration-guide
- Published: 2026-03-01

---

**The MCP Memory server automatically migrates legacy [`memory.json`](https://github.com/modelcontextprotocol/servers/blob/main/memory.json) files to the modern `memory.jsonl` format during startup by detecting the old file, renaming it while preserving contents, and logging the transition, requiring no manual intervention from users.**

The **MCP Memory server** in the `modelcontextprotocol/servers` repository stores knowledge-graph data in a JSON Lines format for improved efficiency and append-only operations. To ensure seamless **backward compatibility migration** for existing deployments, the server implements an automatic migration routine in [`src/memory/index.ts`](https://github.com/modelcontextprotocol/servers/blob/main/src/memory/index.ts) that upgrades legacy storage files without breaking existing data or requiring user action.

## Migration Architecture in [`src/memory/index.ts`](https://github.com/modelcontextprotocol/servers/blob/main/src/memory/index.ts)

The core migration logic resides in the `ensureMemoryFilePath` function. This utility determines the correct file path and handles format transitions during server initialization by detecting file presence and executing conditional rename operations.

### Detecting Legacy vs. Modern Formats

The function distinguishes between two storage formats:

- **Legacy format**: [`memory.json`](https://github.com/modelcontextprotocol/servers/blob/main/memory.json) (plain JSON structure)
- **Modern format**: `memory.jsonl` (JSON Lines for append-only efficiency)

According to the source code at lines 22-25, the function constructs both paths relative to the module directory. When no custom path is specified via environment variables, it checks for the existence of these files to determine if migration is necessary.

### Environment Variable Override

Before checking for legacy files, the function respects the `MEMORY_FILE_PATH` environment variable. As implemented at lines 15-20, if this variable is set, the function resolves the specified absolute or relative path and returns it immediately, skipping all migration logic. This allows users to maintain custom storage locations outside the default migration workflow.

## Automatic Migration Workflow

When the server starts, the migration routine executes automatically through the following decision tree implemented in lines 26-43:

1. **Both files exist**: The server uses `memory.jsonl` exclusively, ignoring the legacy file without migration or console output.
2. **Only legacy file exists**: The server logs a detection message, executes `fs.rename()` at line 36 to rename [`memory.json`](https://github.com/modelcontextprotocol/servers/blob/main/memory.json) to `memory.jsonl`, logs completion, and proceeds with the new file.
3. **No legacy file**: The server returns the default `memory.jsonl` path, creating the file later when data is first saved.

This approach ensures the migration is **idempotent** and **non-destructive**, preserving exact file contents during the rename operation without parsing or transforming the JSON data.

## Validating Migration Behavior

The test suite in [`src/memory/__tests__/file-path.test.ts`](https://github.com/modelcontextprotocol/servers/blob/main/src/memory/__tests__/file-path.test.ts) validates all migration scenarios to ensure reliability:

- **Environment variable precedence**: Confirms `MEMORY_FILE_PATH` bypasses migration logic for absolute, relative, and Windows paths.
- **Clean installation**: Verifies behavior when neither file exists, returning the default path.
- **Legacy-only migration**: Ensures [`memory.json`](https://github.com/modelcontextprotocol/servers/blob/main/memory.json) is renamed to `memory.jsonl` with exact content preservation and proper log output.
- **Coexistence handling**: Confirms no migration occurs when both files exist, preventing accidental overwrites of existing modern format data.
- **Data integrity**: Validates that file contents remain bit-for-bit identical after migration, confirming the rename operation does not modify data.

## Implementation Examples

### Starting the Server with Automatic Migration

When you start the Memory server, the migration runs automatically if needed:

```typescript
import { ensureMemoryFilePath } from "./src/memory/index.js";

async function start() {
  // Triggers migration if memory.json exists
  const memoryPath = await ensureMemoryFilePath();
  console.log("Using memory file:", memoryPath);
  // Server initialization continues...
}
start();

```

*Console output when migration occurs:*

```

DETECTED: Found legacy memory.json file, migrating to memory.jsonl for JSONL format compatibility
COMPLETED: Successfully migrated memory.json to memory.jsonl
Using memory file: /path/to/memory.jsonl

```

### Bypassing Migration with Custom Paths

To use a custom storage location and skip automatic migration:

```bash

# Unix/Linux

export MEMORY_FILE_PATH=/data/persistent-memory.jsonl
node src/memory/index.js

# Windows PowerShell

$env:MEMORY_FILE_PATH = "C:\data\persistent-memory.jsonl"
node src/memory/index.js

```

When `MEMORY_FILE_PATH` is set, the server resolves the absolute path and ignores the default migration logic entirely, as specified in the `ensureMemoryFilePath` implementation.

### Programmatic Migration Testing

Simulate the migration in a test environment to verify behavior:

```typescript
import { promises as fs } from "fs";
import path from "path";
import { ensureMemoryFilePath, defaultMemoryPath } from "./src/memory/index.js";

async function testMigration() {
  // Create legacy file with sample data
  const legacyPath = path.join(process.cwd(), "memory.json");
  await fs.writeFile(legacyPath, '{"entities":[],"relations":[]}');
  
  // Execute migration
  await ensureMemoryFilePath();
  
  // Verify migration success
  const newContent = await fs.readFile(defaultMemoryPath, "utf-8");
  console.assert(newContent === '{"entities":[],"relations":[]}');
  console.log("Migration verified successfully");
}
testMigration();

```

## Summary

- The MCP Memory server automatically handles **backward compatibility migration** by detecting legacy [`memory.json`](https://github.com/modelcontextprotocol/servers/blob/main/memory.json) files and renaming them to `memory.jsonl` during startup.
- The `ensureMemoryFilePath` function in [`src/memory/index.ts`](https://github.com/modelcontextprotocol/servers/blob/main/src/memory/index.ts) implements this logic at lines 26-43, specifically performing the atomic rename operation at line 36.
- Migration only occurs when exclusively the legacy file exists; if both files exist, the server uses the modern format without modification to prevent data loss.
- The `MEMORY_FILE_PATH` environment variable overrides all migration logic, allowing custom storage locations without triggering legacy file detection.
- Comprehensive tests in [`src/memory/__tests__/file-path.test.ts`](https://github.com/modelcontextprotocol/servers/blob/main/src/memory/__tests__/file-path.test.ts) verify idempotent behavior and data preservation across all migration scenarios.

## Frequently Asked Questions

### What triggers the MCP Memory server backward compatibility migration?

The migration triggers automatically when the server starts and detects a [`memory.json`](https://github.com/modelcontextprotocol/servers/blob/main/memory.json) file in the module directory without an existing `memory.jsonl` file. The `ensureMemoryFilePath` function performs this check during initialization, renaming the legacy file to the new JSON Lines format while preserving all contents exactly and logging the transition to stderr.

### Will I lose data during the automatic migration from memory.json to memory.jsonl?

No. The migration uses a simple file rename operation at line 36 of [`src/memory/index.ts`](https://github.com/modelcontextprotocol/servers/blob/main/src/memory/index.ts), which preserves the exact byte content of the original file. The test suite confirms that data remains bit-for-bit identical after migration, and because the operation uses the filesystem's native rename, it is atomic and does not parse or transform the JSON structure.

### How do I prevent automatic migration and use a custom memory file location?

Set the `MEMORY_FILE_PATH` environment variable to your desired absolute or relative path. When this variable is present, the server uses the specified path directly and skips all legacy file detection and migration logic, as implemented in lines 15-20 of the source code. This is the recommended approach for production deployments requiring specific storage volumes or network paths.

### What happens if both memory.json and memory.jsonl exist in the directory?

If both files exist simultaneously, the server uses `memory.jsonl` exclusively and performs no migration. This prevents accidental overwrites of existing data and allows administrators to manually manage the transition if needed. The server produces no console output in this scenario, treating the presence of both files as a standard operational state where the modern format takes precedence.