Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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