@wonderwhy-er/desktop-commander 0.2.3 → 0.2.5
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/README.md +72 -4
- package/dist/config-manager.d.ts +6 -0
- package/dist/config-manager.js +1 -1
- package/dist/custom-stdio.d.ts +23 -2
- package/dist/custom-stdio.js +167 -12
- package/dist/handlers/edit-search-handlers.js +25 -6
- package/dist/handlers/terminal-handlers.d.ts +8 -4
- package/dist/handlers/terminal-handlers.js +16 -10
- package/dist/index-dxt.d.ts +2 -0
- package/dist/index-dxt.js +76 -0
- package/dist/index-with-startup-detection.d.ts +5 -0
- package/dist/index-with-startup-detection.js +180 -0
- package/dist/index.js +2 -0
- package/dist/server.d.ts +5 -0
- package/dist/server.js +345 -42
- package/dist/terminal-manager.d.ts +7 -0
- package/dist/terminal-manager.js +93 -18
- package/dist/tools/client.d.ts +10 -0
- package/dist/tools/client.js +13 -0
- package/dist/tools/config.d.ts +1 -1
- package/dist/tools/config.js +21 -3
- package/dist/tools/edit.js +4 -3
- package/dist/tools/environment.d.ts +55 -0
- package/dist/tools/environment.js +65 -0
- package/dist/tools/feedback.d.ts +8 -0
- package/dist/tools/feedback.js +132 -0
- package/dist/tools/filesystem.js +152 -57
- package/dist/tools/improved-process-tools.js +170 -29
- package/dist/tools/schemas.d.ts +20 -2
- package/dist/tools/schemas.js +20 -2
- package/dist/tools/usage.d.ts +5 -0
- package/dist/tools/usage.js +24 -0
- package/dist/types.d.ts +4 -0
- package/dist/utils/capture.js +23 -1
- package/dist/utils/early-logger.d.ts +4 -0
- package/dist/utils/early-logger.js +35 -0
- package/dist/utils/mcp-logger.d.ts +30 -0
- package/dist/utils/mcp-logger.js +59 -0
- package/dist/utils/smithery-detector.d.ts +94 -0
- package/dist/utils/smithery-detector.js +292 -0
- package/dist/utils/startup-detector.d.ts +65 -0
- package/dist/utils/startup-detector.js +390 -0
- package/dist/utils/usageTracker.d.ts +85 -0
- package/dist/utils/usageTracker.js +280 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +3 -1
package/README.md
CHANGED
|
@@ -22,6 +22,7 @@ Work with code and text, run processes, and automate tasks, going far beyond oth
|
|
|
22
22
|
- [Features](#features)
|
|
23
23
|
- [Installation](#installation)
|
|
24
24
|
- [Usage](#usage)
|
|
25
|
+
- [Docker Support](#docker-support)
|
|
25
26
|
- [Handling Long-Running Commands](#handling-long-running-commands)
|
|
26
27
|
- [Work in Progress and TODOs](#work-in-progress-and-todos)
|
|
27
28
|
- [Sponsors and Supporters](#sponsors-and-supporters)
|
|
@@ -38,6 +39,10 @@ Execute long-running terminal commands on your computer and manage processes thr
|
|
|
38
39
|
|
|
39
40
|
## Features
|
|
40
41
|
|
|
42
|
+
- **Enhanced terminal commands with interactive process control**
|
|
43
|
+
- **Execute code in memory (Python, Node.js, R) without saving files**
|
|
44
|
+
- **Instant data analysis - just ask to analyze CSV/JSON files**
|
|
45
|
+
- **Interact with running processes (SSH, databases, development servers)**
|
|
41
46
|
- Execute terminal commands with output streaming
|
|
42
47
|
- Command timeout and background execution support
|
|
43
48
|
- Process management (list and kill processes)
|
|
@@ -182,8 +187,9 @@ The server provides a comprehensive set of tools organized into several categori
|
|
|
182
187
|
|----------|------|-------------|
|
|
183
188
|
| **Configuration** | `get_config` | Get the complete server configuration as JSON (includes blockedCommands, defaultShell, allowedDirectories, fileReadLineLimit, fileWriteLineLimit, telemetryEnabled) |
|
|
184
189
|
| | `set_config_value` | Set a specific configuration value by key. Available settings: <br>• `blockedCommands`: Array of shell commands that cannot be executed<br>• `defaultShell`: Shell to use for commands (e.g., bash, zsh, powershell)<br>• `allowedDirectories`: Array of filesystem paths the server can access for file operations (⚠️ terminal commands can still access files outside these directories)<br>• `fileReadLineLimit`: Maximum lines to read at once (default: 1000)<br>• `fileWriteLineLimit`: Maximum lines to write at once (default: 50)<br>• `telemetryEnabled`: Enable/disable telemetry (boolean) |
|
|
185
|
-
| **Terminal** | `
|
|
186
|
-
| | `
|
|
190
|
+
| **Terminal** | `start_process` | Start programs with smart detection of when they're ready for input |
|
|
191
|
+
| | `interact_with_process` | Send commands to running programs and get responses |
|
|
192
|
+
| | `read_process_output` | Read output from running processes |
|
|
187
193
|
| | `force_terminate` | Force terminate a running terminal session |
|
|
188
194
|
| | `list_sessions` | List all active terminal sessions |
|
|
189
195
|
| | `list_processes` | List all running processes with detailed information |
|
|
@@ -198,6 +204,25 @@ The server provides a comprehensive set of tools organized into several categori
|
|
|
198
204
|
| | `search_code` | Search for text/code patterns within file contents using ripgrep |
|
|
199
205
|
| | `get_file_info` | Retrieve detailed metadata about a file or directory |
|
|
200
206
|
| **Text Editing** | `edit_block` | Apply targeted text replacements with enhanced prompting for smaller edits (includes character-level diff feedback) |
|
|
207
|
+
| **Analytics** | `get_usage_stats` | Get usage statistics for your own insight |
|
|
208
|
+
| | `give_feedback_to_desktop_commander` | Open feedback form in browser to provide feedback to Desktop Commander Team |
|
|
209
|
+
|
|
210
|
+
### Quick Examples
|
|
211
|
+
|
|
212
|
+
**Data Analysis:**
|
|
213
|
+
```
|
|
214
|
+
"Analyze sales.csv and show top customers" → Claude runs Python code in memory
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
**Remote Access:**
|
|
218
|
+
```
|
|
219
|
+
"SSH to my server and check disk space" → Claude maintains SSH session
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
**Development:**
|
|
223
|
+
```
|
|
224
|
+
"Start Node.js and test this API" → Claude runs interactive Node session
|
|
225
|
+
```
|
|
201
226
|
|
|
202
227
|
### Tool Usage Examples
|
|
203
228
|
|
|
@@ -233,7 +258,34 @@ The `edit_block` tool includes several enhancements for better reliability:
|
|
|
233
258
|
|
|
234
259
|
When a search fails, you'll see detailed information about the closest match found, including similarity percentage, execution time, and character differences. All these details are automatically logged for later analysis using the fuzzy search log tools.
|
|
235
260
|
|
|
236
|
-
###
|
|
261
|
+
### Docker Support
|
|
262
|
+
|
|
263
|
+
### 🐳 Isolated Environment Usage
|
|
264
|
+
|
|
265
|
+
Desktop Commander can be run in Docker containers for **complete isolation from your host system**, providing **zero risk to your computer**. This is perfect for testing, development, or when you want complete sandboxing.
|
|
266
|
+
|
|
267
|
+
### Installation Instructions
|
|
268
|
+
|
|
269
|
+
1. **Install Docker for Windows/Mac**
|
|
270
|
+
- Download and install Docker Desktop from [docker.com](https://www.docker.com/products/docker-desktop/)
|
|
271
|
+
|
|
272
|
+
2. **Get Desktop Commander Docker Configuration**
|
|
273
|
+
- Visit: https://hub.docker.com/mcp/server/desktop-commander/manual
|
|
274
|
+
- **Option A:** Use the provided terminal command for automated setup
|
|
275
|
+
- **Option B:** Click "Standalone" to get the config JSON and add it manually to your Claude Desktop config
|
|
276
|
+

|
|
277
|
+
|
|
278
|
+
3. **Mount Your Machine Folders (Coming Soon)**
|
|
279
|
+
- Instructions on how to mount your local directories into the Docker container will be provided soon
|
|
280
|
+
- This will allow you to work with your files while maintaining complete isolation
|
|
281
|
+
|
|
282
|
+
### Benefits of Docker Usage
|
|
283
|
+
- **Complete isolation** from your host system
|
|
284
|
+
- **Consistent environment** across different machines
|
|
285
|
+
- **Easy cleanup** - just remove the container when done
|
|
286
|
+
- **Perfect for testing** new features or configurations
|
|
287
|
+
|
|
288
|
+
## URL Support
|
|
237
289
|
- `read_file` can now fetch content from both local files and URLs
|
|
238
290
|
- Example: `read_file` with `isUrl: true` parameter to read from web resources
|
|
239
291
|
- Handles both text and image content from remote sources
|
|
@@ -605,14 +657,30 @@ Join our [Discord server](https://discord.gg/kQ27sNnZr7) for community support,
|
|
|
605
657
|
|
|
606
658
|
Desktop Commander collects limited anonymous telemetry data to help improve the tool. No personal information, file contents, file paths, or command arguments are collected.
|
|
607
659
|
|
|
608
|
-
|
|
660
|
+
### Usage Analytics (Local Only)
|
|
661
|
+
- **Local usage statistics** are always collected and stored locally on your machine for functionality and the `get_usage_stats` tool
|
|
662
|
+
- Use the `get_usage_stats` tool to view your personal usage patterns, success rates, and performance metrics
|
|
663
|
+
- **This data is NOT sent anywhere** - it remains on your computer for your personal insights
|
|
664
|
+
|
|
665
|
+
### Feedback System
|
|
666
|
+
- Use the `give_feedback_to_desktop_commander` tool to provide feedback about Desktop Commander
|
|
667
|
+
- Opens a browser-based feedback form to send suggestions and feedback to the development team
|
|
668
|
+
- Only basic usage statistics (tool call count, days using, platform) are pre-filled to provide context but you can remove them
|
|
669
|
+
|
|
670
|
+
### External Telemetry Opt-Out
|
|
671
|
+
External telemetry (sent to analytics services) is enabled by default but can be disabled:
|
|
609
672
|
|
|
610
673
|
1. Open the chat and simply ask:
|
|
611
674
|
**"Disable telemetry"**
|
|
612
675
|
2. The chatbot will update your settings automatically.
|
|
613
676
|
|
|
677
|
+
**Note:** This only disables external telemetry. Local usage analytics remain active for tool functionality but is not share externally
|
|
678
|
+
|
|
614
679
|
For complete details about data collection, please see our [Privacy Policy](PRIVACY.md).
|
|
615
680
|
|
|
681
|
+
## Verifications
|
|
682
|
+
[](https://mseep.ai/app/25ff7a06-58bc-40b8-bd79-ebb715140f1a)
|
|
683
|
+
|
|
616
684
|
## License
|
|
617
685
|
|
|
618
686
|
MIT
|
package/dist/config-manager.d.ts
CHANGED
|
@@ -5,8 +5,14 @@ export interface ServerConfig {
|
|
|
5
5
|
telemetryEnabled?: boolean;
|
|
6
6
|
fileWriteLineLimit?: number;
|
|
7
7
|
fileReadLineLimit?: number;
|
|
8
|
+
clientId?: string;
|
|
9
|
+
currentClient?: ClientInfo;
|
|
8
10
|
[key: string]: any;
|
|
9
11
|
}
|
|
12
|
+
export interface ClientInfo {
|
|
13
|
+
name: string;
|
|
14
|
+
version: string;
|
|
15
|
+
}
|
|
10
16
|
/**
|
|
11
17
|
* Singleton config manager for the server
|
|
12
18
|
*/
|
package/dist/config-manager.js
CHANGED
|
@@ -101,7 +101,7 @@ class ConfigManager {
|
|
|
101
101
|
"cipher", // Encrypt/decrypt files or wipe data
|
|
102
102
|
"takeown" // Take ownership of files
|
|
103
103
|
],
|
|
104
|
-
defaultShell: os.platform() === 'win32' ? 'powershell.exe' : '
|
|
104
|
+
defaultShell: os.platform() === 'win32' ? 'powershell.exe' : '/bin/sh',
|
|
105
105
|
allowedDirectories: [],
|
|
106
106
|
telemetryEnabled: true, // Default to opt-out approach (telemetry on by default)
|
|
107
107
|
fileWriteLineLimit: 50, // Default line limit for file write operations (changed from 100)
|
package/dist/custom-stdio.d.ts
CHANGED
|
@@ -1,8 +1,29 @@
|
|
|
1
1
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
3
|
+
* Enhanced StdioServerTransport that wraps console output in valid JSON-RPC structures
|
|
4
|
+
* instead of filtering them out. This prevents crashes while maintaining debug visibility.
|
|
5
5
|
*/
|
|
6
6
|
export declare class FilteredStdioServerTransport extends StdioServerTransport {
|
|
7
|
+
private originalConsole;
|
|
8
|
+
private originalStdoutWrite;
|
|
7
9
|
constructor();
|
|
10
|
+
private setupConsoleRedirection;
|
|
11
|
+
private setupStdoutFiltering;
|
|
12
|
+
private sendLogNotification;
|
|
13
|
+
/**
|
|
14
|
+
* Public method to send log notifications from anywhere in the application
|
|
15
|
+
*/
|
|
16
|
+
sendLog(level: "emergency" | "alert" | "critical" | "error" | "warning" | "notice" | "info" | "debug", message: string, data?: any): void;
|
|
17
|
+
/**
|
|
18
|
+
* Send a progress notification (useful for long-running operations)
|
|
19
|
+
*/
|
|
20
|
+
sendProgress(token: string, value: number, total?: number): void;
|
|
21
|
+
/**
|
|
22
|
+
* Send a custom notification with any method name
|
|
23
|
+
*/
|
|
24
|
+
sendCustomNotification(method: string, params: any): void;
|
|
25
|
+
/**
|
|
26
|
+
* Cleanup method to restore original console methods if needed
|
|
27
|
+
*/
|
|
28
|
+
cleanup(): void;
|
|
8
29
|
}
|
package/dist/custom-stdio.js
CHANGED
|
@@ -1,22 +1,177 @@
|
|
|
1
1
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
2
2
|
import process from "node:process";
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* Enhanced StdioServerTransport that wraps console output in valid JSON-RPC structures
|
|
5
|
+
* instead of filtering them out. This prevents crashes while maintaining debug visibility.
|
|
6
6
|
*/
|
|
7
7
|
export class FilteredStdioServerTransport extends StdioServerTransport {
|
|
8
8
|
constructor() {
|
|
9
|
-
// Create a proxy for stdout that only allows valid JSON to pass through
|
|
10
|
-
const originalStdoutWrite = process.stdout.write;
|
|
11
|
-
process.stdout.write = function (buffer) {
|
|
12
|
-
// Only intercept string output that doesn't look like JSON
|
|
13
|
-
if (typeof buffer === 'string' && !buffer.trim().startsWith('{')) {
|
|
14
|
-
return true; //process.stderr.write(buffer);
|
|
15
|
-
}
|
|
16
|
-
return originalStdoutWrite.apply(process.stdout, arguments);
|
|
17
|
-
};
|
|
18
9
|
super();
|
|
10
|
+
// Store original methods
|
|
11
|
+
this.originalConsole = {
|
|
12
|
+
log: console.log,
|
|
13
|
+
warn: console.warn,
|
|
14
|
+
error: console.error,
|
|
15
|
+
debug: console.debug,
|
|
16
|
+
info: console.info,
|
|
17
|
+
};
|
|
18
|
+
this.originalStdoutWrite = process.stdout.write;
|
|
19
|
+
// Setup console redirection
|
|
20
|
+
this.setupConsoleRedirection();
|
|
21
|
+
// Setup stdout filtering for any other output
|
|
22
|
+
this.setupStdoutFiltering();
|
|
19
23
|
// Log initialization to stderr to avoid polluting the JSON stream
|
|
20
|
-
process.stderr.write(`[desktop-commander]
|
|
24
|
+
process.stderr.write(`[desktop-commander] Enhanced FilteredStdioServerTransport initialized\n`);
|
|
25
|
+
}
|
|
26
|
+
setupConsoleRedirection() {
|
|
27
|
+
console.log = (...args) => {
|
|
28
|
+
this.sendLogNotification("info", args);
|
|
29
|
+
};
|
|
30
|
+
console.info = (...args) => {
|
|
31
|
+
this.sendLogNotification("info", args);
|
|
32
|
+
};
|
|
33
|
+
console.warn = (...args) => {
|
|
34
|
+
this.sendLogNotification("warning", args);
|
|
35
|
+
};
|
|
36
|
+
console.error = (...args) => {
|
|
37
|
+
this.sendLogNotification("error", args);
|
|
38
|
+
};
|
|
39
|
+
console.debug = (...args) => {
|
|
40
|
+
this.sendLogNotification("debug", args);
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
setupStdoutFiltering() {
|
|
44
|
+
process.stdout.write = (buffer, encoding, callback) => {
|
|
45
|
+
// Handle different call signatures
|
|
46
|
+
if (typeof buffer === 'string') {
|
|
47
|
+
const trimmed = buffer.trim();
|
|
48
|
+
// Check if this looks like a valid JSON-RPC message
|
|
49
|
+
if (trimmed.startsWith('{') && (trimmed.includes('"jsonrpc"') ||
|
|
50
|
+
trimmed.includes('"method"') ||
|
|
51
|
+
trimmed.includes('"id"'))) {
|
|
52
|
+
// This looks like a valid JSON-RPC message, allow it
|
|
53
|
+
return this.originalStdoutWrite.call(process.stdout, buffer, encoding, callback);
|
|
54
|
+
}
|
|
55
|
+
else if (trimmed.length > 0) {
|
|
56
|
+
// Non-JSON-RPC output, wrap it in a log notification
|
|
57
|
+
this.sendLogNotification("info", [buffer.replace(/\n$/, '')]);
|
|
58
|
+
if (callback)
|
|
59
|
+
callback();
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
// For non-string buffers or empty strings, let them through
|
|
64
|
+
return this.originalStdoutWrite.call(process.stdout, buffer, encoding, callback);
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
sendLogNotification(level, args) {
|
|
68
|
+
try {
|
|
69
|
+
// For data, we can send structured data or string according to MCP spec
|
|
70
|
+
let data;
|
|
71
|
+
if (args.length === 1 && typeof args[0] === 'object' && args[0] !== null) {
|
|
72
|
+
// Single object - send as structured data
|
|
73
|
+
data = args[0];
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
// Multiple args or primitives - convert to string
|
|
77
|
+
data = args.map(arg => {
|
|
78
|
+
if (typeof arg === 'object') {
|
|
79
|
+
try {
|
|
80
|
+
return JSON.stringify(arg, null, 2);
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
return String(arg);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return String(arg);
|
|
87
|
+
}).join(' ');
|
|
88
|
+
}
|
|
89
|
+
const notification = {
|
|
90
|
+
jsonrpc: "2.0",
|
|
91
|
+
method: "notifications/message",
|
|
92
|
+
params: {
|
|
93
|
+
level: level,
|
|
94
|
+
logger: "desktop-commander",
|
|
95
|
+
data: data
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
// Send as valid JSON-RPC notification
|
|
99
|
+
this.originalStdoutWrite.call(process.stdout, JSON.stringify(notification) + '\n');
|
|
100
|
+
}
|
|
101
|
+
catch (error) {
|
|
102
|
+
// Fallback to stderr if JSON serialization fails
|
|
103
|
+
process.stderr.write(`[${level.toUpperCase()}] ${args.join(' ')}\n`);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Public method to send log notifications from anywhere in the application
|
|
108
|
+
*/
|
|
109
|
+
sendLog(level, message, data) {
|
|
110
|
+
try {
|
|
111
|
+
const notification = {
|
|
112
|
+
jsonrpc: "2.0",
|
|
113
|
+
method: "notifications/message",
|
|
114
|
+
params: {
|
|
115
|
+
level: level,
|
|
116
|
+
logger: "desktop-commander",
|
|
117
|
+
data: data ? { message, ...data } : message
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
this.originalStdoutWrite.call(process.stdout, JSON.stringify(notification) + '\n');
|
|
121
|
+
}
|
|
122
|
+
catch (error) {
|
|
123
|
+
process.stderr.write(`[${level.toUpperCase()}] ${message}\n`);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Send a progress notification (useful for long-running operations)
|
|
128
|
+
*/
|
|
129
|
+
sendProgress(token, value, total) {
|
|
130
|
+
try {
|
|
131
|
+
const notification = {
|
|
132
|
+
jsonrpc: "2.0",
|
|
133
|
+
method: "notifications/progress",
|
|
134
|
+
params: {
|
|
135
|
+
progressToken: token,
|
|
136
|
+
value: value,
|
|
137
|
+
...(total && { total })
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
this.originalStdoutWrite.call(process.stdout, JSON.stringify(notification) + '\n');
|
|
141
|
+
}
|
|
142
|
+
catch (error) {
|
|
143
|
+
process.stderr.write(`[PROGRESS] ${token}: ${value}${total ? `/${total}` : ''}\n`);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Send a custom notification with any method name
|
|
148
|
+
*/
|
|
149
|
+
sendCustomNotification(method, params) {
|
|
150
|
+
try {
|
|
151
|
+
const notification = {
|
|
152
|
+
jsonrpc: "2.0",
|
|
153
|
+
method: method,
|
|
154
|
+
params: params
|
|
155
|
+
};
|
|
156
|
+
this.originalStdoutWrite.call(process.stdout, JSON.stringify(notification) + '\n');
|
|
157
|
+
}
|
|
158
|
+
catch (error) {
|
|
159
|
+
process.stderr.write(`[NOTIFICATION] ${method}: ${JSON.stringify(params)}\n`);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Cleanup method to restore original console methods if needed
|
|
164
|
+
*/
|
|
165
|
+
cleanup() {
|
|
166
|
+
if (this.originalConsole) {
|
|
167
|
+
console.log = this.originalConsole.log;
|
|
168
|
+
console.warn = this.originalConsole.warn;
|
|
169
|
+
console.error = this.originalConsole.error;
|
|
170
|
+
console.debug = this.originalConsole.debug;
|
|
171
|
+
console.info = this.originalConsole.info;
|
|
172
|
+
}
|
|
173
|
+
if (this.originalStdoutWrite) {
|
|
174
|
+
process.stdout.write = this.originalStdoutWrite;
|
|
175
|
+
}
|
|
21
176
|
}
|
|
22
177
|
}
|
|
@@ -14,6 +14,8 @@ export { handleEditBlock };
|
|
|
14
14
|
export async function handleSearchCode(args) {
|
|
15
15
|
const parsed = SearchCodeArgsSchema.parse(args);
|
|
16
16
|
const timeoutMs = parsed.timeoutMs || 30000; // 30 seconds default
|
|
17
|
+
// Limit maxResults to prevent overwhelming responses
|
|
18
|
+
const safeMaxResults = parsed.maxResults ? Math.min(parsed.maxResults, 5000) : 2000; // Default to 2000 instead of 1000
|
|
17
19
|
// Apply timeout at the handler level
|
|
18
20
|
const searchOperation = async () => {
|
|
19
21
|
return await searchTextInFiles({
|
|
@@ -21,7 +23,7 @@ export async function handleSearchCode(args) {
|
|
|
21
23
|
pattern: parsed.pattern,
|
|
22
24
|
filePattern: parsed.filePattern,
|
|
23
25
|
ignoreCase: parsed.ignoreCase,
|
|
24
|
-
maxResults:
|
|
26
|
+
maxResults: safeMaxResults,
|
|
25
27
|
includeHidden: parsed.includeHidden,
|
|
26
28
|
contextLines: parsed.contextLines,
|
|
27
29
|
// Don't pass timeoutMs down to the implementation
|
|
@@ -53,16 +55,33 @@ export async function handleSearchCode(args) {
|
|
|
53
55
|
content: [{ type: "text", text: "No matches found" }],
|
|
54
56
|
};
|
|
55
57
|
}
|
|
56
|
-
// Format the results in a VS Code-like format
|
|
58
|
+
// Format the results in a VS Code-like format with early truncation
|
|
57
59
|
let currentFile = "";
|
|
58
60
|
let formattedResults = "";
|
|
59
|
-
|
|
61
|
+
const MAX_RESPONSE_SIZE = 900000; // 900KB limit - well below the 1MB API limit
|
|
62
|
+
let resultsProcessed = 0;
|
|
63
|
+
let totalResults = results.length;
|
|
64
|
+
for (const result of results) {
|
|
65
|
+
// Check if adding this result would exceed our limit
|
|
66
|
+
const newFileHeader = result.file !== currentFile ? `\n${result.file}:\n` : '';
|
|
67
|
+
const newLine = ` ${result.line}: ${result.match}\n`;
|
|
68
|
+
const potentialAddition = newFileHeader + newLine;
|
|
69
|
+
// If adding this would exceed the limit, truncate here
|
|
70
|
+
if (formattedResults.length + potentialAddition.length > MAX_RESPONSE_SIZE) {
|
|
71
|
+
const remainingResults = totalResults - resultsProcessed;
|
|
72
|
+
const avgResultLength = formattedResults.length / Math.max(resultsProcessed, 1);
|
|
73
|
+
const estimatedRemainingChars = remainingResults * avgResultLength;
|
|
74
|
+
const truncationMessage = `\n\n[Results truncated - ${remainingResults} more results available (approximately ${Math.round(estimatedRemainingChars).toLocaleString()} more characters). Try refining your search pattern or using a more specific file pattern to get fewer results.]`;
|
|
75
|
+
formattedResults += truncationMessage;
|
|
76
|
+
break;
|
|
77
|
+
}
|
|
60
78
|
if (result.file !== currentFile) {
|
|
61
|
-
formattedResults +=
|
|
79
|
+
formattedResults += newFileHeader;
|
|
62
80
|
currentFile = result.file;
|
|
63
81
|
}
|
|
64
|
-
formattedResults +=
|
|
65
|
-
|
|
82
|
+
formattedResults += newLine;
|
|
83
|
+
resultsProcessed++;
|
|
84
|
+
}
|
|
66
85
|
return {
|
|
67
86
|
content: [{ type: "text", text: formattedResults.trim() }],
|
|
68
87
|
};
|
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
import { ServerResult } from '../types.js';
|
|
2
2
|
/**
|
|
3
|
-
* Handle
|
|
3
|
+
* Handle start_process command (improved execute_command)
|
|
4
4
|
*/
|
|
5
|
-
export declare function
|
|
5
|
+
export declare function handleStartProcess(args: unknown): Promise<ServerResult>;
|
|
6
6
|
/**
|
|
7
|
-
* Handle
|
|
7
|
+
* Handle read_process_output command (improved read_output)
|
|
8
8
|
*/
|
|
9
|
-
export declare function
|
|
9
|
+
export declare function handleReadProcessOutput(args: unknown): Promise<ServerResult>;
|
|
10
|
+
/**
|
|
11
|
+
* Handle interact_with_process command (improved send_input)
|
|
12
|
+
*/
|
|
13
|
+
export declare function handleInteractWithProcess(args: unknown): Promise<ServerResult>;
|
|
10
14
|
/**
|
|
11
15
|
* Handle force_terminate command
|
|
12
16
|
*/
|
|
@@ -1,18 +1,24 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { startProcess, readProcessOutput, interactWithProcess, forceTerminate, listSessions } from '../tools/improved-process-tools.js';
|
|
2
|
+
import { StartProcessArgsSchema, ReadProcessOutputArgsSchema, ForceTerminateArgsSchema } from '../tools/schemas.js';
|
|
3
3
|
/**
|
|
4
|
-
* Handle
|
|
4
|
+
* Handle start_process command (improved execute_command)
|
|
5
5
|
*/
|
|
6
|
-
export async function
|
|
7
|
-
const parsed =
|
|
8
|
-
return
|
|
6
|
+
export async function handleStartProcess(args) {
|
|
7
|
+
const parsed = StartProcessArgsSchema.parse(args);
|
|
8
|
+
return startProcess(parsed);
|
|
9
9
|
}
|
|
10
10
|
/**
|
|
11
|
-
* Handle
|
|
11
|
+
* Handle read_process_output command (improved read_output)
|
|
12
12
|
*/
|
|
13
|
-
export async function
|
|
14
|
-
const parsed =
|
|
15
|
-
return
|
|
13
|
+
export async function handleReadProcessOutput(args) {
|
|
14
|
+
const parsed = ReadProcessOutputArgsSchema.parse(args);
|
|
15
|
+
return readProcessOutput(parsed);
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Handle interact_with_process command (improved send_input)
|
|
19
|
+
*/
|
|
20
|
+
export async function handleInteractWithProcess(args) {
|
|
21
|
+
return interactWithProcess(args);
|
|
16
22
|
}
|
|
17
23
|
/**
|
|
18
24
|
* Handle force_terminate command
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Add immediate logging before any imports
|
|
3
|
+
console.error("[DXT] === ENTRY POINT START ===");
|
|
4
|
+
console.error(`[DXT] Node version: ${process.version}`);
|
|
5
|
+
console.error(`[DXT] Platform: ${process.platform}`);
|
|
6
|
+
console.error(`[DXT] Working directory: ${process.cwd()}`);
|
|
7
|
+
console.error(`[DXT] __dirname: ${__dirname}`);
|
|
8
|
+
console.error(`[DXT] Args: ${JSON.stringify(process.argv)}`);
|
|
9
|
+
// Add error handlers immediately
|
|
10
|
+
process.on('uncaughtException', (error) => {
|
|
11
|
+
console.error(`[DXT] UNCAUGHT EXCEPTION: ${error.message}`);
|
|
12
|
+
console.error(`[DXT] Stack: ${error.stack}`);
|
|
13
|
+
});
|
|
14
|
+
process.on('unhandledRejection', (reason) => {
|
|
15
|
+
console.error(`[DXT] UNHANDLED REJECTION: ${String(reason)}`);
|
|
16
|
+
});
|
|
17
|
+
process.on('exit', (code) => {
|
|
18
|
+
console.error(`[DXT] PROCESS EXITING with code: ${code}`);
|
|
19
|
+
});
|
|
20
|
+
console.error("[DXT] About to import modules...");
|
|
21
|
+
// Simplified entry point for DXT that avoids configuration loading issues
|
|
22
|
+
import { FilteredStdioServerTransport } from './custom-stdio.js';
|
|
23
|
+
console.error("[DXT] FilteredStdioServerTransport imported");
|
|
24
|
+
import { server } from './server.js';
|
|
25
|
+
console.error("[DXT] Server imported");
|
|
26
|
+
async function runDXTServer() {
|
|
27
|
+
try {
|
|
28
|
+
console.error("[DXT] === runDXTServer() START ===");
|
|
29
|
+
console.error("=== DXT DEBUG START ===");
|
|
30
|
+
console.error(`Node version: ${process.version}`);
|
|
31
|
+
console.error(`Platform: ${process.platform}`);
|
|
32
|
+
console.error(`Working directory: ${process.cwd()}`);
|
|
33
|
+
console.error(`__dirname: ${__dirname}`);
|
|
34
|
+
console.error(`Args: ${JSON.stringify(process.argv)}`);
|
|
35
|
+
console.error("=== DXT DEBUG END ===");
|
|
36
|
+
console.error("[DXT] About to create transport...");
|
|
37
|
+
// Create transport
|
|
38
|
+
const transport = new FilteredStdioServerTransport();
|
|
39
|
+
console.error("[DXT] Transport created successfully");
|
|
40
|
+
// Send structured debug info
|
|
41
|
+
transport.sendLog("info", "DXT Server Starting", {
|
|
42
|
+
nodeVersion: process.version,
|
|
43
|
+
platform: process.platform,
|
|
44
|
+
cwd: process.cwd(),
|
|
45
|
+
dirname: __dirname,
|
|
46
|
+
argv: process.argv
|
|
47
|
+
});
|
|
48
|
+
console.error("[DXT] Debug info sent via transport");
|
|
49
|
+
// Connect server
|
|
50
|
+
console.error("[DXT] About to connect server...");
|
|
51
|
+
console.error("Connecting MCP server...");
|
|
52
|
+
await server.connect(transport);
|
|
53
|
+
console.error("[DXT] Server connected successfully!");
|
|
54
|
+
console.error("MCP server connected successfully");
|
|
55
|
+
transport.sendLog("info", "MCP server connected successfully in DXT mode");
|
|
56
|
+
console.error("[DXT] === runDXTServer() END ===");
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
60
|
+
const errorStack = error instanceof Error ? error.stack : undefined;
|
|
61
|
+
console.error(`[DXT] FATAL ERROR in runDXTServer: ${errorMessage}`);
|
|
62
|
+
if (errorStack) {
|
|
63
|
+
console.error(`[DXT] Stack: ${errorStack}`);
|
|
64
|
+
}
|
|
65
|
+
process.exit(1);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
console.error("[DXT] About to call runDXTServer...");
|
|
69
|
+
// Run the server
|
|
70
|
+
runDXTServer().catch((error) => {
|
|
71
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
72
|
+
console.error(`[DXT] Failed to start in catch block: ${errorMessage}`);
|
|
73
|
+
console.error(`[DXT] Failed to start: ${errorMessage}`);
|
|
74
|
+
process.exit(1);
|
|
75
|
+
});
|
|
76
|
+
console.error("[DXT] === ENTRY POINT END ===");
|