unix-disk-mcp 0.2.0 → 0.4.0

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 CHANGED
@@ -95,6 +95,7 @@ unix-disk-mcp delete
95
95
  - `get_disk_usage` - Disk space overview
96
96
  - `find_large_items` - Find big files/folders (supports progressive depth exploration)
97
97
  - `get_item_info` - Details on specific paths
98
+ - `search_files` - Find files/directories by name pattern
98
99
 
99
100
  **Discovery:**
100
101
  - `list_applications` - Installed apps with last-opened dates (macOS only)
@@ -147,4 +148,4 @@ unix-disk-mcp help # Show help
147
148
 
148
149
  ## License
149
150
 
150
- MIT
151
+ GPL-3.0-or-later
@@ -17,11 +17,13 @@ const MCP_CONFIGS = {
17
17
  ? join(homedir(), "Library", "Application Support", "Code", "User", "mcp.json")
18
18
  : join(homedir(), ".config", "Code", "User", "mcp.json"),
19
19
  },
20
+ cursor: {
21
+ name: "Cursor",
22
+ path: join(homedir(), ".cursor", "mcp.json"),
23
+ },
20
24
  claude: {
21
25
  name: "Claude Desktop",
22
- path: process.platform === 'darwin'
23
- ? join(homedir(), "Library", "Application Support", "Claude", "claude_desktop_config.json")
24
- : join(homedir(), ".config", "Claude", "claude_desktop_config.json"),
26
+ path: join(homedir(), ".claude.json"),
25
27
  },
26
28
  };
