@wonderwhy-er/desktop-commander 0.1.34 → 0.1.35

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.
Files changed (39) hide show
  1. package/README.md +105 -36
  2. package/dist/command-manager.d.ts +1 -7
  3. package/dist/command-manager.js +31 -50
  4. package/dist/config-manager.d.ts +27 -16
  5. package/dist/config-manager.js +109 -191
  6. package/dist/config.js +8 -4
  7. package/dist/error-handlers.js +4 -0
  8. package/dist/handlers/edit-search-handlers.js +9 -13
  9. package/dist/handlers/filesystem-handlers.d.ts +0 -4
  10. package/dist/handlers/filesystem-handlers.js +10 -18
  11. package/dist/handlers/index.d.ts +0 -1
  12. package/dist/handlers/index.js +0 -1
  13. package/dist/index.js +18 -3
  14. package/dist/sandbox/index.d.ts +9 -0
  15. package/dist/sandbox/index.js +50 -0
  16. package/dist/sandbox/mac-sandbox.d.ts +19 -0
  17. package/dist/sandbox/mac-sandbox.js +174 -0
  18. package/dist/server.js +152 -175
  19. package/dist/setup-claude-server.js +98 -49
  20. package/dist/terminal-manager.d.ts +1 -1
  21. package/dist/terminal-manager.js +20 -3
  22. package/dist/tools/config.d.ts +0 -58
  23. package/dist/tools/config.js +44 -107
  24. package/dist/tools/debug-path.d.ts +1 -0
  25. package/dist/tools/debug-path.js +44 -0
  26. package/dist/tools/edit.js +8 -5
  27. package/dist/tools/execute.js +4 -4
  28. package/dist/tools/filesystem-fixed.d.ts +22 -0
  29. package/dist/tools/filesystem-fixed.js +176 -0
  30. package/dist/tools/filesystem.d.ts +4 -6
  31. package/dist/tools/filesystem.js +101 -80
  32. package/dist/tools/schemas.d.ts +15 -14
  33. package/dist/tools/schemas.js +10 -6
  34. package/dist/tools/search.js +3 -3
  35. package/dist/utils.d.ts +5 -0
  36. package/dist/utils.js +92 -32
  37. package/dist/version.d.ts +1 -1
  38. package/dist/version.js +1 -1
  39. package/package.json +1 -2
