@wonderwhy-er/desktop-commander 0.1.32 → 0.1.34

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.
@@ -0,0 +1,7 @@
1
+ import { ServerResult } from './types.js';
2
+ /**
3
+ * Creates a standard error response for tools
4
+ * @param message The error message
5
+ * @returns A ServerResult with the error message
6
+ */
7
+ export declare function createErrorResponse(message: string): ServerResult;
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Creates a standard error response for tools
3
+ * @param message The error message
4
+ * @returns A ServerResult with the error message
5
+ */
6
+ export function createErrorResponse(message) {
7
+ return {
8
+ content: [{ type: "text", text: `Error: ${message}` }],
9
+ isError: true,
10
+ };
11
+ }
@@ -1,27 +1,13 @@
1
+ import { ServerResult } from '../types.js';
1
2
  /**
2
3
  * Handle block_command command
3
4
  */
4
- export declare function handleBlockCommand(args: unknown): Promise<{
5
- content: {
6
- type: string;
7
- text: boolean;
8
- }[];
9
- }>;
5
+ export declare function handleBlockCommand(args: unknown): Promise<ServerResult>;
10
6
  /**
11
7
  * Handle unblock_command command
12
8
  */
13
- export declare function handleUnblockCommand(args: unknown): Promise<{
14
- content: {
15
- type: string;
16
- text: boolean;
17
- }[];
18
- }>;
9
+ export declare function handleUnblockCommand(args: unknown): Promise<ServerResult>;
19
10
  /**
20
11
  * Handle list_blocked_commands command
21
12
  */
22
- export declare function handleListBlockedCommands(): {
23
- content: {
24
- type: string;
25
- text: string;
26
- }[];
27
- };
13
+ export declare function handleListBlockedCommands(): ServerResult;
@@ -6,8 +6,12 @@ import { BlockCommandArgsSchema, UnblockCommandArgsSchema } from '../tools/schem
6
6
  export async function handleBlockCommand(args) {
7
7
  const parsed = BlockCommandArgsSchema.parse(args);
8
8
  const blockResult = await commandManager.blockCommand(parsed.command);
9
+ // Convert boolean result to appropriate message string
10
+ const message = blockResult
11
+ ? `Successfully blocked command: ${parsed.command}`
12
+ : `Command is already blocked: ${parsed.command}`;
9
13
  return {
10
- content: [{ type: "text", text: blockResult }],
14
+ content: [{ type: "text", text: message }],
11
15
  };
12
16
  }
13
17
  /**
@@ -16,8 +20,12 @@ export async function handleBlockCommand(args) {
16
20
  export async function handleUnblockCommand(args) {
17
21
  const parsed = UnblockCommandArgsSchema.parse(args);
18
22
  const unblockResult = await commandManager.unblockCommand(parsed.command);
23
+ // Convert boolean result to appropriate message string
24
+ const message = unblockResult
25
+ ? `Successfully unblocked command: ${parsed.command}`
26
+ : `Command is not blocked or doesn't exist: ${parsed.command}`;
19
27
  return {
20
- content: [{ type: "text", text: unblockResult }],
28
+ content: [{ type: "text", text: message }],
21
29
  };
22
30
  }
23
31
  /**
@@ -25,7 +33,11 @@ export async function handleUnblockCommand(args) {
25
33
  */
26
34
  export function handleListBlockedCommands() {
27
35
  const blockedCommands = commandManager.listBlockedCommands();
36
+ // Create appropriate message based on whether there are blocked commands
37
+ const message = blockedCommands.length > 0
38
+ ? `Blocked commands:\n${blockedCommands.join('\n')}`
39
+ : "No commands are currently blocked.";
28
40
  return {
29
- content: [{ type: "text", text: blockedCommands.join('\n') }],
41
+ content: [{ type: "text", text: message }],
30
42
  };
31
43
  }
@@ -1,18 +1,9 @@
1
+ import { ServerResult } from '../types.js';
1
2
  /**
2
3
  * Handle edit_block command
3
4
  */
