@j0hanz/filesystem-mcp 1.1.1 → 1.1.2

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
@@ -137,6 +137,15 @@ The server communicates via `stdio`. Ensure your MCP client is configured to run
137
137
  | `apply_patch` | Apply unified patch | `path`, `patch` |
138
138
  | `search_and_replace` | Search & replace across files | `filePattern`, `searchPattern`, `replacement` |
139
139
 
140
+ ### Behavioral Notes
141
+
142
+ - `rm` with `recursive: false`:
143
+ - Deletes files and empty directories.
144
+ - Returns `E_INVALID_INPUT` for non-empty directories with guidance to use `recursive: true`.
145
+ - `includeIgnored: false` (default) for navigation/search tools:
146
+ - Excludes common generated/vendor directories such as `node_modules`, `dist`, `.git`, and similar patterns.
147
+ - Set `includeIgnored: true` to include those entries.
148
+
140
149
  ### Resources
141
150
 
142
151
  | URI Pattern | Description |
@@ -252,6 +261,12 @@ args = ["-y", "@j0hanz/filesystem-mcp@latest", "${workspaceFolder}"]
252
261
  - **Path Restrictions**: All file operations are strictly validated against the allowed root directories provided at startup.
253
262
  - **Path Validation**: Uses `isPathWithinDirectories` to prevent path traversal attacks.
254
263
  - **Hidden Files**: Hidden files (starting with `.`) are excluded by default in listings and searches unless explicitly requested.
264
+ - **Ignored Directories**: Ignored directories (for example `node_modules`, `.git`, `dist`) are excluded by default unless `includeIgnored=true`.
265
+
266
+ ## Testing Notes
267
+
268
+ - For protocol-level validation, prefer an MCP SDK client (`listTools`, `listResources`, `listPrompts`, `callTool`, `readResource`) as source-of-truth.
269
+ - Some third-party MCP CLIs may have URI parsing limitations when reading resources; if this happens, verify resource behavior through SDK client calls.
255
270
 
256
271
  ## Development Workflow
257
272
 
@@ -146,24 +146,42 @@ export const KNOWN_BINARY_EXTENSIONS = new Set([
146
146
  '.dat',
147
147
  ]);
148
148
  export const DEFAULT_EXCLUDE_PATTERNS = [
149
+ '**/node_modules',
149
150
  '**/node_modules/**',
151
+ '**/dist',
150
152
  '**/dist/**',
153
+ '**/build',
151
154
  '**/build/**',
155
+ '**/coverage',
152
156
  '**/coverage/**',
157
+ '**/.git',
153
158
  '**/.git/**',
159
+ '**/.vscode',
154
160
  '**/.vscode/**',
161
+ '**/.idea',
155
162
  '**/.idea/**',
156
163
  '**/.DS_Store',
164
+ '**/.next',
157
165
  '**/.next/**',
166
+ '**/.nuxt',
158
167
  '**/.nuxt/**',
168
+ '**/.output',
159
169
  '**/.output/**',
170
+ '**/.svelte-kit',
160
171
  '**/.svelte-kit/**',
172
+ '**/.cache',
161
173
  '**/.cache/**',
174
+ '**/.yarn',
162
175
  '**/.yarn/**',
176
+ '**/jspm_packages',
163
177
  '**/jspm_packages/**',
178
+ '**/bower_components',
164
179
  '**/bower_components/**',
180
+ '**/out',
165
181
  '**/out/**',
182
+ '**/tmp',
166
183
  '**/tmp/**',
184
+ '**/.temp',
167
185
  '**/.temp/**',
168
186
  '**/npm-debug.log',
169
187
  '**/yarn-debug.log',
@@ -45,7 +45,7 @@ async function handleApplyPatch(args, signal) {
45
45
  autoConvertLineEndings: args.autoConvertLineEndings,
46
46
  });
47
47
  if (patched === false) {
48
- throw new McpError(ErrorCode.E_INVALID_INPUT, `Patch application failed. The file content may have changed or the patch context is insufficient. Try enable fuzzy matching.`);
48
+ throw new McpError(ErrorCode.E_INVALID_INPUT, 'Patch application failed. The file content may have changed or patch context is insufficient. Generate a fresh patch via diff_files against the current file, then retry. If differences are minor, enable fuzzy matching (fuzzy=true or fuzzFactor).');
49
49
  }
50
50
  if (args.dryRun) {
51
51
  return buildToolResponse('Dry run successful. Patch can be applied.', {
@@ -19,10 +19,32 @@ const DELETE_FILE_TOOL = {
19
19
  };
20
20
  async function handleDeleteFile(args, signal) {
21
21
  const validPath = await validatePathForWrite(args.path, signal);
22
- await withAbort(fs.rm(validPath, {
23
- recursive: args.recursive,
24
- force: args.ignoreIfNotExists,
25
- }), signal);
22
+ let stats;
23
+ try {
24
+ stats = await withAbort(fs.lstat(validPath), signal);
25
+ }
26
+ catch (error) {
27
+ if (isNodeError(error) &&
28
+ error.code === 'ENOENT' &&
29
+ args.ignoreIfNotExists) {
30
+ return buildToolResponse(`Successfully deleted: ${args.path}`, {
31
+ ok: true,
32
+ path: validPath,
33
+ });
34
+ }
35
+ throw error;
36
+ }
37
+ if (stats.isDirectory() && !args.recursive) {
38
+ // Use rmdir for non-recursive directory deletes so non-empty directories
39
+ // consistently return ENOTEMPTY-style errors with actionable guidance.
40
+ await withAbort(fs.rmdir(validPath), signal);
41
+ }
42
+ else {
43
+ await withAbort(fs.rm(validPath, {
44
+ recursive: args.recursive,
45
+ force: args.ignoreIfNotExists,
46
+ }), signal);
47
+ }
26
48
  return buildToolResponse(`Successfully deleted: ${args.path}`, {
27
49
  ok: true,
28
50
  path: validPath,
@@ -45,6 +67,12 @@ export function registerDeleteFileTool(server, options = {}) {
45
67
  if (error.code === 'ENOTEMPTY') {
46
68
  return buildToolErrorResponse(new Error(`Directory is not empty: ${args.path}. Use recursive: true to delete non-empty directories.`), ErrorCode.E_INVALID_INPUT, args.path);
47
69
  }
70
+ if (error.code === 'EISDIR') {
71
+ return buildToolErrorResponse(new Error(`Path is a directory: ${args.path}. Use recursive: true to delete directories.`), ErrorCode.E_INVALID_INPUT, args.path);
72
+ }
73
+ if (error.code === 'EEXIST') {
74
+ return buildToolErrorResponse(new Error(`Directory is not empty: ${args.path}. Use recursive: true to delete non-empty directories.`), ErrorCode.E_INVALID_INPUT, args.path);
75
+ }
48
76
  if (error.code === 'EPERM' || error.code === 'EACCES') {
49
77
  return buildToolErrorResponse(error, ErrorCode.E_PERMISSION_DENIED, args.path);
50
78
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@j0hanz/filesystem-mcp",
3
- "version": "1.1.1",
3
+ "version": "1.1.2",
4
4
  "mcpName": "io.github.j0hanz/filesystem-mcp",
5
5
  "description": "MCP Server that enables LLMs to interact with the local filesystem.",
6
6
  "type": "module",