@wonderwhy-er/desktop-commander 0.2.16 → 0.2.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/server.js CHANGED
@@ -8,7 +8,7 @@ const OS_GUIDANCE = getOSSpecificGuidance(SYSTEM_INFO);
8
8
  const DEV_TOOL_GUIDANCE = getDevelopmentToolGuidance(SYSTEM_INFO);
9
9
  const PATH_GUIDANCE = `IMPORTANT: ${getPathGuidance(SYSTEM_INFO)} Relative paths may fail as they depend on the current working directory. Tilde paths (~/...) might not work in all contexts. Unless the user explicitly asks for relative paths, use absolute paths.`;
10
10
  const CMD_PREFIX_DESCRIPTION = `This command can be referenced as "DC: ..." or "use Desktop Commander to ..." in your instructions.`;
11
- import { StartProcessArgsSchema, ReadProcessOutputArgsSchema, InteractWithProcessArgsSchema, ForceTerminateArgsSchema, ListSessionsArgsSchema, KillProcessArgsSchema, ReadFileArgsSchema, ReadMultipleFilesArgsSchema, WriteFileArgsSchema, CreateDirectoryArgsSchema, ListDirectoryArgsSchema, MoveFileArgsSchema, GetFileInfoArgsSchema, GetConfigArgsSchema, SetConfigValueArgsSchema, ListProcessesArgsSchema, EditBlockArgsSchema, GetUsageStatsArgsSchema, GiveFeedbackArgsSchema, StartSearchArgsSchema, GetMoreSearchResultsArgsSchema, StopSearchArgsSchema, ListSearchesArgsSchema, GetPromptsArgsSchema, } from './tools/schemas.js';
11
+ import { StartProcessArgsSchema, ReadProcessOutputArgsSchema, InteractWithProcessArgsSchema, ForceTerminateArgsSchema, ListSessionsArgsSchema, KillProcessArgsSchema, ReadFileArgsSchema, ReadMultipleFilesArgsSchema, WriteFileArgsSchema, CreateDirectoryArgsSchema, ListDirectoryArgsSchema, MoveFileArgsSchema, GetFileInfoArgsSchema, GetConfigArgsSchema, SetConfigValueArgsSchema, ListProcessesArgsSchema, EditBlockArgsSchema, GetUsageStatsArgsSchema, GiveFeedbackArgsSchema, StartSearchArgsSchema, GetMoreSearchResultsArgsSchema, StopSearchArgsSchema, ListSearchesArgsSchema, GetPromptsArgsSchema, GetRecentToolCallsArgsSchema, } from './tools/schemas.js';
12
12
  import { getConfig, setConfigValue } from './tools/config.js';
13
13
  import { getUsageStats } from './tools/usage.js';
14
14
  import { giveFeedbackToDesktopCommander } from './tools/feedback.js';
@@ -16,6 +16,7 @@ import { getPrompts } from './tools/prompts.js';
16
16
  import { trackToolCall } from './utils/trackTools.js';
17
17
  import { usageTracker } from './utils/usageTracker.js';
18
18
  import { processDockerPrompt } from './utils/dockerPrompt.js';
19
+ import { toolHistory } from './utils/toolHistory.js';
19
20
  import { VERSION } from './version.js';
20
21
  import { capture, capture_call_tool } from "./utils/capture.js";
21
22
  import { logToStderr, logger } from './utils/logger.js';