@@ -0,0 +1,174 @@
1
+ import { spawn } from 'child_process';
2
+ import fs from 'fs/promises';
3
+ import path from 'path';
4
+ import os from 'os';
5
+ /**
6
+ * Generate a temporary sandbox profile for macOS that restricts access to allowed directories
7
+ * @param allowedDirectories Array of directories that should be accessible
8
+ * @returns Path to the generated sandbox profile file
9
+ */
10
+ export async function generateSandboxProfile(allowedDirectories) {
11
+ // Create a temporary directory for the sandbox profile
12
+ const tempDir = path.join(os.tmpdir(), 'claude-server-sandbox');
13
+ // Ensure temp directory exists
14
+ try {
15
+ // Check if directory exists first
16
+ try {
17
+ await fs.access(tempDir);
18
+ console.log(`Temp directory exists: ${tempDir}`);
19
+ }
20
+ catch {
21
+ // Directory doesn't exist, create it
22
+ console.log(`Creating temp directory: ${tempDir}`);
23
+ await fs.mkdir(tempDir, { recursive: true });
24
+ console.log(`Temp directory created: ${tempDir}`);
25
+ }
26
+ }
27
+ catch (error) {
28
+ console.error('Error creating temp directory for sandbox:', error);
29
+ throw new Error(`Failed to create sandbox temp directory: ${error}`);
30
+ }
31
+ // Create the sandbox profile content - based on our tests, we need a simpler approach
32
+ // that just allows by default and then adds specific permissions for allowed directories
33
+ // Use a more restrictive approach - deny all file access, then explicitly allow only what we need
34
+ let profileContent = `(version 1)
35
+ (debug deny)
36
+ (allow default)
37
+ (deny file-read* file-write*)
38
+ `;
39
+ // Add explicit permissions for allowed directories
40
+ for (const dir of allowedDirectories) {
41
+ // Ensure path is absolute
42
+ const absPath = path.resolve(dir);
43
+ profileContent += `(allow file-read* file-write* (subpath "${absPath}"))\n`;
44
+ }
45
+ // Add system paths needed for basic command execution
46
+ profileContent += `
47
+ (allow file-read* (subpath "/usr"))
48
+ (allow file-read* (subpath "/bin"))
49
+ (allow file-read* (subpath "/sbin"))
50
+ (allow file-read* (subpath "/Library"))
51
+ (allow file-read* (subpath "/System"))
52
+ (allow file-read* (subpath "/tmp"))
53
+ (allow file-read* (subpath "/dev"))
54
+ (allow file-read* (subpath "/etc"))
55
+ (allow file-read* (subpath "${os.homedir()}/.zshrc"))
56
+ (allow file-read* (subpath "${os.homedir()}/.bash_profile"))
57
+ (allow file-read* (subpath "${os.homedir()}/.bashrc"))
58
+ (allow process-exec)
59
+ (allow process-fork)
60
+ (allow mach-lookup)
61
+ (allow network-outbound)
62
+ (allow system-socket)
63
+ (allow sysctl-read)
64
+ `;
65
+ // Add comment for debugging
66
+ profileContent += `\n; Allowed directories: ${allowedDirectories.join(', ')}\n`;
67
+ // Write the profile to a temporary file
68
+ const profilePath = path.join(tempDir, 'sandbox-profile.sb');
69
+ try {
70
+ // Write the profile with verbose logging
71
+ console.log(`Writing sandbox profile to: ${profilePath}`);
72
+ await fs.writeFile(profilePath, profileContent, 'utf-8');
73
+ // Verify the file was created
74
+ await fs.access(profilePath);
75
+ console.log(`Sandbox profile created successfully`);
76
+ // Log the profile content for debugging
77
+ console.log(`Sandbox profile content:\n${profileContent}`);
78
+ return profilePath;
79
+ }
80
+ catch (error) {
81
+ console.error(`Error creating sandbox profile at ${profilePath}:`, error);
82
+ throw new Error(`Failed to create sandbox profile: ${error}`);
83
+ }
84
+ }
85
+ /**
86
+ * Execute a command in a macOS sandbox with access restricted to allowed directories
87
+ * @param command Command to execute
88
+ * @param allowedDirectories Array of allowed directory paths
89
+ * @param options Additional execution options
90
+ * @returns Promise resolving to the execution result
91
+ */
92
+ export async function executeSandboxedCommand(command, allowedDirectories, timeoutMs = 30000) {
93
+ try {
94
+ // Generate the sandbox profile
95
+ const profilePath = await generateSandboxProfile(allowedDirectories);
96
+ // Create a wrapper script that will perform additional path checks
97
+ // This is a belt-and-suspenders approach since our tests show the sandbox
98
+ // doesn't perfectly restrict access to only allowed directories
99
+ const wrapperScriptPath = path.join(os.tmpdir(), `claude-sandbox-wrapper-${Date.now()}.sh`);
100
+ // Generate a script that does additional path validation
101
+ // This will extract file paths from the command and verify they're in allowed directories
102
+ const wrapperScript = `#!/bin/sh
103
+ # Wrapper script for sandboxed execution
104
+ # Only allows access to specific directories: ${allowedDirectories.join(', ')}
105
+
106
+ # The actual command to run
107
+ COMMAND="${command.replace(/"/g, '\\"')}"
108
+
109
+ # Run the command in sandbox
110
+ sandbox-exec -f "${profilePath}" /bin/sh -c "$COMMAND"
111
+ EXIT_CODE=$?
112
+
113
+ # Return the exit code from the sandbox
114
+ exit $EXIT_CODE
115
+ `;
116
+ // Write the wrapper script
117
+ await fs.writeFile(wrapperScriptPath, wrapperScript, { mode: 0o755 });
118
+ // Log what we're doing
119
+ console.log(`Executing sandboxed command via wrapper script`);
120
+ console.log(`Command: ${command}`);
121
+ console.log(`Allowed directories: ${allowedDirectories.join(', ')}`);
122
+ // Execute the wrapper script
123
+ const process = spawn(wrapperScriptPath, []);
124
+ let output = '';
125
+ let isBlocked = false;
126
+ // Set up timeout
127
+ const timeoutId = setTimeout(() => {
128
+ isBlocked = true;
129
+ }, timeoutMs);
130
+ // Handle output
131
+ process.stdout.on('data', (data) => {
132
+ const text = data.toString();
133
+ console.log(`Sandbox stdout: ${text}`);
134
+ output += text;
135
+ });
136
+ process.stderr.on('data', (data) => {
137
+ const text = data.toString();
138
+ console.log(`Sandbox stderr: ${text}`);
139
+ output += text;
140
+ });
141
+ // Return a promise that resolves when the process exits
142
+ return new Promise((resolve) => {
143
+ process.on('exit', (code) => {
144
+ clearTimeout(timeoutId);
145
+ console.log(`Sandbox process exited with code: ${code}`);
146
+ // Clean up the temporary files
147
+ Promise.all([
148
+ fs.unlink(profilePath).catch(err => {
149
+ console.error('Error removing temporary sandbox profile:', err);
150
+ }),
151
+ fs.unlink(wrapperScriptPath).catch(err => {
152
+ console.error('Error removing temporary wrapper script:', err);
153
+ })
154
+ ]).finally(() => {
155
+ resolve({
156
+ output,
157
+ exitCode: code,
158
+ isBlocked,
159
+ pid: process.pid || -1
160
+ });
161
+ });
162
+ });
163
+ });
164
+ }
165
+ catch (error) {
166
+ console.error('Error in sandbox execution:', error);
167
+ return {
168
+ output: `Sandbox execution error: ${error instanceof Error ? error.message : String(error)}`,
169
+ exitCode: 1,
170
+ isBlocked: false,
171
+ pid: -1
172
+ };
173
+ }
174
+ }
package/dist/server.js CHANGED
@@ -1,9 +1,11 @@
1
1
  import { Server } from "@modelcontextprotocol/sdk/server/index.js";