4
- export declare function handleEditBlock(args: unknown): Promise<{
5
- content: {
6
- type: string;
7
- text: string;
8
- }[];
9
- }>;
5
+ export declare function handleEditBlock(args: unknown): Promise<ServerResult>;
10
6
  /**
11
7
  * Handle search_code command
12
8
  */
13
- export declare function handleSearchCode(args: unknown): Promise<{
14
- content: {
15
- type: string;
16
- text: string;
17
- }[];
18
- }>;
9
+ export declare function handleSearchCode(args: unknown): Promise<ServerResult>;
@@ -2,16 +2,23 @@ import { parseEditBlock, performSearchReplace } from '../tools/edit.js';
2
2
  import { searchTextInFiles } from '../tools/search.js';
3
3
  import { EditBlockArgsSchema, SearchCodeArgsSchema } from '../tools/schemas.js';
4
4
  import { withTimeout } from '../utils.js';
5
+ import { createErrorResponse } from '../error-handlers.js';
5
6
  /**
6
7
  * Handle edit_block command
7
8
  */
8
9
  export async function handleEditBlock(args) {
9
- const parsed = EditBlockArgsSchema.parse(args);
10
- const { filePath, searchReplace } = await parseEditBlock(parsed.blockContent);
11
- await performSearchReplace(filePath, searchReplace);
12
- return {
13
- content: [{ type: "text", text: `Successfully applied edit to ${filePath}` }],
14
- };
10
+ try {
11
+ const parsed = EditBlockArgsSchema.parse(args);
12
+ const { filePath, searchReplace, error } = await parseEditBlock(parsed.blockContent);
13
+ if (error) {
14
+ return createErrorResponse(error);
15
+ }
16
+ return performSearchReplace(filePath, searchReplace);
17
+ }
18
+ catch (error) {
19
+ const errorMessage = error instanceof Error ? error.message : String(error);
20
+ return createErrorResponse(errorMessage);
21
+ }
15
22
  }
16
23
  /**
17
24
  * Handle search_code command
@@ -1,90 +1,37 @@
1
+ import { ServerResult } from '../types.js';
1
2
  /**
2
3
  * Handle read_file command
3
4
  */
4
- export declare function handleReadFile(args: unknown): Promise<{
5
- content: ({
6
- type: string;
7
- text: string;
8
- data?: undefined;
9
- mimeType?: undefined;
10
- } | {
11
- type: string;
12
- data: string;
13
- mimeType: string;
14
- text?: undefined;
15
- })[];
16
- }>;
5
+ export declare function handleReadFile(args: unknown): Promise<ServerResult>;
17
6
  /**
18
7
  * Handle read_multiple_files command
19
8
  */
20
- export declare function handleReadMultipleFiles(args: unknown): Promise<{
21
- content: {
22
- type: string;
23
- text?: string;
24
- data?: string;
25
- mimeType?: string;
26
- }[];
27
- }>;
9
+ export declare function handleReadMultipleFiles(args: unknown): Promise<ServerResult>;
28
10
  /**
29
11
  * Handle write_file command
30
12
  */
31
- export declare function handleWriteFile(args: unknown): Promise<{
32
- content: {
33
- type: string;
34
- text: string;
35
- }[];
36
- }>;
13
+ export declare function handleWriteFile(args: unknown): Promise<ServerResult>;
37
14
  /**
38
15
  * Handle create_directory command
39
16
  */
40
- export declare function handleCreateDirectory(args: unknown): Promise<{
41
- content: {
42
- type: string;
43
- text: string;
44
- }[];
45
- }>;
17
+ export declare function handleCreateDirectory(args: unknown): Promise<ServerResult>;
46
18
  /**
47
19
  * Handle list_directory command
48
20
  */
49
- export declare function handleListDirectory(args: unknown): Promise<{
50
- content: {
51
- type: string;
52
- text: string;
53
- }[];
54
- }>;
21
+ export declare function handleListDirectory(args: unknown): Promise<ServerResult>;
55
22
  /**
56
23
  * Handle move_file command
57
24
  */
