Where DesktopCommanderMCP Stores Tool Call Logs: Audit Logging Across macOS, Linux, and Windows
DesktopCommanderMCP stores every tool invocation in a JSONL audit file at ~/.claude-server-commander/tool-history.jsonl, using os.homedir() to ensure the same logging mechanism works identically on macOS, Linux, and Windows.
DesktopCommanderMCP is a Model Context Protocol (MCP) server that provides desktop automation capabilities. Understanding where tool call logs are stored and how the audit logging system functions across different operating systems is essential for debugging and compliance. The implementation uses a platform-agnostic approach that writes to the user's home directory regardless of the underlying OS.
Audit Log Storage Location and File Format
The primary audit store is implemented in src/utils/toolHistory.ts.
The system constructs the log file path using Node.js's os.homedir() method:
import * as os from 'os';
import * as path from 'path';
const historyFile = path.join(os.homedir(), '.claude-server-commander', 'tool-history.jsonl');
Each entry is appended as a JSON object containing the timestamp, tool name, arguments, output, and optional duration. The file uses JSON Lines (JSONL) format, where each line represents a complete JSON record.
How the Audit Logging Mechanism Works
The ToolHistory class in src/utils/toolHistory.ts manages the audit trail through several key mechanisms.
The addCall Method
When a tool executes, the addCall method creates a ToolCallRecord and queues it for persistence:
import { toolHistory } from './utils/toolHistory';
// After tool execution
const result = await someTool.run(args);
toolHistory.addCall('someTool', args, result, Date.now() - start);
This method pushes the record into a bounded in-memory array (maximum 1,000 entries) and schedules an asynchronous disk flush via flushToDisk().
File Size Management
The audit system enforces storage limits to prevent unbounded growth:
- Maximum file size: 5 MiB
- Target size after trim: approximately 4 MiB
When the file exceeds the size cap, trimHistoryFileIfTooLarge() removes the oldest lines until the file shrinks to the target size. This rotation happens automatically during the flush cycle.
Asynchronous Write Queue
The flushToDisk routine checks the file size, trims if necessary, then appends new JSON lines using fs.appendFileSync. This design ensures that tool calls are recorded without blocking the main execution thread.
Cross-Platform Storage Paths
Because the log path derives from os.homedir(), the audit logging mechanism is platform-agnostic. The same code executes on all supported operating systems, with the OS determining the actual directory resolution.
| Platform | os.homedir() Resolution |
Final Audit File Location |
|---|---|---|
| macOS | /Users/<username> |
/Users/<username>/.claude-server-commander/tool-history.jsonl |
| Linux | /home/<username> |
/home/<username>/.claude-server-commander/tool-history.jsonl |
| Windows | C:\Users\<username> |
C:\Users\<username>\.claude-server-commander\tool-history.jsonl |
Secondary and Legacy Log Files
Beyond the primary JSONL audit store, DesktopCommanderMCP maintains additional logging infrastructure.
Legacy Plain-Text Logger
The older trackTools helper in src/utils/trackTools.ts writes plain-text logs to a different directory structure:
~/.claude-server-commander-logs/fuzzy-search.log
This logger rotates files when they reach approximately 10 MiB, compared to the 5 MiB cap used by the primary audit system.
Specialized Loggers
Additional components like src/utils/fuzzySearchLogger.ts implement domain-specific logging under the same home-directory scheme. These files complement the main audit trail but use different rotation strategies and formats.
Programmatic Access to Audit Logs
You can interact with the audit system directly through the toolHistory API.
Retrieving Recent Calls
To fetch formatted history entries with timezone conversion:
import { toolHistory } from './utils/toolHistory';
const recent = toolHistory.getRecentCallsFormatted({
maxResults: 20,
since: '2024-01-01T00:00:00Z',
});
console.log(recent);
Cleanup and Shutdown
For graceful shutdown or test cleanup:
await toolHistory.cleanup(); // Flushes pending writes and clears timers
Accessing the File Path Directly
To locate the audit file programmatically:
import { toolHistory } from './utils/toolHistory';
console.log('Audit file:', toolHistory.getStats().historyFile);
Summary
- DesktopCommanderMCP stores tool call logs in
~/.claude-server-commander/tool-history.jsonlusing a JSONL format. - The
src/utils/toolHistory.tsmodule provides the primary audit logging implementation with a 5 MiB size cap and 1,000-entry memory buffer. - Cross-platform compatibility is achieved through
os.homedir(), resulting in platform-specific paths on macOS (/Users/...), Linux (/home/...), and Windows (C:\Users\...). - Legacy logging in
src/utils/trackTools.tsuses plain-text format with 10 MiB rotation under~/.claude-server-commander-logs/.
Frequently Asked Questions
Where exactly is the tool call audit log stored on Windows?
On Windows, the audit log is stored at C:\Users\<username>\.claude-server-commander\tool-history.jsonl, where <username> is the current user's profile name. The path is constructed dynamically using Node.js's os.homedir() function, which resolves to the user's home directory regardless of Windows version.
What is the maximum size of the audit log file before rotation?
The primary audit file caps at 5 MiB, at which point the system trims oldest entries until the file reaches approximately 4 MiB. This is implemented in the trimHistoryFileIfTooLarge() function within src/utils/toolHistory.ts. Secondary log files used by the legacy trackTools system rotate at 10 MiB instead.
How can I programmatically retrieve recent tool call history?
Import the toolHistory singleton from src/utils/toolHistory.ts and call getRecentCallsFormatted(), passing optional parameters for maxResults and since timestamp. This returns the most recent entries with timestamps converted to the local timezone, formatted for display or further processing.
Does DesktopCommanderMCP support custom audit log directories?
Currently, the audit log directory is hardcoded to .claude-server-commander within the user's home directory as defined by os.homedir(). The path is constructed in src/utils/toolHistory.ts without configuration options, meaning you cannot specify custom locations without modifying the source code. Direct file access is possible by reading the JSONL file directly from the resolved home directory path.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →