# How Desktop Commander MCP Audit Logging Works: Inside `claude_tool_call.log`

> Explore how Desktop Commander MCP audit logging works, detailing the claude_tool_call.log. Discover what information is captured, including timestamps, client identity, tool arguments, and outcomes. Learn about log rotation.

- Repository: [Eduard Ruzga/DesktopCommanderMCP](https://github.com/wonderwhy-er/DesktopCommanderMCP)
- Tags: internals
- Published: 2026-08-07

---

**Desktop Commander MCP writes a JSON audit record for every tool call to `~/.claude-server-commander/claude_tool_call.log`, capturing timestamps, client identity, tool names, arguments, and outcomes—with automatic 10 MiB log rotation.**

This audit system lets developers trace exactly what AI agents requested, when, and what happened. The implementation spans configuration constants, a dedicated logging utility, and integration points across all tool handlers.

## Core Architecture: Three Components

### Configuration Layer ([`src/config.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/config.ts))

The log file location is defined centrally in [`src/config.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/config.ts) via `TOOL_CALL_FILE`. This constant joins `CONFIG_DIR` (set to `~/.claude-server-commander`) with the filename `claude_tool_call.log`.

```typescript
// src/config.ts – simplified excerpt
import path from 'path';
import os from 'os';

export const CONFIG_DIR = path.join(os.homedir(), '.claude-server-commander');
export const TOOL_CALL_FILE = path.join(CONFIG_DIR, 'claude_tool_call.log');

```

See [src/config.ts#L6-L10](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/config.ts#L6-L10) for the full definition.

### Audit Recorder ([`src/utils/toolHistory.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/utils/toolHistory.ts))

The `logToolCall` function in [`src/utils/toolHistory.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/utils/toolHistory.ts) is the heart of the audit system. Every tool handler imports and calls this function before executing its logic.

**Captured fields per record:**

- **ts** – ISO-8601 timestamp from `new Date().toISOString()`
- **client** – identifying string for the calling client (e.g., `claude-desktop`, `claude-code`)
- **tool** – the `toolId` being invoked
- **args** – serialized arguments object
- **result** – `"ok"` for success, or `"error"` with accompanying **error** message

Source: [src/utils/toolHistory.ts](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/utils/toolHistory.ts)

### Log Rotation ([`src/utils/fuzzySearchLogger.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/utils/fuzzySearchLogger.ts))

To prevent unbounded growth, the logger enforces a **10 MiB size limit**. When `TOOL_CALL_FILE` exceeds this threshold, it is renamed to `claude_tool_call.log.old` and a fresh file begins. This rotation logic is shared with other logging utilities in the codebase.

```typescript
// src/utils/fuzzySearchLogger.ts – rotation logic excerpt
const MAX_LOG_SIZE = 10 * 1024 * 1024; // 10 MiB

if (currentSize > MAX_LOG_SIZE) {
  const oldPath = `${logPath}.old`;
  await rename(logPath, oldPath);
  // Continue writing to fresh file
}

```

Source: [src/utils/fuzzySearchLogger.ts#L30-L36](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/utils/fuzzySearchLogger.ts#L30-L36)

## Log Entry Format and Examples

Each tool call produces a **single JSON line** (newline-delimited JSON), enabling efficient streaming and command-line processing.

### Successful tool call

```json
{"ts":"2024-07-19T14:23:11.842Z","client":"claude-desktop","tool":"read_file","args":{"path":"~/projects/app/src/index.ts"},"result":"ok"}

```

### Failed tool call with error details

```json
{"ts":"2024-07-19T14:25:04.113Z","client":"claude-code","tool":"write_file","args":{"path":"/etc/passwd","content":"..."},"result":"error","error":"EACCES: permission denied"}

```

The **newline-delimited format** ensures compatibility with standard Unix tools: `grep`, `jq`, `awk`, and log aggregation pipelines.

## Working with Audit Logs: Practical Examples

### Read recent entries programmatically

```typescript
import { readFileSync } from 'fs';
import { join } from 'path';
import os from 'os';

const logPath = join(os.homedir(), '.claude-server-commander', 'claude_tool_call.log');

const recent = readFileSync(logPath, 'utf8')
  .trim()
  .split('\n')
  .slice(-10)
  .map(line => JSON.parse(line));

console.table(recent.map(r => ({ tool: r.tool, client: r.client, result: r.result })));

```

### Filter for specific tool usage with `jq`

```bash

# All read_file calls, pretty-printed

jq 'select(.tool == "read_file")' ~/.claude-server-commander/claude_tool_call.log

# Count errors by tool

jq -r 'select(.result == "error") | .tool' ~/.claude-server-commander/claude_tool_call.log | sort | uniq -c

```

### Combine current and rotated logs for full history

```bash
cat ~/.claude-server-commander/claude_tool_call.log* > full_audit.jsonl
jq '.' full_audit.jsonl | less

```

### Disable audit logging for sensitive sessions

Set `DISABLE_AUDIT_LOG` to any non-empty value to skip `logToolCall` writes entirely:

```bash
DISABLE_AUDIT_LOG=1 npx @wonderwhy-er/desktop-commander@latest setup

```

## Integration Across Tool Handlers

Every handler in `src/handlers/` imports `logToolCall` and invokes it at entry. For example, terminal-related handlers in [`terminal-handlers.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/terminal-handlers.ts) call the logger before spawning processes or executing shell commands.

See [src/handlers/terminal-handlers.ts](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/handlers/terminal-handlers.ts) for representative usage patterns.

## Summary

- **Log location**: `~/.claude-server-commander/claude_tool_call.log` (defined in [`src/config.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/config.ts))
- **Log format**: Newline-delimited JSON with `ts`, `client`, `tool`, `args`, and `result` fields
- **Rotation trigger**: 10 MiB file size, archived to `.old` suffix
- **Core implementation**: [`src/utils/toolHistory.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/utils/toolHistory.ts) with shared rotation from [`src/utils/fuzzySearchLogger.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/utils/fuzzySearchLogger.ts)
- **Opt-out**: Set `DISABLE_AUDIT_LOG` environment variable

## Frequently Asked Questions

### What happens when `claude_tool_call.log` reaches 10 MiB?

The current file is renamed to `claude_tool_call.log.old` and a new empty log begins. Only one archived generation is kept—older `.old` files are overwritten on subsequent rotations.

### Can I change the audit log directory or filename?

Not without modifying the source. The path is hardcoded in [`src/config.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/config.ts) as `TOOL_CALL_FILE`. To relocate logs, fork the repository and adjust the `CONFIG_DIR` or `TOOL_CALL_FILE` constants.

### Does the audit log capture the full output of tool executions?

No. The audit log records **arguments provided and success/failure status**, not the complete stdout/stderr or return values. For full execution transcripts, inspect individual tool implementations or enable additional debugging at the client level.

### How do I search audit logs for a specific time range?

Use `jq` with date filtering on the `ts` field:

```bash
jq 'select(.ts >= "2024-07-19T10:00:00Z" and .ts < "2024-07-19T15:00:00Z")' \
  ~/.claude-server-commander/claude_tool_call.log

```