58
- export declare function handleMoveFile(args: unknown): Promise<{
59
- content: {
60
- type: string;
61
- text: string;
62
- }[];
63
- }>;
25
+ export declare function handleMoveFile(args: unknown): Promise<ServerResult>;
64
26
  /**
65
27
  * Handle search_files command
66
28
  */
67
- export declare function handleSearchFiles(args: unknown): Promise<{
68
- content: {
69
- type: string;
70
- text: string;
71
- }[];
72
- }>;
29
+ export declare function handleSearchFiles(args: unknown): Promise<ServerResult>;
73
30
  /**
74
31
  * Handle get_file_info command
75
32
  */
76
- export declare function handleGetFileInfo(args: unknown): Promise<{
77
- content: {
78
- type: string;
79
- text: string;
80
- }[];
81
- }>;
33
+ export declare function handleGetFileInfo(args: unknown): Promise<ServerResult>;
82
34
  /**
83
35
  * Handle list_allowed_directories command
84
36
  */
85
- export declare function handleListAllowedDirectories(): {
86
- content: {
87
- type: string;
88
- text: string;
89
- }[];
90
- };
37
+ export declare function handleListAllowedDirectories(): ServerResult;
@@ -1,6 +1,19 @@
1
1
  import { readFile, readMultipleFiles, writeFile, createDirectory, listDirectory, moveFile, searchFiles, getFileInfo, listAllowedDirectories } from '../tools/filesystem.js';
2
2
  import { withTimeout } from '../utils.js';
3
+ import { createErrorResponse } from '../error-handlers.js';
3
4
  import { ReadFileArgsSchema, ReadMultipleFilesArgsSchema, WriteFileArgsSchema, CreateDirectoryArgsSchema, ListDirectoryArgsSchema, MoveFileArgsSchema, SearchFilesArgsSchema, GetFileInfoArgsSchema } from '../tools/schemas.js';
5
+ /**
6
+ * Helper function to check if path contains an error
7
+ */
8
+ function isErrorPath(path) {
9
+ return path.startsWith('__ERROR__:');
10
+ }
11
+ /**
12
+ * Extract error message from error path
13
+ */
14
+ function getErrorFromPath(path) {
15
+ return path.substring('__ERROR__:'.length).trim();
16
+ }
4
17
  /**
5
18
  * Handle read_file command
6
19
  */