27
29
  /**
@@ -81,19 +83,22 @@ async function configureProtectedPaths(rl) {
81
83
  async function selectMCPClient(rl) {
82
84
  console.log("\nšŸ”§ MCP Client Configuration\n");
83
85
  console.log("Which MCP client would you like to configure?\n");
84
- console.log(" 1. VS Code (Roo Cline)");
85
- console.log(" 2. Claude Desktop");
86
- console.log(" 3. Both");
87
- console.log(" 4. None (manual configuration)\n");
88
- const answer = await ask(rl, "Select [1-4]: ");
86
+ console.log(" 1. VS Code");
87
+ console.log(" 2. Cursor");
88
+ console.log(" 3. Claude Desktop");
89
+ console.log(" 4. All of the above");
90
+ console.log(" 5. None (manual configuration)\n");
91
+ const answer = await ask(rl, "Select [1-5]: ");
89
92
  switch (answer.trim()) {
90
93
  case "1":
91
94
  return "vscode";
92
95
  case "2":
93
- return "claude";
96
+ return "cursor";
94
97
  case "3":
95
- return "both";
98
+ return "claude";
96
99
  case "4":
100
+ return "all";
101
+ case "5":
97
102
  default:
98
103
  return "none";
99
104
  }
@@ -110,24 +115,24 @@ function updateMCPConfig(client, configPath) {
110
115
  try {
111
116
  const raw = readFileSync(config.path, "utf-8");
112
117
  const data = JSON.parse(raw);
113
- if (client === "vscode") {
114
- // VS Code MCP config format
115
- if (!data.servers) {
116
- data.servers = {};
118
+ if (client === "cursor") {
119
+ // Cursor format: uses "mcpServers" without "type"
120
+ if (!data.mcpServers) {
121
+ data.mcpServers = {};
117
122
  }
118
- data.servers["unix-disk-mcp"] = {
119
- type: "stdio",
123
+ data.mcpServers["unix-disk-mcp"] = {
120
124
  command: "unix-disk-mcp",
125
+ args: [],
121
126
  };
122
127
  }
123
128
  else {
124
- // Claude Desktop config format
125
- if (!data.mcpServers) {
126
- data.mcpServers = {};
129
+ // VS Code & Claude format: use "servers" with "type"
130
+ if (!data.servers) {
131
+ data.servers = {};
127
132
  }
128
- data.mcpServers["unix-disk-mcp"] = {
133
+ data.servers["unix-disk-mcp"] = {
134
+ type: "stdio",
129
135
  command: "unix-disk-mcp",
130
- args: [],
131
136
  };
132
137
  }
133
138
  writeFileSync(config.path, JSON.stringify(data, null, 2));
@@ -166,8 +171,10 @@ function printManualInstructions() {
166
171
  args: [],
167
172
  },
168
173
  }, null, 2));
169
- console.log("\n\nVS Code (Roo Cline):");
174
+ console.log("\n\nVS Code:");
170
175
  console.log(` ${MCP_CONFIGS.vscode.path}\n`);
176
+ console.log("Cursor:");
177
+ console.log(` ${MCP_CONFIGS.cursor.path}\n`);
171
178
  console.log("Claude Desktop:");
172
179
  console.log(` ${MCP_CONFIGS.claude.path}\n`);
173
180
  }
@@ -191,10 +198,13 @@ export async function runSetup() {
191
198
  printManualInstructions();
192
199
  }
193
200
  else {
194
- if (client === "vscode" || client === "both") {
201
+ if (client === "vscode" || client === "all") {
195
202
  updateMCPConfig("vscode", getConfigPath());
196
203
  }
197
- if (client === "claude" || client === "both") {
204
+ if (client === "cursor" || client === "all") {
205
+ updateMCPConfig("cursor", getConfigPath());
206
+ }
207
+ if (client === "claude" || client === "all") {
198
208
  updateMCPConfig("claude", getConfigPath());
199
209
  }
200
210
  console.log("\nāœ… Setup complete! Restart your MCP client to use the server.\n");
package/dist/server.js CHANGED
@@ -5,7 +5,8 @@ import { registerStagingTools } from "./tools/staging.js";
5
5
  export function createServer(config) {
6
6
  const server = new McpServer({
7
7
  name: "unix-disk-mcp",
8
- version: "0.1.0",
8
+ version: "0.4.0",
9
+ description: "AI-assisted disk cleanup for Unix systems. **Recommended workflow:** 1) Start with get_disk_usage for overview 2) Use search_files or find_large_items to identify targets 3) Stage items for deletion 4) User executes deletion manually. You can explore but never delete files.",
9
10
  });
10
11
  // Register all tools
11
12
  registerExplorationTools(server, config);
@@ -67,7 +67,7 @@ export function registerExplorationTools(server, config) {
67
67
  }
68
68
  });
69
69
  // get_disk_usage
70
- server.tool("get_disk_usage", "Get overview of disk space usage", {}, async () => {
70
+ server.tool("get_disk_usage", "Get overview of disk space usage. **Use this first** when exploring disk usage to understand which filesystems/volumes need attention and get a breakdown of home directory space.", {}, async () => {
71
71
  try {
72
72
  let disk;
73
73
  if (process.platform === 'darwin') {
@@ -331,4 +331,97 @@ export function registerExplorationTools(server, config) {
331
331
  };
332
332
  }
333
333
  });
334
+ // search_files
335
+ server.tool("search_files", "Search for files and directories by name pattern. Use this to find all instances of an app, package, or file type across the system.", {
336
+ query: z.string().describe("Search query - can be exact name or pattern (e.g., 'Anki', 'node_modules', '*.mp4')"),
337
+ search_path: z.string().optional().describe("Starting directory (defaults to home directory)"),
338
+ max_results: z.number().optional().default(50).describe("Maximum number of results to return"),
339
+ }, async ({ query, search_path, max_results }) => {
340
+ try {
341
+ const startPath = search_path ? expandPath(search_path) : homedir();
342
+ let results = [];
343
+ if (process.platform === 'darwin') {
344
+ // macOS: Use mdfind (Spotlight) for fast searching
345
+ try {
346
+ const mdfindCmd = search_path
347
+ ? `mdfind -onlyin "${startPath}" -name "${query}"`
348
+ : `mdfind -name "${query}"`;
349
+ const output = execSync(mdfindCmd, {
350
+ encoding: "utf-8",
351
+ maxBuffer: 10 * 1024 * 1024, // 10MB buffer
352
+ });
353
+ results = output.trim().split("\n").filter(Boolean);
354
+ }
355
+ catch (error) {
356
+ // Fall back to find if mdfind fails
357
+ const findCmd = `find "${startPath}" -iname "*${query}*" 2>/dev/null`;
358
+ const output = execSync(findCmd, {
359
+ encoding: "utf-8",
360
+ maxBuffer: 10 * 1024 * 1024,
361
+ });
362
+ results = output.trim().split("\n").filter(Boolean);
363
+ }
364
+ }
365
+ else {
366
+ // Linux: Use find
367
+ const findCmd = `find "${startPath}" -iname "*${query}*" 2>/dev/null`;
368
+ const output = execSync(findCmd, {
369
+ encoding: "utf-8",
370
+ maxBuffer: 10 * 1024 * 1024,
371
+ });
372
+ results = output.trim().split("\n").filter(Boolean);
373
+ }
374
+ // Limit results and get sizes
375
+ const limitedResults = results.slice(0, max_results);
376
+ const items = limitedResults.map(path => {
377
+ try {
378
+ const stats = statSync(path);
379
+ return {
380
+ path,
381
+ type: stats.isDirectory() ? "directory" : "file",
382
+ size: stats.size,
383
+ modified: stats.mtime.toISOString(),
384
+ };
385
+ }
386
+ catch {
387
+ return {
388
+ path,
389
+ type: "unknown",
390
+ size: 0,
391
+ error: "Could not read stats",
392
+ };
393
+ }
394
+ });
395
+ return {
396
+ content: [
397
+ {
398
+ type: "text",
399
+ text: JSON.stringify({
400
+ success: true,
401
+ data: {
402
+ query,
403
+ total_found: results.length,
404
+ returned: items.length,
405
+ items,
406
+ },
407
+ }, null, 2),
408
+ },
409
+ ],
410
+ };
411
+ }
412
+ catch (error) {
413
+ return {
414
+ content: [
415
+ {
416
+ type: "text",
417
+ text: JSON.stringify({
418
+ success: false,
419
+ error: error instanceof Error ? error.message : "Unknown error",
420
+ code: "SEARCH_FILES_FAILED",
421
+ }),
422
+ },
423
+ ],
424
+ };
425
+ }
426
+ });
334
427
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "unix-disk-mcp",
3
- "version": "0.2.0",
3
+ "version": "0.4.0",
4
4
  "description": "MCP server for AI-assisted disk cleanup on Unix systems (macOS and Linux)",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",