Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -436,6 +436,7 @@ The server provides a comprehensive set of tools organized into several categori
| | `get_file_info` | Retrieve detailed metadata about a file or directory |
| **Text Editing** | `edit_block` | Apply targeted text replacements with enhanced prompting for smaller edits (includes character-level diff feedback) |
| **Analytics** | `get_usage_stats` | Get usage statistics for your own insight |
| | `get_recent_tool_calls` | Get recent tool call history with arguments and outputs for debugging and context recovery |
| | `give_feedback_to_desktop_commander` | Open feedback form in browser to provide feedback to Desktop Commander Team |

### Quick Examples
Expand Down
4 changes: 4 additions & 0 deletions manifest.template.json
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,10 @@
"name": "get_usage_stats",
"description": "Get usage statistics for debugging and analysis including tool usage and performance metrics."
},
{
"name": "get_recent_tool_calls",
"description": "Get recent tool call history with their arguments and outputs. Returns chronological list of tool calls made during this session for debugging, context recovery, and onboarding new chats."
},
{
"name": "give_feedback_to_desktop_commander",
"description": "Open feedback form in browser to provide feedback about Desktop Commander."
Expand Down
40 changes: 40 additions & 0 deletions src/handlers/history-handlers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { toolHistory } from '../utils/toolHistory.js';
import { GetRecentToolCallsArgsSchema } from '../tools/schemas.js';
import { ServerResult } from '../types.js';

/**
* Handle get_recent_tool_calls command
*/
export async function handleGetRecentToolCalls(args: unknown): Promise<ServerResult> {
try {
const parsed = GetRecentToolCallsArgsSchema.parse(args);

// Use formatted version with local timezone
const calls = toolHistory.getRecentCallsFormatted({
maxResults: parsed.maxResults,
toolName: parsed.toolName,
since: parsed.since
});

const stats = toolHistory.getStats();

// Format the response (excluding file path per user request)
const summary = `Tool Call History (${calls.length} results, ${stats.totalEntries} total in memory)`;
const historyJson = JSON.stringify(calls, null, 2);

return {
content: [{
type: "text",
text: `${summary}\n\n${historyJson}`
}]
};
} catch (error) {
return {
content: [{
type: "text",
text: `Error getting tool history: ${error instanceof Error ? error.message : String(error)}`
}],
isError: true
};
}
}
1 change: 1 addition & 0 deletions src/handlers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ export * from './terminal-handlers.js';
export * from './process-handlers.js';
export * from './edit-search-handlers.js';
export * from './search-handlers.js';
export * from './history-handlers.js';
46 changes: 46 additions & 0 deletions src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ import {
StopSearchArgsSchema,
ListSearchesArgsSchema,
GetPromptsArgsSchema,
GetRecentToolCallsArgsSchema,
} from './tools/schemas.js';
import {getConfig, setConfigValue} from './tools/config.js';
import {getUsageStats} from './tools/usage.js';
Expand All @@ -53,6 +54,7 @@ import {getPrompts} from './tools/prompts.js';
import {trackToolCall} from './utils/trackTools.js';
import {usageTracker} from './utils/usageTracker.js';
import {processDockerPrompt} from './utils/dockerPrompt.js';
import {toolHistory} from './utils/toolHistory.js';

import {VERSION} from './version.js';
import {capture, capture_call_tool} from "./utils/capture.js";
Expand Down Expand Up @@ -811,6 +813,27 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
readOnlyHint: true,
},
},
{
name: "get_recent_tool_calls",
description: `
Get recent tool call history with their arguments and outputs.
Returns chronological list of tool calls made during this session.

Useful for:
- Onboarding new chats about work already done
- Recovering context after chat history loss
- Debugging tool call sequences

Note: Does not track its own calls or other meta/query tools.
History kept in memory (last 1000 calls, lost on restart).

${CMD_PREFIX_DESCRIPTION}`,
inputSchema: zodToJsonSchema(GetRecentToolCallsArgsSchema),
annotations: {
title: "Get Recent Tool Calls",
readOnlyHint: true,
},
},
Comment on lines +816 to +836
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Correct the documentation about history persistence.

Line 828 states "History kept in memory (last 1000 calls, lost on restart)", but according to src/utils/toolHistory.ts, history is actually persisted to disk in ~/.claude-server-commander/tool-history.jsonl and reloaded on startup. Only the in-memory cache is limited to 1000 entries, but the full history survives restarts.