@@ -95,15 +96,27 @@ server.setRequestHandler(InitializeRequestSchema, async (request) => {
95
96
  // Export current client info for access by other modules
96
97
  export { currentClient };
97
98
  deferLog('info', 'Setting up request handlers...');
99
+ /**
100
+ * Check if a tool should be included based on current client
101
+ */
102
+ function shouldIncludeTool(toolName) {
103
+ // Exclude give_feedback_to_desktop_commander for desktop-commander client
104
+ if (toolName === 'give_feedback_to_desktop_commander' && currentClient?.name === 'desktop-commander') {
105
+ return false;
106
+ }
107
+ // Add more conditional tool logic here as needed
108
+ // Example: if (toolName === 'some_tool' && currentClient?.name === 'some_client') return false;
109
+ return true;
110
+ }
98
111
  server.setRequestHandler(ListToolsRequestSchema, async () => {
99
112
  try {
100
113
  logToStderr('debug', 'Generating tools list...');
101
- return {
102
- tools: [
103
- // Configuration tools
104
- {
105
- name: "get_config",
106
- description: `
114
+ // Build complete tools array
115
+ const allTools = [
116
+ // Configuration tools
117
+ {
118
+ name: "get_config",
119
+ description: `
107
120
  Get the complete server configuration as JSON. Config includes fields for:
108
121
  - blockedCommands (array of blocked shell commands)
109
122
  - defaultShell (shell to use for commands)
@@ -116,15 +129,15 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
116
129
  - version (version of the DesktopCommander)
117
130
  - systemInfo (operating system and environment details)
118
131
  ${CMD_PREFIX_DESCRIPTION}`,
119
- inputSchema: zodToJsonSchema(GetConfigArgsSchema),
120
- annotations: {
121
- title: "Get Configuration",
122
- readOnlyHint: true,
123
- },
132
+ inputSchema: zodToJsonSchema(GetConfigArgsSchema),
133
+ annotations: {
134
+ title: "Get Configuration",
135
+ readOnlyHint: true,
124
136
  },
125
- {
126
- name: "set_config_value",
127
- description: `
137
+ },
138
+ {
139
+ name: "set_config_value",
140
+ description: `
128
141
  Set a specific configuration value by key.
129
142
 
130
143
  WARNING: Should be used in a separate chat from file operations and
@@ -142,18 +155,18 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
142
155
  to the entire file system, regardless of the operating system.
143
156
 
144
157
  ${CMD_PREFIX_DESCRIPTION}`,
145
- inputSchema: zodToJsonSchema(SetConfigValueArgsSchema),
146
- annotations: {
147
- title: "Set Configuration Value",
148
- readOnlyHint: false,
149
- destructiveHint: true,
150
- openWorldHint: false,
151
- },
158
+ inputSchema: zodToJsonSchema(SetConfigValueArgsSchema),
159
+ annotations: {
160
+ title: "Set Configuration Value",
161
+ readOnlyHint: false,
162
+ destructiveHint: true,
163
+ openWorldHint: false,
152
164
  },
153
- // Filesystem tools
154
- {
155
- name: "read_file",
156
- description: `
165
+ },
166
+ // Filesystem tools
167
+ {
168
+ name: "read_file",
169
+ description: `
157
170
  Read the contents of a file from the file system or a URL with optional offset and length parameters.
158
171
 
159
172
  Prefer this over 'execute_command' with cat/type for viewing files.
@@ -186,16 +199,16 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
186
199
 
187
200
  ${PATH_GUIDANCE}
188
201
  ${CMD_PREFIX_DESCRIPTION}`,
189
- inputSchema: zodToJsonSchema(ReadFileArgsSchema),
190
- annotations: {
191
- title: "Read File or URL",
192
- readOnlyHint: true,
193
- openWorldHint: true,
194
- },
202
+ inputSchema: zodToJsonSchema(ReadFileArgsSchema),
203
+ annotations: {
204
+ title: "Read File or URL",
205
+ readOnlyHint: true,
206
+ openWorldHint: true,
195
207
  },
196
- {
197
- name: "read_multiple_files",
198
- description: `
208
+ },
209
+ {
210
+ name: "read_multiple_files",
211
+ description: `
199
212
  Read the contents of multiple files simultaneously.
200
213
 
201
214
  Each file's content is returned with its path as a reference.
@@ -207,15 +220,15 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
207
220
 
208
221
  ${PATH_GUIDANCE}
209
222
  ${CMD_PREFIX_DESCRIPTION}`,
210
- inputSchema: zodToJsonSchema(ReadMultipleFilesArgsSchema),
211
- annotations: {
212
- title: "Read Multiple Files",
213
- readOnlyHint: true,
214
- },
223
+ inputSchema: zodToJsonSchema(ReadMultipleFilesArgsSchema),
224
+ annotations: {
225
+ title: "Read Multiple Files",
226
+ readOnlyHint: true,
215
227
  },
216
- {
217
- name: "write_file",
218
- description: `
228
+ },
229
+ {
230
+ name: "write_file",
231
+ description: `
219
232
  Write or append to file contents.
220
233
 
221
234
  CHUNKING IS STANDARD PRACTICE: Always write files in chunks of 25-30 lines maximum.
@@ -244,17 +257,17 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
244
257
 
245
258
  ${PATH_GUIDANCE}
246
259
  ${CMD_PREFIX_DESCRIPTION}`,
247
- inputSchema: zodToJsonSchema(WriteFileArgsSchema),
248
- annotations: {
249
- title: "Write File",
250
- readOnlyHint: false,
251
- destructiveHint: true,
252
- openWorldHint: false,
253
- },
260
+ inputSchema: zodToJsonSchema(WriteFileArgsSchema),
261
+ annotations: {
262
+ title: "Write File",
263
+ readOnlyHint: false,
264
+ destructiveHint: true,
265
+ openWorldHint: false,
254
266
  },
255
- {
256
- name: "create_directory",
257
- description: `
267
+ },
268
+ {
269
+ name: "create_directory",
270
+ description: `
258
271
  Create a new directory or ensure a directory exists.
259
272
 
260
273
  Can create multiple nested directories in one operation.
@@ -262,28 +275,49 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
262
275
 
263
276
  ${PATH_GUIDANCE}
264
277
  ${CMD_PREFIX_DESCRIPTION}`,
265
- inputSchema: zodToJsonSchema(CreateDirectoryArgsSchema),
266
- },
267
- {
268
- name: "list_directory",
269
- description: `
278
+ inputSchema: zodToJsonSchema(CreateDirectoryArgsSchema),
279
+ },
280
+ {
281
+ name: "list_directory",
282
+ description: `
270
283
  Get a detailed listing of all files and directories in a specified path.
271
284
 
272
285
  Use this instead of 'execute_command' with ls/dir commands.
273
286
  Results distinguish between files and directories with [FILE] and [DIR] prefixes.
287
+
288
+ Supports recursive listing with the 'depth' parameter (default: 2):
289
+ - depth=1: Only direct contents of the directory
290
+ - depth=2: Contents plus one level of subdirectories
291
+ - depth=3+: Multiple levels deep
292
+
293
+ CONTEXT OVERFLOW PROTECTION:
294
+ - Top-level directory shows ALL items
295
+ - Nested directories are limited to 100 items maximum per directory
296
+ - When a nested directory has more than 100 items, you'll see a warning like:
297
+ [WARNING] node_modules: 500 items hidden (showing first 100 of 600 total)
298
+ - This prevents overwhelming the context with large directories like node_modules
299
+
300
+ Results show full relative paths from the root directory being listed.
301
+ Example output with depth=2:
302
+ [DIR] src
303
+ [FILE] src/index.ts
304
+ [DIR] src/tools
305
+ [FILE] src/tools/filesystem.ts
306
+
307
+ If a directory cannot be accessed, it will show [DENIED] instead.
274
308
  Only works within allowed directories.
275
309
 
276
310
  ${PATH_GUIDANCE}
277
311
  ${CMD_PREFIX_DESCRIPTION}`,
278
- inputSchema: zodToJsonSchema(ListDirectoryArgsSchema),
279
- annotations: {
280
- title: "List Directory Contents",
281
- readOnlyHint: true,
282
- },
312
+ inputSchema: zodToJsonSchema(ListDirectoryArgsSchema),
313
+ annotations: {
314
+ title: "List Directory Contents",
315
+ readOnlyHint: true,
283
316
  },
284
- {
285
- name: "move_file",
286
- description: `
317
+ },
318
+ {
319
+ name: "move_file",
320
+ description: `
287
321
  Move or rename files and directories.
288
322
 
289
323
  Can move files between directories and rename them in a single operation.
@@ -291,17 +325,17 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
291
325
 
292
326
  ${PATH_GUIDANCE}
293
327
  ${CMD_PREFIX_DESCRIPTION}`,
294
- inputSchema: zodToJsonSchema(MoveFileArgsSchema),
295
- annotations: {
296
- title: "Move/Rename File",
297
- readOnlyHint: false,
298
- destructiveHint: true,
299
- openWorldHint: false,
300
- },
328
+ inputSchema: zodToJsonSchema(MoveFileArgsSchema),
329
+ annotations: {
330
+ title: "Move/Rename File",
331
+ readOnlyHint: false,
332
+ destructiveHint: true,
333
+ openWorldHint: false,
301
334
  },
302
- {
303
- name: "start_search",
304
- description: `
335
+ },
336
+ {
337
+ name: "start_search",
338
+ description: `
305
339
  Start a streaming search that can return results progressively.
306
340
 
307
341
  SEARCH STRATEGY GUIDE:
@@ -380,11 +414,11 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
380
414
 
381
415
  ${PATH_GUIDANCE}
382
416
  ${CMD_PREFIX_DESCRIPTION}`,
383
- inputSchema: zodToJsonSchema(StartSearchArgsSchema),
384
- },
385
- {
386
- name: "get_more_search_results",
387
- description: `
417
+ inputSchema: zodToJsonSchema(StartSearchArgsSchema),
418
+ },
419
+ {
420
+ name: "get_more_search_results",
421
+ description: `
388
422
  Get more results from an active search with offset-based pagination.
389
423
 
390
424
  Supports partial result reading with:
@@ -406,15 +440,15 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
406
440
  results from a search started with start_search.
407
441
 
408
442
  ${CMD_PREFIX_DESCRIPTION}`,
409
- inputSchema: zodToJsonSchema(GetMoreSearchResultsArgsSchema),
410
- annotations: {
411
- title: "Get Search Results",
412
- readOnlyHint: true,
413
- },
443
+ inputSchema: zodToJsonSchema(GetMoreSearchResultsArgsSchema),
444
+ annotations: {
445
+ title: "Get Search Results",
446
+ readOnlyHint: true,
414
447
  },
415
- {
416
- name: "stop_search",
417
- description: `
448
+ },
449
+ {
450
+ name: "stop_search",
451
+ description: `
418
452
  Stop an active search.
419
453
 
420
454
  Stops the background search process gracefully. Use this when you've found
@@ -425,11 +459,11 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
425
459
  automatically cleaned up after 5 minutes.
426
460
 
427
461
  ${CMD_PREFIX_DESCRIPTION}`,
428
- inputSchema: zodToJsonSchema(StopSearchArgsSchema),
429
- },
430
- {
431
- name: "list_searches",
432
- description: `
462
+ inputSchema: zodToJsonSchema(StopSearchArgsSchema),
463
+ },
464
+ {
465
+ name: "list_searches",
466
+ description: `
433
467
  List all active searches.
434
468
 
435
469
  Shows search IDs, search types, patterns, status, and runtime.
@@ -437,15 +471,15 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
437
471
  multiple concurrent searches.
438
472
 
439
473
  ${CMD_PREFIX_DESCRIPTION}`,
440
- inputSchema: zodToJsonSchema(ListSearchesArgsSchema),
441
- annotations: {
442
- title: "List Active Searches",
443
- readOnlyHint: true,
444
- },
474
+ inputSchema: zodToJsonSchema(ListSearchesArgsSchema),
475
+ annotations: {
476
+ title: "List Active Searches",
477
+ readOnlyHint: true,
445
478
  },
446
- {
447
- name: "get_file_info",
448
- description: `
479
+ },
480
+ {
481
+ name: "get_file_info",
482
+ description: `
449
483
  Retrieve detailed metadata about a file or directory including:
450
484
  - size
451
485
  - creation time
@@ -460,17 +494,17 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
460
494
 
461
495
  ${PATH_GUIDANCE}
462
496
  ${CMD_PREFIX_DESCRIPTION}`,
463
- inputSchema: zodToJsonSchema(GetFileInfoArgsSchema),
464
- annotations: {
465
- title: "Get File Information",
466
- readOnlyHint: true,
467
- },
497
+ inputSchema: zodToJsonSchema(GetFileInfoArgsSchema),
498
+ annotations: {
499
+ title: "Get File Information",
500
+ readOnlyHint: true,
468
501
  },
469
- // Note: list_allowed_directories removed - use get_config to check allowedDirectories
470
- // Text editing tools
471
- {
472
- name: "edit_block",
473
- description: `
502
+ },
503
+ // Note: list_allowed_directories removed - use get_config to check allowedDirectories
504
+ // Text editing tools
505
+ {
506
+ name: "edit_block",
507
+ description: `
474
508
  Apply surgical text replacements to files.
475
509
 
476
510
  BEST PRACTICE: Make multiple small, focused edits rather than one large edit.
@@ -503,18 +537,18 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
503
537
 
504
538
  ${PATH_GUIDANCE}
505
539
  ${CMD_PREFIX_DESCRIPTION}`,
506
- inputSchema: zodToJsonSchema(EditBlockArgsSchema),
507
- annotations: {
508
- title: "Edit Text Block",
509
- readOnlyHint: false,
510
- destructiveHint: true,
511
- openWorldHint: false,
512
- },
540
+ inputSchema: zodToJsonSchema(EditBlockArgsSchema),
541
+ annotations: {
542
+ title: "Edit Text Block",
543
+ readOnlyHint: false,
544
+ destructiveHint: true,
545
+ openWorldHint: false,
513
546
  },
514
- // Terminal tools
515
- {
516
- name: "start_process",
517
- description: `
547
+ },
548
+ // Terminal tools
549
+ {
550
+ name: "start_process",
551
+ description: `
518
552
  Start a new terminal process with intelligent state detection.
519
553
 
520
554
  PRIMARY TOOL FOR FILE ANALYSIS AND DATA PROCESSING
@@ -565,17 +599,17 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
565
599
 
566
600
  ${PATH_GUIDANCE}
567
601
  ${CMD_PREFIX_DESCRIPTION}`,
568
- inputSchema: zodToJsonSchema(StartProcessArgsSchema),
569
- annotations: {
570
- title: "Start Terminal Process",
571
- readOnlyHint: false,
572
- destructiveHint: true,
573
- openWorldHint: true,
574
- },
602
+ inputSchema: zodToJsonSchema(StartProcessArgsSchema),
603
+ annotations: {
604
+ title: "Start Terminal Process",
605
+ readOnlyHint: false,
606
+ destructiveHint: true,
607
+ openWorldHint: true,
575
608
  },
576
- {
577
- name: "read_process_output",
578
- description: `
609
+ },
610
+ {
611
+ name: "read_process_output",
612
+ description: `
579
613
  Read output from a running process with intelligent completion detection.
580
614
 
581
615
  Automatically detects when process is ready for more input instead of timing out.
@@ -598,15 +632,15 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
598
632
  Timeout reached (may still be running)
599
633
 
600
634
  ${CMD_PREFIX_DESCRIPTION}`,
601
- inputSchema: zodToJsonSchema(ReadProcessOutputArgsSchema),
602
- annotations: {
603
- title: "Read Process Output",
604
- readOnlyHint: true,
605
- },
635
+ inputSchema: zodToJsonSchema(ReadProcessOutputArgsSchema),
636
+ annotations: {
637
+ title: "Read Process Output",
638
+ readOnlyHint: true,
606
639
  },
607
- {
608
- name: "interact_with_process",
609
- description: `
640
+ },
641
+ {
642
+ name: "interact_with_process",
643
+ description: `
610
644
  Send input to a running process and automatically receive the response.
611
645
 
612
646
  CRITICAL: THIS IS THE PRIMARY TOOL FOR ALL LOCAL FILE ANALYSIS
@@ -654,31 +688,31 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
654
688
  NEVER USE ANALYSIS TOOL FOR: Local file access (it cannot read files from disk and WILL FAIL)
655
689
 
656
690
  ${CMD_PREFIX_DESCRIPTION}`,
657
- inputSchema: zodToJsonSchema(InteractWithProcessArgsSchema),
658
- annotations: {
659
- title: "Send Input to Process",
660
- readOnlyHint: false,
661
- destructiveHint: true,
662
- openWorldHint: true,
663
- },
691
+ inputSchema: zodToJsonSchema(InteractWithProcessArgsSchema),
692
+ annotations: {
693
+ title: "Send Input to Process",
694
+ readOnlyHint: false,
695
+ destructiveHint: true,
696
+ openWorldHint: true,
664
697
  },
665
- {
666
- name: "force_terminate",
667
- description: `
698
+ },
699
+ {
700
+ name: "force_terminate",
701
+ description: `
668
702
  Force terminate a running terminal session.
669
703
 
670
704
  ${CMD_PREFIX_DESCRIPTION}`,
671
- inputSchema: zodToJsonSchema(ForceTerminateArgsSchema),
672
- annotations: {
673
- title: "Force Terminate Process",
674
- readOnlyHint: false,
675
- destructiveHint: true,
676
- openWorldHint: false,
677
- },
705
+ inputSchema: zodToJsonSchema(ForceTerminateArgsSchema),
706
+ annotations: {
707
+ title: "Force Terminate Process",
708
+ readOnlyHint: false,
709
+ destructiveHint: true,
710
+ openWorldHint: false,
678
711
  },
679
- {
680
- name: "list_sessions",
681
- description: `
712
+ },
713
+ {
714
+ name: "list_sessions",
715
+ description: `
682
716
  List all active terminal sessions.
683
717
 
684
718
  Shows session status including:
@@ -692,59 +726,80 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
692
726
  - Long runtime with blocked status may indicate stuck process
693
727
 
694
728
  ${CMD_PREFIX_DESCRIPTION}`,
695
- inputSchema: zodToJsonSchema(ListSessionsArgsSchema),
696
- annotations: {
697
- title: "List Terminal Sessions",
698
- readOnlyHint: true,
699
- },
729
+ inputSchema: zodToJsonSchema(ListSessionsArgsSchema),
730
+ annotations: {
731
+ title: "List Terminal Sessions",
732
+ readOnlyHint: true,
700
733
  },
701
- {
702
- name: "list_processes",
703
- description: `
734
+ },
735
+ {
736
+ name: "list_processes",
737
+ description: `
704
738
  List all running processes.
705
739
 
706
740
  Returns process information including PID, command name, CPU usage, and memory usage.
707
741
 
708
742
  ${CMD_PREFIX_DESCRIPTION}`,
709
- inputSchema: zodToJsonSchema(ListProcessesArgsSchema),
710
- annotations: {
711
- title: "List Running Processes",
712
- readOnlyHint: true,
713
- },
743
+ inputSchema: zodToJsonSchema(ListProcessesArgsSchema),
744
+ annotations: {
745
+ title: "List Running Processes",
746
+ readOnlyHint: true,
714
747
  },
715
- {
716
- name: "kill_process",
717
- description: `
748
+ },
749
+ {
750
+ name: "kill_process",
751
+ description: `
718
752
  Terminate a running process by PID.
719
753
 
720
754
  Use with caution as this will forcefully terminate the specified process.
721
755
 
722
756
  ${CMD_PREFIX_DESCRIPTION}`,
723
- inputSchema: zodToJsonSchema(KillProcessArgsSchema),
724
- annotations: {
725
- title: "Kill Process",
726
- readOnlyHint: false,
727
- destructiveHint: true,
728
- openWorldHint: false,
729
- },
757
+ inputSchema: zodToJsonSchema(KillProcessArgsSchema),
758
+ annotations: {
759
+ title: "Kill Process",
760
+ readOnlyHint: false,
761
+ destructiveHint: true,
762
+ openWorldHint: false,
730
763
  },
731
- {
732
- name: "get_usage_stats",
733
- description: `
764
+ },
765
+ {
766
+ name: "get_usage_stats",
767
+ description: `
734
768
  Get usage statistics for debugging and analysis.
735
769
 
736
770
  Returns summary of tool usage, success/failure rates, and performance metrics.
737
771
 
738
772
  ${CMD_PREFIX_DESCRIPTION}`,
739
- inputSchema: zodToJsonSchema(GetUsageStatsArgsSchema),
740
- annotations: {
741
- title: "Get Usage Statistics",
742
- readOnlyHint: true,
743
- },
773
+ inputSchema: zodToJsonSchema(GetUsageStatsArgsSchema),
774
+ annotations: {
775
+ title: "Get Usage Statistics",
776
+ readOnlyHint: true,
744
777
  },
745
- {
746
- name: "give_feedback_to_desktop_commander",
747
- description: `
778
+ },
779
+ {
780
+ name: "get_recent_tool_calls",
781
+ description: `
782
+ Get recent tool call history with their arguments and outputs.
783
+ Returns chronological list of tool calls made during this session.
784
+
785
+ Useful for:
786
+ - Onboarding new chats about work already done
787
+ - Recovering context after chat history loss
788
+ - Debugging tool call sequences
789
+
790
+ Note: Does not track its own calls or other meta/query tools.
791
+ History kept in memory (last 1000 calls, lost on restart).
792
+
793
+ ${CMD_PREFIX_DESCRIPTION}`,
794
+ inputSchema: zodToJsonSchema(GetRecentToolCallsArgsSchema),
795
+ annotations: {
796
+ title: "Get Recent Tool Calls",
797
+ readOnlyHint: true,
798
+ },
799
+ },
800
+ {
801
+ name: "give_feedback_to_desktop_commander",
802
+ description: `
748
803
  Open feedback form in browser to provide feedback about Desktop Commander.
749
804
 
750
805
  IMPORTANT: This tool simply opens the feedback form - no pre-filling available.
@@ -777,11 +832,11 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
777
832
  No parameters are needed - just call the tool to open the form.
778
833
 
779
834
  ${CMD_PREFIX_DESCRIPTION}`,
780
- inputSchema: zodToJsonSchema(GiveFeedbackArgsSchema),
781
- },
782
- {
783
- name: "get_prompts",
784
- description: `
835
+ inputSchema: zodToJsonSchema(GiveFeedbackArgsSchema),
836
+ },
837
+ {
838
+ name: "get_prompts",
839
+ description: `
785
840
  Browse and retrieve curated Desktop Commander prompts for various tasks and workflows.
786
841
 
787
842
  IMPORTANT: When displaying prompt lists to users, do NOT show the internal prompt IDs (like 'onb_001').
@@ -811,9 +866,14 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
811
866
  Perfect for discovering proven workflows and getting started with Desktop Commander.
812
867
 
813
868
  ${CMD_PREFIX_DESCRIPTION}`,
814
- inputSchema: zodToJsonSchema(GetPromptsArgsSchema),
815
- },
816
- ],
869
+ inputSchema: zodToJsonSchema(GetPromptsArgsSchema),
870
+ },
871
+ ];
872
+ // Filter tools based on current client
873
+ const filteredTools = allTools.filter(tool => shouldIncludeTool(tool.name));
874
+ logToStderr('debug', `Returning ${filteredTools.length} tools (filtered from ${allTools.length} total) for client: ${currentClient?.name || 'unknown'}`);
875
+ return {
876
+ tools: filteredTools,
817
877
  };
818
878
  }
819
879
  catch (error) {
@@ -824,6 +884,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
824
884
  import * as handlers from './handlers/index.js';
825
885
  server.setRequestHandler(CallToolRequestSchema, async (request) => {
826
886
  const { name, arguments: args } = request.params;
887
+ const startTime = Date.now();
827
888
  try {
828
889
  // Prepare telemetry data - add config key for set_config_value
829
890
  const telemetryData = { name };
@@ -960,6 +1021,18 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
960
1021
  };
961
1022
  }
962
1023
  break;
1024
+ case "get_recent_tool_calls":
1025
+ try {
1026
+ result = await handlers.handleGetRecentToolCalls(args);
1027
+ }
1028
+ catch (error) {
1029
+ capture('server_request_error', { message: `Error in get_recent_tool_calls handler: ${error}` });
1030
+ result = {
1031
+ content: [{ type: "text", text: `Error: Failed to get tool call history` }],
1032
+ isError: true,
1033
+ };
1034
+ }
1035
+ break;
963
1036
  case "give_feedback_to_desktop_commander":
964
1037
  try {
965
1038
  result = await giveFeedbackToDesktopCommander(args);
@@ -1040,6 +1113,14 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
1040
1113
  isError: true,
1041
1114
  };
1042
1115
  }
1116
+ // Add tool call to history (exclude only get_recent_tool_calls to prevent recursion)
1117
+ const duration = Date.now() - startTime;
1118
+ const EXCLUDED_TOOLS = [
1119
+ 'get_recent_tool_calls'
1120
+ ];
1121
+ if (!EXCLUDED_TOOLS.includes(name)) {
1122
+ toolHistory.addCall(name, args, result, duration);
1123
+ }
1043
1124
  // Track success or failure based on result
1044
1125
  if (result.isError) {
1045
1126
  await usageTracker.trackFailure(name);