How Desktop Commander MCP Tracks Recent Operations for Context Recovery

Desktop Commander MCP uses a size-limited in-memory queue backed by a JSON-Lines file to record every tool invocation, enabling users to recover their session context after a lost chat transcript.

The tool history system in Desktop Commander MCP maintains a durable, queryable log of recent operations. This subsystem lives primarily in src/utils/toolHistory.ts and exposes its data through a dedicated API, allowing clients to rebuild state even when the original conversation context is lost.

Core Architecture of the Tool History System

In-Memory Record Queue

At runtime, the history manager maintains a private array that stores recent tool calls:

private history: ToolCallRecord[] = [];  // toolHistory.ts#L33

Each entry is a ToolCallRecord containing timestamp, tool name, arguments, and output. The queue enforces a ceiling defined by MAX_ENTRIES; when exceeded, the oldest record is dropped via this.history.shift() (toolHistory.ts#L286).

Persistent JSON-Lines Storage

To survive process restarts, records are written to a per-user file:

const historyDir = path.join(os.homedir(), '.claude-server-commander');  // toolHistory.ts#L65
if (!fs.existsSync(historyDir)) {
  fs.mkdirSync(historyDir, { recursive: true });
}
this.historyFile = path.join(historyDir, 'tool-history.jsonl');  // toolHistory.ts#L74

On instantiation, the constructor loads existing entries using fs.readFileSync (toolHistory.ts#L76-L84) and trims the dataset to respect MAX_STORED_OUTPUT_BYTES (toolHistory.ts#L263).

How Records Are Added and Maintained

Appending New Tool Calls

When a tool completes, addToolCall() performs three operations:

  1. Creates a ToolCallRecord with the current timestamp
  2. Pushes to the in-memory array (and evicts oldest if over limit)
  3. Appends a JSON-encoded line to disk via fs.appendFileSync
// src/utils/toolHistory.ts#L230-L240 (excerpt)
public addToolCall(name: string, args: any, output: string) {
  const record: ToolCallRecord = {
    timestamp: Date.now(),
    name,
    args,
    output: output.length > this.MAX_STORED_OUTPUT_BYTES
      ? `[output omitted from history: ${output.length}, over the ${this.MAX_STORED_OUTPUT_BYTES}-byte cap]`
      : output,
  };
  this.history.push(record);
  if (this.history.length > this.MAX_ENTRIES) this.history.shift();
  fs.appendFileSync(this.historyFile, JSON.stringify(record) + '\n');
}

Automatic Log Trimming

The system monitors file size using fs.statSync (toolHistory.ts#L140-L152). When the on-disk log exceeds the byte limit, it rewrites the file containing only the most recent MAX_ENTRIES records via fs.writeFileSync (toolHistory.ts#L187-L191).

Querying Recent Operations

Server Endpoint for Context Recovery

The Desktop Commander MCP server exposes recent history through a dedicated route in src/server.ts (lines 1141-1146):

app.get('/get_recent_tool_calls', async (req, res) => {
  try {
    const calls = await toolHistory.getRecentCalls();
    res.json({
      totalEntries: calls.length,
      oldestEntry: calls[0]?.timestamp,
      newestEntry: calls[calls.length - 1]?.timestamp,
      historyFile: this.historyFile,
      calls
    });
  } catch (e) {
    res.status(500).json({ error: `Failed to get tool call history: ${e.message}` });
  }
});

Formatting for Client Consumption

The history-handlers module (src/handlers/history-handlers.ts) transforms raw records into human-readable JSON:

// src/handlers/history-handlers.ts#L34-L39
const formattedHistory = JSON.stringify(recentCalls, null, 2);
return {
  content: [{
    type: "text",
    text: `## Recent Tool Calls\n\`\`\`json\n${formattedHistory}\n\`\`\``

  }]
};

Errors during file reads are caught and surfaced with descriptive messages (Error getting tool history…, history-handlers.ts#L46-L48).

How Context Recovery Works

When a chat transcript is lost—for example, after a browser refresh—the client can request the recent tool-call dump from the server. By replaying the stored tool name, arguments, and output, the UI reconstructs the last several actions without requiring the original conversation history.

Component Responsibility Key Location
In-memory queue Fast runtime access to recent calls toolHistory.ts#L33
JSON-Lines persistence Durability across restarts ~/.claude-server-commander/tool-history.jsonl
Size-based trimming Prevents unbounded growth toolHistory.ts#L140-L191
HTTP endpoint Exposes data for context recovery server.ts#L1141-L1150
Handler formatting Pretty-prints for UI display history-handlers.ts#L34-L39

Summary

  • Desktop Commander MCP implements tool history tracking through a hybrid memory-disk architecture in src/utils/toolHistory.ts.
  • Records are stored in ~/.claude-server-commander/tool-history.jsonl using the JSON-Lines format for append-only efficiency.
  • Automatic size limits protect against unbounded growth through both entry count (MAX_ENTRIES) and byte size (MAX_STORED_OUTPUT_BYTES) thresholds.
  • The /get_recent_tool_calls endpoint enables clients to recover session context after chat transcript loss.
  • Error handling and formatting logic in src/handlers/history-handlers.ts ensures reliable delivery to the UI.

Frequently Asked Questions

What format is used to store tool history entries?

Desktop Commander MCP uses JSON-Lines (.jsonl), where each line is an independent JSON object representing one ToolCallRecord. This format allows efficient append operations without rewriting the entire file on every tool invocation.

How does the system prevent the history file from growing indefinitely?

Two mechanisms enforce limits: an in-memory ceiling (MAX_ENTRIES) drops oldest records when exceeded, and a byte-size check (MAX_STORED_OUTPUT_BYTES) triggers periodic file rewrites containing only recent entries. Output text itself is truncated if it exceeds the per-record byte cap.

Can I retrieve tool history after restarting the Desktop Commander MCP server?

Yes. The constructor in toolHistory.ts automatically loads any existing tool-history.jsonl file from ~/.claude-server-commander/ on startup (lines 76-84), restoring the previous session's recent operations into memory.

What happens if the history file becomes corrupted?

The getRecentCalls() method and history handlers wrap file operations in try-catch blocks. Errors are captured and returned with descriptive messages like Error getting tool history, preventing server crashes while alerting the client to the failure condition.

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 →