2
2
  import { CallToolRequestSchema, ListToolsRequestSchema, ListResourcesRequestSchema, ListPromptsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
3
3
  import { zodToJsonSchema } from "zod-to-json-schema";
4
- import { ExecuteCommandArgsSchema, ReadOutputArgsSchema, ForceTerminateArgsSchema, ListSessionsArgsSchema, KillProcessArgsSchema, BlockCommandArgsSchema, UnblockCommandArgsSchema, ReadFileArgsSchema, ReadMultipleFilesArgsSchema, WriteFileArgsSchema, CreateDirectoryArgsSchema, ListDirectoryArgsSchema, MoveFileArgsSchema, SearchFilesArgsSchema, GetFileInfoArgsSchema, EditBlockArgsSchema, SearchCodeArgsSchema, } from './tools/schemas.js';
4
+ import { ExecuteCommandArgsSchema, ReadOutputArgsSchema, ForceTerminateArgsSchema, ListSessionsArgsSchema, KillProcessArgsSchema, ReadFileArgsSchema, ReadMultipleFilesArgsSchema, WriteFileArgsSchema, CreateDirectoryArgsSchema, ListDirectoryArgsSchema, MoveFileArgsSchema, SearchFilesArgsSchema, GetFileInfoArgsSchema, EditBlockArgsSchema, SearchCodeArgsSchema, GetConfigArgsSchema, SetConfigValueArgsSchema, ListProcessesArgsSchema, } from './tools/schemas.js';
5
+ import { getConfig, setConfigValue } from './tools/config.js';
5
6
  import { VERSION } from './version.js';
6
7
  import { capture } from "./utils.js";
8
+ console.error("Loading server.ts");
7
9
  export const server = new Server({
8
10
  name: "desktop-commander",
9
11
  version: VERSION,
@@ -28,207 +30,182 @@ server.setRequestHandler(ListPromptsRequestSchema, async () => {
28
30
  prompts: [],
29
31
  };
30
32
  });
33
+ console.error("Setting up request handlers...");
31
34
  server.setRequestHandler(ListToolsRequestSchema, async () => {
32
- return {
33
- tools: [
34
- // Terminal tools
35
- {
36
- name: "execute_command",
37
- description: "Execute a terminal command with timeout. Command will continue running in background if it doesn't complete within timeout.",
38
- inputSchema: zodToJsonSchema(ExecuteCommandArgsSchema),
39
- },
40
- {
41
- name: "read_output",
42
- description: "Read new output from a running terminal session.",
43
- inputSchema: zodToJsonSchema(ReadOutputArgsSchema),
44
- },
45
- {
46
- name: "force_terminate",
47
- description: "Force terminate a running terminal session.",
48
- inputSchema: zodToJsonSchema(ForceTerminateArgsSchema),
49
- },
50
- {
51
- name: "list_sessions",
52
- description: "List all active terminal sessions.",
53
- inputSchema: zodToJsonSchema(ListSessionsArgsSchema),
54
- },
55
- {
56
- name: "list_processes",
57
- description: "List all running processes. Returns process information including PID, " +
58
- "command name, CPU usage, and memory usage.",
59
- inputSchema: {
60
- type: "object",
61
- properties: {},
62
- required: [],
63
- },
64
- },
65
- {
66
- name: "kill_process",
67
- description: "Terminate a running process by PID. Use with caution as this will " +
68
- "forcefully terminate the specified process.",
69
- inputSchema: zodToJsonSchema(KillProcessArgsSchema),
70
- },
71
- {
72
- name: "block_command",
73
- description: "Add a command to the blacklist. Once blocked, the command cannot be executed until unblocked.",
74
- inputSchema: zodToJsonSchema(BlockCommandArgsSchema),
75
- },
76
- {
77
- name: "unblock_command",
78
- description: "Remove a command from the blacklist. Once unblocked, the command can be executed normally.",
79
- inputSchema: zodToJsonSchema(UnblockCommandArgsSchema),
80
- },
81
- {
82
- name: "list_blocked_commands",
83
- description: "List all currently blocked commands.",
84
- inputSchema: {
85
- type: "object",
86
- properties: {},
87
- required: [],
88
- },
89
- },
90
- // Filesystem tools
91
- {
92
- name: "read_file",
93
- description: "Read the complete contents of a file from the file system or a URL. " +
94
- "When reading from the file system, only works within allowed directories. " +
95
- "Can fetch content from URLs when isUrl parameter is set to true. " +
96
- "Handles text files normally and image files are returned as viewable images. " +
97
- "Recognized image types: PNG, JPEG, GIF, WebP.",
98
- inputSchema: zodToJsonSchema(ReadFileArgsSchema),
99
- },
100
- {
101
- name: "read_multiple_files",
102
- description: "Read the contents of multiple files simultaneously. " +
103
- "Each file's content is returned with its path as a reference. " +
104
- "Handles text files normally and renders images as viewable content. " +
105
- "Recognized image types: PNG, JPEG, GIF, WebP. " +
106
- "Failed reads for individual files won't stop the entire operation. " +
107
- "Only works within allowed directories.",
108
- inputSchema: zodToJsonSchema(ReadMultipleFilesArgsSchema),
109
- },
110
- {
111
- name: "write_file",
112
- description: "Completely replace file contents. Best for large changes (>20% of file) or when edit_block fails. " +
113
- "Use with caution as it will overwrite existing files. Only works within allowed directories.",
114
- inputSchema: zodToJsonSchema(WriteFileArgsSchema),
115
- },
116
- {
117
- name: "create_directory",
118
- description: "Create a new directory or ensure a directory exists. Can create multiple " +
119
- "nested directories in one operation. Only works within allowed directories.",
120
- inputSchema: zodToJsonSchema(CreateDirectoryArgsSchema),
121
- },
122
- {
123
- name: "list_directory",
124
- description: "Get a detailed listing of all files and directories in a specified path. " +
125
- "Results distinguish between files and directories with [FILE] and [DIR] prefixes. " +
126
- "Only works within allowed directories.",
127
- inputSchema: zodToJsonSchema(ListDirectoryArgsSchema),
128
- },
129
- {
130
- name: "move_file",
131
- description: "Move or rename files and directories. Can move files between directories " +
132
- "and rename them in a single operation. Both source and destination must be " +
133
- "within allowed directories.",
134
- inputSchema: zodToJsonSchema(MoveFileArgsSchema),
135
- },
136
- {
137
- name: "search_files",
138
- description: "Finds files by name using a case-insensitive substring matching. " +
139
- "Searches through all subdirectories from the starting path. " +
140
- "Has a default timeout of 30 seconds which can be customized using the timeoutMs parameter. " +
141
- "Only searches within allowed directories.",
142
- inputSchema: zodToJsonSchema(SearchFilesArgsSchema),
143
- },
144
- {
145
- name: "search_code",
146
- description: "Search for text/code patterns within file contents using ripgrep. " +
147
- "Fast and powerful search similar to VS Code search functionality. " +
148
- "Supports regular expressions, file pattern filtering, and context lines. " +
149
- "Has a default timeout of 30 seconds which can be customized. " +
150
- "Only searches within allowed directories.",
151
- inputSchema: zodToJsonSchema(SearchCodeArgsSchema),
152
- },
153
- {
154
- name: "get_file_info",
155
- description: "Retrieve detailed metadata about a file or directory including size, " +
156
- "creation time, last modified time, permissions, and type. " +
157
- "Only works within allowed directories.",
158
- inputSchema: zodToJsonSchema(GetFileInfoArgsSchema),
159
- },
160
- {
161
- name: "list_allowed_directories",
162
- description: "Returns the list of directories that this server is allowed to access.",
163
- inputSchema: {
164
- type: "object",
165
- properties: {},
166
- required: [],
167
- },
168
- },
169
- {
170
- name: "edit_block",
171
- description: "Apply surgical text replacements to files. Best for small changes (<20% of file size). " +
172
- "Call repeatedly to change multiple blocks. Will verify changes after application. " +
173
- "Format:\nfilepath\n<<<<<<< SEARCH\ncontent to find\n=======\nnew content\n>>>>>>> REPLACE",
174
- inputSchema: zodToJsonSchema(EditBlockArgsSchema),
175
- },
176
- ],
177
- };
35
+ try {
36
+ console.error("Generating tools list...");
37
+ return {
38
+ tools: [
39
+ // Configuration tools
40
+ {
41
+ name: "get_config",
42
+ description: "Get the complete server configuration as JSON. Config includes fields for: blockedCommands (array of blocked shell commands), defaultShell (shell to use for commands), allowedDirectories (paths the server can access).",
43
+ inputSchema: zodToJsonSchema(GetConfigArgsSchema),
44
+ },
45
+ {
46
+ name: "set_config_value",
47
+ description: "Set a specific configuration value by key. WARNING: Should be used in a separate chat from file operations and command execution to prevent security issues. Config keys include: blockedCommands (array), defaultShell (string), allowedDirectories (array of paths). IMPORTANT: Setting allowedDirectories to an empty array ([]) allows full access to the entire file system, regardless of the operating system.",
48
+ inputSchema: zodToJsonSchema(SetConfigValueArgsSchema),
49
+ },
50
+ // Terminal tools
51
+ {
52
+ name: "execute_command",
53
+ description: "Execute a terminal command with timeout. Command will continue running in background if it doesn't complete within timeout.",
54
+ inputSchema: zodToJsonSchema(ExecuteCommandArgsSchema),
55
+ },
56
+ {
57
+ name: "read_output",
58
+ description: "Read new output from a running terminal session.",
59
+ inputSchema: zodToJsonSchema(ReadOutputArgsSchema),
60
+ },
61
+ {
62
+ name: "force_terminate",
63
+ description: "Force terminate a running terminal session.",
64
+ inputSchema: zodToJsonSchema(ForceTerminateArgsSchema),
65
+ },
66
+ {
67
+ name: "list_sessions",
68
+ description: "List all active terminal sessions.",
69
+ inputSchema: zodToJsonSchema(ListSessionsArgsSchema),
70
+ },
71
+ {
72
+ name: "list_processes",
73
+ description: "List all running processes. Returns process information including PID, command name, CPU usage, and memory usage.",
74
+ inputSchema: zodToJsonSchema(ListProcessesArgsSchema),
75
+ },
76
+ {
77
+ name: "kill_process",
78
+ description: "Terminate a running process by PID. Use with caution as this will forcefully terminate the specified process.",
79
+ inputSchema: zodToJsonSchema(KillProcessArgsSchema),
80
+ },
81
+ // Filesystem tools
82
+ {
83
+ name: "read_file",
84
+ description: "Read the complete contents of a file from the file system or a URL. When reading from the file system, only works within allowed directories. Can fetch content from URLs when isUrl parameter is set to true. Handles text files normally and image files are returned as viewable images. Recognized image types: PNG, JPEG, GIF, WebP.",
85
+ inputSchema: zodToJsonSchema(ReadFileArgsSchema),
86
+ },
87
+ {
88
+ name: "read_multiple_files",
89
+ description: "Read the contents of multiple files simultaneously. Each file's content is returned with its path as a reference. Handles text files normally and renders images as viewable content. Recognized image types: PNG, JPEG, GIF, WebP. Failed reads for individual files won't stop the entire operation. Only works within allowed directories.",
90
+ inputSchema: zodToJsonSchema(ReadMultipleFilesArgsSchema),
91
+ },
92
+ {
93
+ name: "write_file",
94
+ description: "Completely replace file contents. Best for large changes (>20% of file) or when edit_block fails. Use with caution as it will overwrite existing files. Only works within allowed directories.",
95
+ inputSchema: zodToJsonSchema(WriteFileArgsSchema),
96
+ },
97
+ {
98
+ name: "create_directory",
99
+ description: "Create a new directory or ensure a directory exists. Can create multiple nested directories in one operation. Only works within allowed directories.",
100
+ inputSchema: zodToJsonSchema(CreateDirectoryArgsSchema),
101
+ },
102
+ {
103
+ name: "list_directory",
104
+ description: "Get a detailed listing of all files and directories in a specified path. Results distinguish between files and directories with [FILE] and [DIR] prefixes. Only works within allowed directories.",
105
+ inputSchema: zodToJsonSchema(ListDirectoryArgsSchema),
106
+ },
107
+ {
108
+ name: "move_file",
109
+ description: "Move or rename files and directories. Can move files between directories and rename them in a single operation. Both source and destination must be within allowed directories.",
110
+ inputSchema: zodToJsonSchema(MoveFileArgsSchema),
111
+ },
112
+ {
113
+ name: "search_files",
114
+ description: "Finds files by name using a case-insensitive substring matching. Searches through all subdirectories from the starting path. Has a default timeout of 30 seconds which can be customized using the timeoutMs parameter. Only searches within allowed directories.",
115
+ inputSchema: zodToJsonSchema(SearchFilesArgsSchema),
116
+ },
117
+ {
118
+ name: "search_code",
119
+ description: "Search for text/code patterns within file contents using ripgrep. Fast and powerful search similar to VS Code search functionality. Supports regular expressions, file pattern filtering, and context lines. Has a default timeout of 30 seconds which can be customized. Only searches within allowed directories.",
120
+ inputSchema: zodToJsonSchema(SearchCodeArgsSchema),
121
+ },
122
+ {
123
+ name: "get_file_info",
124
+ description: "Retrieve detailed metadata about a file or directory including size, creation time, last modified time, permissions, and type. Only works within allowed directories.",
125
+ inputSchema: zodToJsonSchema(GetFileInfoArgsSchema),
126
+ },
127
+ // Note: list_allowed_directories removed - use get_config to check allowedDirectories
128
+ // Text editing tools
129
+ {
130
+ name: "edit_block",
131
+ description: "Apply surgical text replacements to files. Best for small changes (<20% of file size). Call repeatedly to change multiple blocks. Will verify changes after application. Format:\nfilepath\n<<<<<<< SEARCH\ncontent to find\n=======\nnew content\n>>>>>>> REPLACE",
132
+ inputSchema: zodToJsonSchema(EditBlockArgsSchema),
133
+ },
134
+ ],
135
+ };
136
+ }
137
+ catch (error) {
138
+ console.error("Error in list_tools request handler:", error);
139
+ throw error;
140
+ }
178
141
  });
179
142
  import * as handlers from './handlers/index.js';
180
143
  server.setRequestHandler(CallToolRequestSchema, async (request) => {
181
144
  try {
182
145
  const { name, arguments: args } = request.params;
183
- capture('server_call_tool');
184
- // Add a single dynamic capture for the specific tool
185
- capture('server_' + name);
146
+ capture('server_call_tool', {
147
+ name
148
+ });
186
149
  // Using a more structured approach with dedicated handlers
187
150
  switch (name) {
151
+ // Config tools
152
+ case "get_config":
153
+ try {
154
+ return await getConfig();
155
+ }
156
+ catch (error) {
157
+ capture('server_request_error', { message: `Error in get_config handler: ${error}` });
158
+ return {
159
+ content: [{ type: "text", text: `Error: Failed to get configuration` }],
160
+ isError: true,
161
+ };
162
+ }
163
+ case "set_config_value":
164
+ try {
165
+ return await setConfigValue(args);
166
+ }
167
+ catch (error) {
168
+ capture('server_request_error', { message: `Error in set_config_value handler: ${error}` });
169
+ return {
170
+ content: [{ type: "text", text: `Error: Failed to set configuration value` }],
171
+ isError: true,
172
+ };
173
+ }
188
174
  // Terminal tools
189
175
  case "execute_command":
190
- return handlers.handleExecuteCommand(args);
176
+ return await handlers.handleExecuteCommand(args);
191
177
  case "read_output":
192
- return handlers.handleReadOutput(args);
178
+ return await handlers.handleReadOutput(args);
193
179
  case "force_terminate":
194
- return handlers.handleForceTerminate(args);
180
+ return await handlers.handleForceTerminate(args);
195
181
  case "list_sessions":
196
- return handlers.handleListSessions();
182
+ return await handlers.handleListSessions();
197
183
  // Process tools
198
184
  case "list_processes":
199
- return handlers.handleListProcesses();
185
+ return await handlers.handleListProcesses();
200
186
  case "kill_process":
201
- return handlers.handleKillProcess(args);
202
- // Command management tools
203
- case "block_command":
204
- return handlers.handleBlockCommand(args);
205
- case "unblock_command":
206
- return handlers.handleUnblockCommand(args);
207
- case "list_blocked_commands":
208
- return handlers.handleListBlockedCommands();
187
+ return await handlers.handleKillProcess(args);
209
188
  // Filesystem tools
210
189
  case "read_file":
211
- return handlers.handleReadFile(args);
190
+ return await handlers.handleReadFile(args);
212
191
  case "read_multiple_files":
213
- return handlers.handleReadMultipleFiles(args);
192
+ return await handlers.handleReadMultipleFiles(args);
214
193
  case "write_file":
215
- return handlers.handleWriteFile(args);
194
+ return await handlers.handleWriteFile(args);
216
195
  case "create_directory":
217
- return handlers.handleCreateDirectory(args);
196
+ return await handlers.handleCreateDirectory(args);
218
197
  case "list_directory":
219
- return handlers.handleListDirectory(args);
198
+ return await handlers.handleListDirectory(args);
220
199
  case "move_file":
221
- return handlers.handleMoveFile(args);
200
+ return await handlers.handleMoveFile(args);
222
201
  case "search_files":
223
- return handlers.handleSearchFiles(args);
202
+ return await handlers.handleSearchFiles(args);
224
203
  case "search_code":
225
- return handlers.handleSearchCode(args);
204
+ return await handlers.handleSearchCode(args);
226
205
  case "get_file_info":
227
- return handlers.handleGetFileInfo(args);
228
- case "list_allowed_directories":
229
- return handlers.handleListAllowedDirectories();
206
+ return await handlers.handleGetFileInfo(args);
230
207
  case "edit_block":
231
- return handlers.handleEditBlock(args);
208
+ return await handlers.handleEditBlock(args);
232
209
  default:
233
210
  capture('server_unknown_tool', { name });
234
211
  return {