Desktop Commander MCP Audit Logging: How Tool Call Tracking Works

Desktop Commander MCP records every tool invocation to ~/.claude-server-commander/claude_tool_call.log with automatic 10 MB rotation, plus an optional bounded JSON-Lines history for UI inspection.

The audit logging mechanism in Desktop Commander MCP provides forensic visibility into every tool interaction. According to the wonderwhy-er/DesktopCommanderMCP source code, the system uses a dual-track approach: a raw append-only text log for debugging and a structured history file for quick UI access.

Log File Location and Configuration

All audit logs reside in a dedicated configuration directory under the user home folder.

In src/config.ts, the following constants define the primary audit log:

export const TOOL_CALL_FILE = path.join(CONFIG_DIR, 'claude_tool_call.log');
export const TOOL_CALL_FILE_MAX_SIZE = 1024 * 1024 * 10; // 10 MB

The CONFIG_DIR expands to ~/.claude-server-commander on Linux/macOS or the equivalent path on Windows. Therefore, the canonical audit log location is:


$HOME/.claude-server-commander/claude_tool_call.log

How the Audit Logger Writes Entries

The core audit function lives in src/utils/trackTools.ts. The trackToolCall(toolName, args?) function handles every logged invocation:

export async function trackToolCall(toolName: string, args?: unknown): Promise<void> {
  const timestamp = new Date().toISOString();
  const logEntry = `${timestamp} | ${toolName.padEnd(20, ' ')}${args ? `\t| Arguments: ${JSON.stringify(args)}` : ''}\n`;
  // …size check & rotation…
  await fs.promises.appendFile(TOOL_CALL_FILE, logEntry, 'utf8');
}

Each entry contains:

  • ISO-8601 timestamp for precise temporal ordering
  • Tool name padded to 20 characters for columnar alignment
  • JSON-encoded arguments (optional, when provided)

Log Rotation Behavior

Before writing, trackToolCall checks if the current log exceeds 10 MB. If so, it performs rotation:

  1. Renames claude_tool_call.log to claude_tool_call_YYYY-MM-DD_HH-MM-SS.log
  2. Creates a fresh empty log file
  3. Continues appending new entries

This prevents unbounded growth while preserving historical audit data.

Failure-Resilient Design

Errors during logging never block primary operations. If appendFile throws, the error is reported via telemetry and silently ignored—tool execution continues uninterrupted.

Tool Call History for UI Inspection

A separate system in src/utils/toolHistory.ts maintains tool-history.jsonl in the same directory. This JSON-Lines store keeps approximately 1,000 recent entries with full call metadata including results.

File Purpose Format
claude_tool_call.log Authoritative audit trail for debugging Plain text, append-only
tool-history.jsonl Bounded history for UI display JSON-Lines, ~1000 entries

The history file serves the Desktop Commander UI; the raw audit log remains the source of truth for forensic analysis.

Working with Audit Logs Programmatically

Logging a Tool Call from Custom Code

import { trackToolCall } from './utils/trackTools.js';

await trackToolCall('read_file', { path: '/tmp/example.txt' });

Reading the Current Audit Log

import { TOOL_CALL_FILE } from './config.js';
import { readFile } from 'fs/promises';

async function showAuditLog() {
  const content = await readFile(TOOL_CALL_FILE, 'utf-8');
  console.log(content);
}

Forcing Log Rotation for Testing

import { TOOL_CALL_FILE_MAX_SIZE, TOOL_CALL_FILE } from './config.js';
import { rename, stat, appendFile } from 'fs/promises';
import path from 'path';

async function forceRotation() {
  const dir = path.dirname(TOOL_CALL_FILE);
  const base = path.basename(TOOL_CALL_FILE, '.log');
  const now = new Date();
  const ts = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')}_${String(now.getHours()).padStart(2, '0')}-${String(now.getMinutes()).padStart(2, '0')}-${String(now.getSeconds()).padStart(2, '0')}`;
  const rotated = path.join(dir, `${base}_${ts}.log`);
  await rename(TOOL_CALL_FILE, rotated);
  await appendFile(TOOL_CALL_FILE, '', 'utf8');
}

Summary

  • Primary audit log: ~/.claude-server-commander/claude_tool_call.log (10 MB rotation)
  • Core implementation: trackToolCall() in src/utils/trackTools.ts
  • Configuration: src/config.ts defines paths and size limits
  • Secondary history: tool-history.jsonl for UI access to ~1,000 recent calls
  • Design priorities: Non-blocking writes, automatic rotation, failure resilience

Frequently Asked Questions

Where exactly are Desktop Commander MCP tool call logs stored?

The audit log resides at $HOME/.claude-server-commander/claude_tool_call.log. On Windows, this maps to %USERPROFILE%\.claude-server-commander\claude_tool_call.log. A separate UI-oriented history file exists at tool-history.jsonl in the same directory.

What happens when the audit log reaches 10 MB?

The trackToolCall function automatically rotates the file. It renames the current log with a timestamp suffix (e.g., claude_tool_call_2024-11-03_14-27-55.log) and starts a fresh empty log. This prevents disk exhaustion while preserving prior audit data.

Can audit logging be disabled?

The source code in wonderwhy-er/DesktopCommanderMCP does not expose a configuration flag to disable trackToolCall. Since errors are caught and ignored, logging fails gracefully without affecting operations. To effectively disable, you would need to modify src/utils/trackTools.ts or redirect TOOL_CALL_FILE to /dev/null.

How does the tool history differ from the audit log?

The tool history (tool-history.jsonl) is a structured JSON-Lines file with a ~1,000 entry limit used by the Desktop Commander UI. The audit log (claude_tool_call.log) is an unlimited, human-readable text file designed for forensic debugging and compliance tracing.

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 →