@@ -86,84 +99,120 @@ export async function handleReadMultipleFiles(args) {
86
99
  * Handle write_file command
87
100
  */
88
101
  export async function handleWriteFile(args) {
89
- const parsed = WriteFileArgsSchema.parse(args);
90
- await writeFile(parsed.path, parsed.content);
91
- return {
92
- content: [{ type: "text", text: `Successfully wrote to ${parsed.path}` }],
93
- };
102
+ try {
103
+ const parsed = WriteFileArgsSchema.parse(args);
104
+ await writeFile(parsed.path, parsed.content);
105
+ return {
106
+ content: [{ type: "text", text: `Successfully wrote to ${parsed.path}` }],
107
+ };
108
+ }
109
+ catch (error) {
110
+ const errorMessage = error instanceof Error ? error.message : String(error);
111
+ return createErrorResponse(errorMessage);
112
+ }
94
113
  }
95
114
  /**
96
115
  * Handle create_directory command
97
116
  */
98
117
  export async function handleCreateDirectory(args) {
99
- const parsed = CreateDirectoryArgsSchema.parse(args);
100
- await createDirectory(parsed.path);
101
- return {
102
- content: [{ type: "text", text: `Successfully created directory ${parsed.path}` }],
103
- };
118
+ try {
119
+ const parsed = CreateDirectoryArgsSchema.parse(args);
120
+ await createDirectory(parsed.path);
121
+ return {
122
+ content: [{ type: "text", text: `Successfully created directory ${parsed.path}` }],
123
+ };
124
+ }
125
+ catch (error) {
126
+ const errorMessage = error instanceof Error ? error.message : String(error);
127
+ return createErrorResponse(errorMessage);
128
+ }
104
129
  }
105
130
  /**
106
131
  * Handle list_directory command
107
132
  */
108
133
  export async function handleListDirectory(args) {
109
- const parsed = ListDirectoryArgsSchema.parse(args);
110
- const entries = await listDirectory(parsed.path);
111
- return {
112
- content: [{ type: "text", text: entries.join('\n') }],
113
- };
134
+ try {
135
+ const parsed = ListDirectoryArgsSchema.parse(args);
136
+ const entries = await listDirectory(parsed.path);
137
+ return {
138
+ content: [{ type: "text", text: entries.join('\n') }],
139
+ };
140
+ }
141
+ catch (error) {
142
+ const errorMessage = error instanceof Error ? error.message : String(error);
143
+ return createErrorResponse(errorMessage);
144
+ }
114
145
  }
115
146
  /**
116
147
  * Handle move_file command
117
148
  */
118
149
  export async function handleMoveFile(args) {
119
- const parsed = MoveFileArgsSchema.parse(args);
120
- await moveFile(parsed.source, parsed.destination);
121
- return {
122
- content: [{ type: "text", text: `Successfully moved ${parsed.source} to ${parsed.destination}` }],
123
- };
150
+ try {
151
+ const parsed = MoveFileArgsSchema.parse(args);
152
+ await moveFile(parsed.source, parsed.destination);
153
+ return {
154
+ content: [{ type: "text", text: `Successfully moved ${parsed.source} to ${parsed.destination}` }],
155
+ };
156
+ }
157
+ catch (error) {
158
+ const errorMessage = error instanceof Error ? error.message : String(error);
159
+ return createErrorResponse(errorMessage);
160
+ }
124
161
  }
125
162
  /**
126
163
  * Handle search_files command
127
164
  */
128
165
  export async function handleSearchFiles(args) {
129
- const parsed = SearchFilesArgsSchema.parse(args);
130
- const timeoutMs = parsed.timeoutMs || 30000; // 30 seconds default
131
- // Apply timeout at the handler level
132
- const searchOperation = async () => {
133
- return await searchFiles(parsed.path, parsed.pattern);
134
- };
135
- // Use withTimeout at the handler level
136
- const results = await withTimeout(searchOperation(), timeoutMs, 'File search operation', [] // Empty array as default on timeout
137
- );
138
- if (results.length === 0) {
139
- // Similar approach as in handleSearchCode
140
- if (timeoutMs > 0) {
166
+ try {
167
+ const parsed = SearchFilesArgsSchema.parse(args);
168
+ const timeoutMs = parsed.timeoutMs || 30000; // 30 seconds default
169
+ // Apply timeout at the handler level
170
+ const searchOperation = async () => {
171
+ return await searchFiles(parsed.path, parsed.pattern);
172
+ };
173
+ // Use withTimeout at the handler level
174
+ const results = await withTimeout(searchOperation(), timeoutMs, 'File search operation', [] // Empty array as default on timeout
175
+ );
176
+ if (results.length === 0) {
177
+ // Similar approach as in handleSearchCode
178
+ if (timeoutMs > 0) {
179
+ return {
180
+ content: [{ type: "text", text: `No matches found or search timed out after ${timeoutMs}ms.` }],
181
+ };
182
+ }
141
183
  return {
142
- content: [{ type: "text", text: `No matches found or search timed out after ${timeoutMs}ms.` }],
184
+ content: [{ type: "text", text: "No matches found" }],
143
185
  };
144
186
  }
145
187
  return {
146
- content: [{ type: "text", text: "No matches found" }],
188
+ content: [{ type: "text", text: results.join('\n') }],
147
189
  };
148
190
  }
149
- return {
150
- content: [{ type: "text", text: results.join('\n') }],
151
- };
191
+ catch (error) {
192
+ const errorMessage = error instanceof Error ? error.message : String(error);
193
+ return createErrorResponse(errorMessage);
194
+ }
152
195
  }
153
196
  /**
154
197
  * Handle get_file_info command
155
198
  */
156
199
  export async function handleGetFileInfo(args) {
157
- const parsed = GetFileInfoArgsSchema.parse(args);
158
- const info = await getFileInfo(parsed.path);
159
- return {
160
- content: [{
161
- type: "text",
162
- text: Object.entries(info)
163
- .map(([key, value]) => `${key}: ${value}`)
164
- .join('\n')
165
- }],
166
- };
200
+ try {
201
+ const parsed = GetFileInfoArgsSchema.parse(args);
202
+ const info = await getFileInfo(parsed.path);
203
+ return {
204
+ content: [{
205
+ type: "text",
206
+ text: Object.entries(info)
207
+ .map(([key, value]) => `${key}: ${value}`)
208
+ .join('\n')
209
+ }],
210
+ };
211
+ }
212
+ catch (error) {
213
+ const errorMessage = error instanceof Error ? error.message : String(error);
214
+ return createErrorResponse(errorMessage);
215
+ }
167
216
  }
168
217
  /**
169
218
  * Handle list_allowed_directories command
@@ -1,18 +1,9 @@
1
+ import { ServerResult } from '../types.js';
1
2
  /**
2
3
  * Handle list_processes command
3
4
  */
4
- export declare function handleListProcesses(): Promise<{
5
- content: Array<{
6
- type: string;
7
- text: string;
8
- }>;
9
- }>;
5
+ export declare function handleListProcesses(): Promise<ServerResult>;
10
6
  /**
11
7
  * Handle kill_process command
12
8
  */
13
- export declare function handleKillProcess(args: unknown): Promise<{
14
- content: {
15
- type: string;
16
- text: string;
17
- }[];
18
- }>;
9
+ export declare function handleKillProcess(args: unknown): Promise<ServerResult>;
@@ -1,36 +1,17 @@
1
+ import { ServerResult } from '../types.js';
1
2
  /**
2
3
  * Handle execute_command command
3
4
  */
4
- export declare function handleExecuteCommand(args: unknown): Promise<{
5
- content: {
6
- type: string;
7
- text: string;
8
- }[];
9
- }>;
5
+ export declare function handleExecuteCommand(args: unknown): Promise<ServerResult>;
10
6
  /**
11
7
  * Handle read_output command
12
8
  */
13
- export declare function handleReadOutput(args: unknown): Promise<{
14
- content: {
15
- type: string;
16
- text: string;
17
- }[];
18
- }>;
9
+ export declare function handleReadOutput(args: unknown): Promise<ServerResult>;
19
10
  /**
20
11
  * Handle force_terminate command
21
12
  */
22
- export declare function handleForceTerminate(args: unknown): Promise<{
23
- content: {
24
- type: string;
25
- text: string;
26
- }[];
27
- }>;
13
+ export declare function handleForceTerminate(args: unknown): Promise<ServerResult>;
28
14
  /**
29
15
  * Handle list_sessions command
30
16
  */
31
- export declare function handleListSessions(): Promise<{
32
- content: {
33
- type: string;
34
- text: string;
35
- }[];
36
- }>;
17
+ export declare function handleListSessions(): Promise<ServerResult>;
package/dist/server.js CHANGED
@@ -231,7 +231,10 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
231
231
  return handlers.handleEditBlock(args);
232
232
  default:
233
233
  capture('server_unknown_tool', { name });
234
- throw new Error(`Unknown tool: ${name}`);
234
+ return {
235
+ content: [{ type: "text", text: `Error: Unknown tool: ${name}` }],
236
+ isError: true,
237
+ };
235
238
  }
236
239
  }
237
240
  catch (error) {
@@ -339,7 +339,7 @@ export default async function setup() {
339
339
  isWindows ?
340
340
  join(process.env.APPDATA || '', "npm", "npx.cmd").replace(/\\/g, '\\\\') :
341
341
  "$(which npx)",
342
- "@wonderwhy-er/desktop-commander"
342
+ "@wonderwhy-er/desktop-commander@latest"
343
343
  ],
344
344
  "env": debugEnv
345
345
  };
@@ -368,7 +368,7 @@ export default async function setup() {
368
368
  serverConfig = {
369
369
  "command": isWindows ? "npx.cmd" : "npx",
370
370
  "args": [
371
- "@wonderwhy-er/desktop-commander"
371
+ "@wonderwhy-er/desktop-commander@latest"
372
372
  ]
373
373
  };
374
374
  } else {
@@ -10,7 +10,12 @@ export class TerminalManager {
10
10
  let output = '';
11
11
  // Ensure process.pid is defined before proceeding
12
12
  if (!process.pid) {
13
- throw new Error('Failed to get process ID');
13
+ // Return a consistent error object instead of throwing
14
+ return {
15
+ pid: -1, // Use -1 to indicate an error state
16
+ output: 'Error: Failed to get process ID. The command could not be executed.',
17
+ isBlocked: false
18
+ };
14
19
  }
15
20
  const session = {
16
21
  pid: process.pid,
@@ -1,10 +1,12 @@
1
+ import { ServerResult } from '../types.js';
1
2
  interface SearchReplace {
2
3
  search: string;
3
4
  replace: string;
4
5
  }
5
- export declare function performSearchReplace(filePath: string, block: SearchReplace): Promise<void>;
6
+ export declare function performSearchReplace(filePath: string, block: SearchReplace): Promise<ServerResult>;
6
7
  export declare function parseEditBlock(blockContent: string): Promise<{
7
8
  filePath: string;
8
9
  searchReplace: SearchReplace;
10
+ error?: string;
9
11
  }>;
10
12
  export {};
@@ -7,13 +7,18 @@ export async function performSearchReplace(filePath, block) {
7
7
  // Find first occurrence
8
8
  const searchIndex = contentStr.indexOf(block.search);
9
9
  if (searchIndex === -1) {
10
- throw new Error(`Search content not found in ${filePath}`);
10
+ return {
11
+ content: [{ type: "text", text: `Search content not found in ${filePath}.` }],
12
+ };
11
13
  }
12
14
  // Replace content
13
15
  const newContent = contentStr.substring(0, searchIndex) +
14
16
  block.replace +
15
17
  contentStr.substring(searchIndex + block.search.length);
16
18
  await writeFile(filePath, newContent);
19
+ return {
20
+ content: [{ type: "text", text: `Successfully applied edit to ${filePath}` }],
21
+ };
17
22
  }
18
23
  export async function parseEditBlock(blockContent) {
19
24
  const lines = blockContent.split('\n');
@@ -24,7 +29,11 @@ export async function parseEditBlock(blockContent) {
24
29
  const divider = lines.indexOf('=======');
25
30
  const replaceEnd = lines.indexOf('>>>>>>> REPLACE');
26
31
  if (searchStart === -1 || divider === -1 || replaceEnd === -1) {
27
- throw new Error('Invalid edit block format - missing markers');
32
+ return {
33
+ filePath: '',
34
+ searchReplace: { search: '', replace: '' },
35
+ error: 'Invalid edit block format - missing markers'
36
+ };
28
37
  }
29
38
  // Extract search and replace content
30
39
  const search = lines.slice(searchStart + 1, divider).join('\n');
@@ -1,21 +1,7 @@
1
- export declare function executeCommand(args: unknown): Promise<{
2
- content: {
3
- type: string;
4
- text: string;
5
- }[];
6
- }>;
7
- export declare function readOutput(args: unknown): Promise<{
8
- content: {
9
- type: string;
10
- text: string;
11
- }[];
12
- }>;
13
- export declare function forceTerminate(args: unknown): Promise<{
14
- content: {
15
- type: string;
16
- text: string;
17
- }[];
18
- }>;
1
+ import { ServerResult } from '../types.js';
2
+ export declare function executeCommand(args: unknown): Promise<ServerResult>;
3
+ export declare function readOutput(args: unknown): Promise<ServerResult>;
4
+ export declare function forceTerminate(args: unknown): Promise<ServerResult>;
19
5
  export declare function listSessions(): Promise<{
20
6
  content: {
21
7
  type: string;
@@ -6,7 +6,10 @@ export async function executeCommand(args) {
6
6
  const parsed = ExecuteCommandArgsSchema.safeParse(args);
7
7
  if (!parsed.success) {
8
8
  capture('server_execute_command_failed');
9
- throw new Error(`Invalid arguments for execute_command: ${parsed.error}`);
9
+ return {
10
+ content: [{ type: "text", text: `Error: Invalid arguments for execute_command: ${parsed.error}` }],
11
+ isError: true,
12
+ };
10
13
  }
11
14
  try {
12
15
  // Extract all commands for analytics while ensuring execution continues even if parsing fails
@@ -25,9 +28,19 @@ export async function executeCommand(args) {
25
28
  console.error('Error during command extraction:', error);
26
29
  }
27
30
  if (!commandManager.validateCommand(parsed.data.command)) {
28
- throw new Error(`Command not allowed: ${parsed.data.command}`);
31
+ return {
32
+ content: [{ type: "text", text: `Error: Command not allowed: ${parsed.data.command}` }],
33
+ isError: true,
34
+ };
29
35
  }
30
36
  const result = await terminalManager.executeCommand(parsed.data.command, parsed.data.timeout_ms);
37
+ // Check for error condition (pid = -1)
38
+ if (result.pid === -1) {
39
+ return {
40
+ content: [{ type: "text", text: result.output }],
41
+ isError: true,
42
+ };
43
+ }
31
44
  return {
32
45
  content: [{
33
46
  type: "text",
@@ -38,7 +51,10 @@ export async function executeCommand(args) {
38
51
  export async function readOutput(args) {
39
52
  const parsed = ReadOutputArgsSchema.safeParse(args);
40
53
  if (!parsed.success) {
41
- throw new Error(`Invalid arguments for read_output: ${parsed.error}`);
54
+ return {
55
+ content: [{ type: "text", text: `Error: Invalid arguments for read_output: ${parsed.error}` }],
56
+ isError: true,
57
+ };
42
58
  }
43
59
  const output = terminalManager.getNewOutput(parsed.data.pid);
44
60
  return {
@@ -53,7 +69,10 @@ export async function readOutput(args) {
53
69
  export async function forceTerminate(args) {
54
70
  const parsed = ForceTerminateArgsSchema.safeParse(args);
55
71
  if (!parsed.success) {
56
- throw new Error(`Invalid arguments for force_terminate: ${parsed.error}`);
72
+ return {
73
+ content: [{ type: "text", text: `Error: Invalid arguments for force_terminate: ${parsed.error}` }],
74
+ isError: true,
75
+ };
57
76
  }
58
77
  const success = terminalManager.forceTerminate(parsed.data.pid);
59
78
  return {
@@ -87,7 +87,8 @@ export async function validatePath(requestedPath) {
87
87
  // Execute with timeout
88
88
  const result = await withTimeout(validationOperation(), PATH_VALIDATION_TIMEOUT, `Path validation for ${requestedPath}`, null);
89
89
  if (result === null) {
90
- throw new Error(`Path validation timed out after ${PATH_VALIDATION_TIMEOUT / 1000} seconds for: ${requestedPath}`);
90
+ // Return a path with an error indicator instead of throwing
91
+ return `__ERROR__: Path validation timed out after ${PATH_VALIDATION_TIMEOUT / 1000} seconds for: ${requestedPath}`;
91
92
  }
92
93
  return result;
93
94
  }
@@ -141,11 +142,20 @@ export async function readFileFromUrl(url, returnMetadata) {
141
142
  catch (error) {
142
143
  // Clear the timeout to prevent memory leaks
143
144
  clearTimeout(timeoutId);
144
- // Improve error message for timeout/abort cases
145
- if (error instanceof DOMException && error.name === 'AbortError') {
146
- throw new Error(`URL fetch timed out after ${FETCH_TIMEOUT_MS}ms: ${url}`);
145
+ // Return error information instead of throwing
146
+ const errorMessage = error instanceof DOMException && error.name === 'AbortError'
147
+ ? `URL fetch timed out after ${FETCH_TIMEOUT_MS}ms: ${url}`
148
+ : `Failed to fetch URL: ${error instanceof Error ? error.message : String(error)}`;
149
+ if (returnMetadata === true) {
150
+ return {
151
+ content: `Error: ${errorMessage}`,
152
+ mimeType: 'text/plain',
153
+ isImage: false
154
+ };
155
+ }
156
+ else {
157
+ return `Error: ${errorMessage}`;
147
158
  }
148
- throw new Error(`Failed to fetch URL: ${error instanceof Error ? error.message : String(error)}`);
149
159
  }
150
160
  }
151
161
  /**
@@ -1,12 +1,3 @@
1
- export declare function listProcesses(): Promise<{
2
- content: Array<{
3
- type: string;
4
- text: string;
5
- }>;
6
- }>;
7
- export declare function killProcess(args: unknown): Promise<{
8
- content: {
9
- type: string;
10
- text: string;
11
- }[];
12
- }>;
1
+ import { ServerResult } from '../types.js';
2
+ export declare function listProcesses(): Promise<ServerResult>;
3
+ export declare function killProcess(args: unknown): Promise<ServerResult>;
@@ -27,13 +27,19 @@ export async function listProcesses() {
27
27
  };
28
28
  }
29
29
  catch (error) {
30
- throw new Error('Failed to list processes');
30
+ return {
31
+ content: [{ type: "text", text: `Error: Failed to list processes: ${error instanceof Error ? error.message : String(error)}` }],
32
+ isError: true,
33
+ };
31
34
  }
32
35
  }
33
36
  export async function killProcess(args) {
34
37
  const parsed = KillProcessArgsSchema.safeParse(args);
35
38
  if (!parsed.success) {
36
- throw new Error(`Invalid arguments for kill_process: ${parsed.error}`);
39
+ return {
40
+ content: [{ type: "text", text: `Error: Invalid arguments for kill_process: ${parsed.error}` }],
41
+ isError: true,
42
+ };
37
43
  }
38
44
  try {
39
45
  process.kill(parsed.data.pid);
@@ -42,6 +48,9 @@ export async function killProcess(args) {
42
48
  };
43
49
  }
44
50
  catch (error) {
45
- throw new Error(`Failed to kill process: ${error instanceof Error ? error.message : String(error)}`);
51
+ return {
52
+ content: [{ type: "text", text: `Error: Failed to kill process: ${error instanceof Error ? error.message : String(error)}` }],
53
+ isError: true,
54
+ };
46
55
  }
47
56
  }
package/dist/types.d.ts CHANGED
@@ -29,3 +29,15 @@ export interface CompletedSession {
29
29
  startTime: Date;
30
30
  endTime: Date;
31
31
  }
32
+ export interface ServerResponseContent {
33
+ type: string;
34
+ text?: string;
35
+ data?: string;
36
+ mimeType?: string;
37
+ }
38
+ export interface ServerResult {
39
+ content: ServerResponseContent[];
40
+ isError?: boolean;
41
+ _meta?: Record<string, unknown>;
42
+ }
43
+ export type ToolHandler<T = unknown> = (args: T) => Promise<ServerResult>;
package/dist/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const VERSION = "0.1.32";
1
+ export declare const VERSION = "0.1.34";
package/dist/version.js CHANGED
@@ -1 +1 @@
1
- export const VERSION = '0.1.32';
1
+ export const VERSION = '0.1.34';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wonderwhy-er/desktop-commander",
3
- "version": "0.1.32",
3
+ "version": "0.1.34",
4
4
  "description": "MCP server for terminal operations and file editing",
5
5
  "license": "MIT",
6
6
  "author": "Eduards Ruzga",