Apply this diff to correct the documentation:

                     description: `
                         Get recent tool call history with their arguments and outputs.
                         Returns chronological list of tool calls made during this session.
                         
                         Useful for:
                         - Onboarding new chats about work already done
                         - Recovering context after chat history loss
                         - Debugging tool call sequences
                         
                         Note: Does not track its own calls or other meta/query tools.
-                        History kept in memory (last 1000 calls, lost on restart).
+                        History persisted to disk and survives restarts (last 1000 calls kept in memory).
                         
                         ${CMD_PREFIX_DESCRIPTION}`,
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
{
name: "get_recent_tool_calls",
description: `
Get recent tool call history with their arguments and outputs.
Returns chronological list of tool calls made during this session.
Useful for:
- Onboarding new chats about work already done
- Recovering context after chat history loss
- Debugging tool call sequences
Note: Does not track its own calls or other meta/query tools.
History kept in memory (last 1000 calls, lost on restart).
${CMD_PREFIX_DESCRIPTION}`,
inputSchema: zodToJsonSchema(GetRecentToolCallsArgsSchema),
annotations: {
title: "Get Recent Tool Calls",
readOnlyHint: true,
},
},
{
name: "get_recent_tool_calls",
description: `
Get recent tool call history with their arguments and outputs.
Returns chronological list of tool calls made during this session.
Useful for:
- Onboarding new chats about work already done
- Recovering context after chat history loss
- Debugging tool call sequences
Note: Does not track its own calls or other meta/query tools.
History persisted to disk and survives restarts (last 1000 calls kept in memory).
${CMD_PREFIX_DESCRIPTION}`,
inputSchema: zodToJsonSchema(GetRecentToolCallsArgsSchema),
annotations: {
title: "Get Recent Tool Calls",
readOnlyHint: true,
},
},
🤖 Prompt for AI Agents
In src/server.ts around lines 816 to 836, the description for
"get_recent_tool_calls" incorrectly states the full history is lost on restart;
update the text to note that the history is persisted to disk at
~/.claude-server-commander/tool-history.jsonl and reloaded on startup, while
only the in-memory cache is limited to the last 1000 entries (which may be
cleared on restart), and keep the rest of the description and
CMD_PREFIX_DESCRIPTION interpolation unchanged.

{
name: "give_feedback_to_desktop_commander",
description: `
Expand Down Expand Up @@ -895,6 +918,7 @@ import {ServerResult} from './types.js';

server.setRequestHandler(CallToolRequestSchema, async (request: CallToolRequest): Promise<ServerResult> => {
const {name, arguments: args} = request.params;
const startTime = Date.now();

try {
// Prepare telemetry data - add config key for set_config_value
Expand Down Expand Up @@ -1042,6 +1066,18 @@ server.setRequestHandler(CallToolRequestSchema, async (request: CallToolRequest)
}
break;

case "get_recent_tool_calls":
try {
result = await handlers.handleGetRecentToolCalls(args);
} catch (error) {
capture('server_request_error', {message: `Error in get_recent_tool_calls handler: ${error}`});
result = {
content: [{type: "text", text: `Error: Failed to get tool call history`}],
isError: true,
};
}
break;

case "give_feedback_to_desktop_commander":
try {
result = await giveFeedbackToDesktopCommander(args);
Expand Down Expand Up @@ -1143,6 +1179,16 @@ server.setRequestHandler(CallToolRequestSchema, async (request: CallToolRequest)
};
}

// Add tool call to history (exclude only get_recent_tool_calls to prevent recursion)
const duration = Date.now() - startTime;
const EXCLUDED_TOOLS = [
'get_recent_tool_calls'
];

if (!EXCLUDED_TOOLS.includes(name)) {
toolHistory.addCall(name, args, result, duration);
}

// Track success or failure based on result
if (result.isError) {
await usageTracker.trackFailure(name);
Expand Down
16 changes: 15 additions & 1 deletion src/tools/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,24 @@ export async function getConfig() {

// Add system information and current client to the config response
const systemInfo = getSystemInfo();

// Get memory usage
const memoryUsage = process.memoryUsage();
const memory = {
rss: `${(memoryUsage.rss / 1024 / 1024).toFixed(2)} MB`,
heapTotal: `${(memoryUsage.heapTotal / 1024 / 1024).toFixed(2)} MB`,
heapUsed: `${(memoryUsage.heapUsed / 1024 / 1024).toFixed(2)} MB`,
external: `${(memoryUsage.external / 1024 / 1024).toFixed(2)} MB`,
arrayBuffers: `${(memoryUsage.arrayBuffers / 1024 / 1024).toFixed(2)} MB`
};

const configWithSystemInfo = {
...config,
currentClient,
systemInfo
systemInfo: {
...systemInfo,
memory
}
};

console.error(`getConfig result: ${JSON.stringify(configWithSystemInfo, null, 2)}`);
Expand Down
7 changes: 7 additions & 0 deletions src/tools/schemas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,4 +136,11 @@ export const GetPromptsArgsSchema = z.object({
action: z.enum(['list_categories', 'list_prompts', 'get_prompt']),
category: z.string().optional(),
promptId: z.string().optional(),
});

// Tool history schema
export const GetRecentToolCallsArgsSchema = z.object({
maxResults: z.number().min(1).max(1000).optional().default(50),
toolName: z.string().optional(),
since: z.string().datetime().optional(),
});
Loading