@j0hanz/filesystem-context-mcp 1.0.4 → 1.0.7

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 (95) hide show
  1. package/README.md +27 -26
  2. package/dist/config/types.d.ts +1 -1
  3. package/dist/config/types.d.ts.map +1 -1
  4. package/dist/instructions.md +209 -0
  5. package/dist/lib/directory-helpers.d.ts +5 -0
  6. package/dist/lib/directory-helpers.d.ts.map +1 -0
  7. package/dist/lib/directory-helpers.js +39 -0
  8. package/dist/lib/directory-helpers.js.map +1 -0
  9. package/dist/lib/file-operations.d.ts.map +1 -1
  10. package/dist/lib/file-operations.js +9 -74
  11. package/dist/lib/file-operations.js.map +1 -1
  12. package/dist/lib/fs-helpers.d.ts.map +1 -1
  13. package/dist/lib/fs-helpers.js +0 -5
  14. package/dist/lib/fs-helpers.js.map +1 -1
  15. package/dist/lib/mcp-logger.d.ts +11 -0
  16. package/dist/lib/mcp-logger.d.ts.map +1 -0
  17. package/dist/lib/mcp-logger.js +45 -0
  18. package/dist/lib/mcp-logger.js.map +1 -0
  19. package/dist/lib/sorting.d.ts +12 -0
  20. package/dist/lib/sorting.d.ts.map +1 -0
  21. package/dist/lib/sorting.js +41 -0
  22. package/dist/lib/sorting.js.map +1 -0
  23. package/dist/prompts/analyze-codebase.d.ts +3 -0
  24. package/dist/prompts/analyze-codebase.d.ts.map +1 -0
  25. package/dist/prompts/analyze-codebase.js +144 -0
  26. package/dist/prompts/analyze-codebase.js.map +1 -0
  27. package/dist/prompts/filesystem-query.d.ts +3 -0
  28. package/dist/prompts/filesystem-query.d.ts.map +1 -0
  29. package/dist/prompts/filesystem-query.js +168 -0
  30. package/dist/prompts/filesystem-query.js.map +1 -0
  31. package/dist/prompts/find-duplicates.d.ts +3 -0
  32. package/dist/prompts/find-duplicates.d.ts.map +1 -0
  33. package/dist/prompts/find-duplicates.js +77 -0
  34. package/dist/prompts/find-duplicates.js.map +1 -0
  35. package/dist/prompts/index.d.ts +3 -0
  36. package/dist/prompts/index.d.ts.map +1 -0
  37. package/dist/prompts/index.js +13 -0
  38. package/dist/prompts/index.js.map +1 -0
  39. package/dist/prompts/project-overview.d.ts +3 -0
  40. package/dist/prompts/project-overview.d.ts.map +1 -0
  41. package/dist/prompts/project-overview.js +122 -0
  42. package/dist/prompts/project-overview.js.map +1 -0
  43. package/dist/prompts/search-and-replace.d.ts +3 -0
  44. package/dist/prompts/search-and-replace.d.ts.map +1 -0
  45. package/dist/prompts/search-and-replace.js +130 -0
  46. package/dist/prompts/search-and-replace.js.map +1 -0
  47. package/dist/prompts/shared.d.ts +3 -0
  48. package/dist/prompts/shared.d.ts.map +1 -0
  49. package/dist/prompts/shared.js +17 -0
  50. package/dist/prompts/shared.js.map +1 -0
  51. package/dist/resources/index.d.ts +3 -0
  52. package/dist/resources/index.d.ts.map +1 -0
  53. package/dist/resources/index.js +54 -0
  54. package/dist/resources/index.js.map +1 -0
  55. package/dist/schemas/inputs.d.ts.map +1 -1
  56. package/dist/schemas/inputs.js +11 -7
  57. package/dist/schemas/inputs.js.map +1 -1
  58. package/dist/schemas/outputs.d.ts +10 -8
  59. package/dist/schemas/outputs.d.ts.map +1 -1
  60. package/dist/schemas/outputs.js +2 -0
  61. package/dist/schemas/outputs.js.map +1 -1
  62. package/dist/server.d.ts.map +1 -1
  63. package/dist/server.js +37 -15
  64. package/dist/server.js.map +1 -1
  65. package/dist/tools/analyze-directory.d.ts.map +1 -1
  66. package/dist/tools/analyze-directory.js +14 -4
  67. package/dist/tools/analyze-directory.js.map +1 -1
  68. package/dist/tools/directory-tree.d.ts.map +1 -1
  69. package/dist/tools/directory-tree.js +19 -2
  70. package/dist/tools/directory-tree.js.map +1 -1
  71. package/dist/tools/get-file-info.d.ts.map +1 -1
  72. package/dist/tools/get-file-info.js +5 -1
  73. package/dist/tools/get-file-info.js.map +1 -1
  74. package/dist/tools/list-allowed-dirs.d.ts.map +1 -1
  75. package/dist/tools/list-allowed-dirs.js +16 -2
  76. package/dist/tools/list-allowed-dirs.js.map +1 -1
  77. package/dist/tools/list-directory.d.ts.map +1 -1
  78. package/dist/tools/list-directory.js +19 -7
  79. package/dist/tools/list-directory.js.map +1 -1
  80. package/dist/tools/read-file.d.ts.map +1 -1
  81. package/dist/tools/read-file.js +6 -1
  82. package/dist/tools/read-file.js.map +1 -1
  83. package/dist/tools/read-media-file.d.ts.map +1 -1
  84. package/dist/tools/read-media-file.js +5 -1
  85. package/dist/tools/read-media-file.js.map +1 -1
  86. package/dist/tools/read-multiple-files.d.ts.map +1 -1
  87. package/dist/tools/read-multiple-files.js +5 -1
  88. package/dist/tools/read-multiple-files.js.map +1 -1
  89. package/dist/tools/search-content.d.ts.map +1 -1
  90. package/dist/tools/search-content.js +44 -4
  91. package/dist/tools/search-content.js.map +1 -1
  92. package/dist/tools/search-files.d.ts.map +1 -1
  93. package/dist/tools/search-files.js +19 -4
  94. package/dist/tools/search-files.js.map +1 -1
  95. package/package.json +3 -2
package/README.md CHANGED
@@ -5,7 +5,7 @@ A secure, read-only MCP server for filesystem scanning, searching, and analysis
5
5
  [![npm version](https://img.shields.io/npm/v/@j0hanz/filesystem-context-mcp.svg)](https://www.npmjs.com/package/@j0hanz/filesystem-context-mcp)
6
6
  [![License](https://img.shields.io/npm/l/@j0hanz/filesystem-context-mcp)](LICENSE)
7
7
  [![Node.js](https://img.shields.io/badge/node-%3E%3D20.0.0-brightgreen)](https://nodejs.org)
8
- [![TypeScript](https://img.shields.io/badge/TypeScript-5.7-blue)](https://www.typescriptlang.org/)
8
+ [![TypeScript](https://img.shields.io/badge/TypeScript-5.7.2-blue)](https://www.typescriptlang.org/)
9
9
  [![MCP SDK](https://img.shields.io/badge/MCP%20SDK-1.12.0-purple)](https://modelcontextprotocol.io)
10
10
 
11
11
  ## One-Click Install
@@ -196,7 +196,7 @@ Search for files using glob patterns.
196
196
  | `path` | string | ✅ | - | Base directory to search from |
197
197
  | `pattern` | string | ✅ | - | Glob pattern (e.g., `**/*.ts`, `src/**/*.js`) |
198
198
  | `excludePatterns` | string[] | ❌ | `[]` | Patterns to exclude |
199
- | `maxResults` | number | ❌ | - | Maximum matches to return (1-10,000) |
199
+ | `maxResults` | number | ❌ | - | Maximum matches to return (max 10,000) |
200
200
  | `sortBy` | string | ❌ | `path` | Sort by: `name`, `size`, `modified`, `path` |
201
201
  | `maxDepth` | number | ❌ | - | Maximum directory depth to search (1-100) |
202
202
 
@@ -218,15 +218,15 @@ Search for files using glob patterns.
218
218
 
219
219
  Read the contents of a text file.
220
220
 
221
- | Parameter | Type | Required | Default | Description |
222
- | ----------- | ------ | -------- | ------- | ------------------------------------------------ |
223
- | `path` | string | ✅ | - | File path to read |
224
- | `encoding` | string | ❌ | `utf-8` | File encoding (`utf-8`, `ascii`, `base64`, etc.) |
225
- | `maxSize` | number | ❌ | 10MB | Maximum file size in bytes |
226
- | `lineStart` | number | ❌ | - | Start line (1-indexed) for reading a range |
227
- | `lineEnd` | number | ❌ | - | End line (inclusive) for reading a range |
228
- | `head` | number | ❌ | - | Read only first N lines |
229
- | `tail` | number | ❌ | - | Read only last N lines |
221
+ | Parameter | Type | Required | Default | Description |
222
+ | ----------- | ------ | -------- | ------- | ---------------------------------------------------------- |
223
+ | `path` | string | ✅ | - | File path to read |
224
+ | `encoding` | string | ❌ | `utf-8` | File encoding (`utf-8`, `ascii`, `base64`, etc.) |
225
+ | `maxSize` | number | ❌ | 10MB | Maximum file size in bytes |
226
+ | `lineStart` | number | ❌ | - | Start line (1-indexed, min 1) for reading a range |
227
+ | `lineEnd` | number | ❌ | - | End line (1-indexed, inclusive, min 1) for reading a range |
228
+ | `head` | number | ❌ | - | Read only first N lines |
229
+ | `tail` | number | ❌ | - | Read only last N lines |
230
230
 
231
231
  > **Note:** Cannot specify both `head` and `tail` simultaneously. Use `lineStart`/`lineEnd` for range reading.
232
232
 
@@ -301,13 +301,13 @@ Search for text content within files using regular expressions.
301
301
 
302
302
  Analyze a directory structure and return statistics.
303
303
 
304
- | Parameter | Type | Required | Default | Description |
305
- | ----------------- | -------- | -------- | ------- | -------------------------------------- |
306
- | `path` | string | ✅ | - | Directory to analyze |
307
- | `maxDepth` | number | ❌ | `10` | Maximum depth to analyze (0-100) |
308
- | `topN` | number | ❌ | `10` | Number of top items to return (1-1000) |
309
- | `excludePatterns` | string[] | ❌ | `[]` | Glob patterns to exclude |
310
- | `includeHidden` | boolean | ❌ | `false` | Include hidden files and directories |
304
+ | Parameter | Type | Required | Default | Description |
305
+ | ----------------- | -------- | -------- | ------- | ---------------------------------------- |
306
+ | `path` | string | ✅ | - | Directory to analyze |
307
+ | `maxDepth` | number | ❌ | `10` | Maximum depth to analyze (0-100) |
308
+ | `topN` | number | ❌ | `10` | Number of top items to return (max 1000) |
309
+ | `excludePatterns` | string[] | ❌ | `[]` | Glob patterns to exclude |
310
+ | `includeHidden` | boolean | ❌ | `false` | Include hidden files and directories |
311
311
 
312
312
  **Returns:** Statistics including total files/directories, total size, file type distribution, largest files, and recently modified files.
313
313
 
@@ -317,14 +317,14 @@ Analyze a directory structure and return statistics.
317
317
 
318
318
  Get a JSON tree structure of a directory, optimized for AI parsing.
319
319
 
320
- | Parameter | Type | Required | Default | Description |
321
- | ----------------- | -------- | -------- | ------- | --------------------------------------- |
322
- | `path` | string | ✅ | - | Directory path to build tree from |
323
- | `maxDepth` | number | ❌ | `5` | Maximum depth to traverse (0-50) |
324
- | `excludePatterns` | string[] | ❌ | `[]` | Glob patterns to exclude |
325
- | `includeHidden` | boolean | ❌ | `false` | Include hidden files and directories |
326
- | `includeSize` | boolean | ❌ | `false` | Include file sizes in the tree |
327
- | `maxFiles` | number | ❌ | - | Maximum total files to include (1-100k) |
320
+ | Parameter | Type | Required | Default | Description |
321
+ | ----------------- | -------- | -------- | ------- | -------------------------------------------- |
322
+ | `path` | string | ✅ | - | Directory path to build tree from |
323
+ | `maxDepth` | number | ❌ | `5` | Maximum depth to traverse (0-50) |
324
+ | `excludePatterns` | string[] | ❌ | `[]` | Glob patterns to exclude |
325
+ | `includeHidden` | boolean | ❌ | `false` | Include hidden files and directories |
326
+ | `includeSize` | boolean | ❌ | `false` | Include file sizes in the tree |
327
+ | `maxFiles` | number | ❌ | - | Maximum total files to include (max 100,000) |
328
328
 
329
329
  **Returns:** Hierarchical tree structure with file/directory nodes.
330
330
 
@@ -500,6 +500,7 @@ This server implements multiple layers of security:
500
500
  src/
501
501
  ├── index.ts # Entry point, CLI argument parsing
502
502
  ├── server.ts # MCP server setup, roots protocol handling
503
+ ├── instructions.md # AI instructions for tool usage (bundled with dist)
503
504
  ├── config/
504
505
  │ └── types.ts # Shared TypeScript types
505
506
  ├── lib/
@@ -149,7 +149,7 @@ export interface DetailedError {
149
149
  details?: Record<string, unknown>;
150
150
  }
151
151
  export interface ErrorResponse {
152
- [x: string]: unknown;
152
+ [key: string]: unknown;
153
153
  content: {
154
154
  type: 'text';
155
155
  text: string;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/config/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/config/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,209 @@
1
+ # Filesystem Context MCP Server
2
+
3
+ > **Read-only** tools for exploring directories, searching files, and analyzing codebases via the [Model Context Protocol (MCP)](https://modelcontextprotocol.io/).
4
+
5
+ This server enables AI assistants to safely explore and analyze filesystem contents without modification capabilities. All operations are sandboxed to explicitly allowed directories.
6
+
7
+ ---
8
+
9
+ ## Quick Reference
10
+
11
+ | Goal | Tool | Key Parameters |
12
+ | ------------------- | -------------------------- | ----------------------------------- |
13
+ | Check access | `list_allowed_directories` | — |
14
+ | Project structure | `directory_tree` | `maxDepth`, `excludePatterns` |
15
+ | List contents | `list_directory` | `recursive`, `sortBy` |
16
+ | Directory stats | `analyze_directory` | `topN`, `excludePatterns` |
17
+ | Find files | `search_files` | `pattern` (glob), `maxResults` |
18
+ | Search in files | `search_content` | `pattern` (regex), `contextLines` |
19
+ | Read file | `read_file` | `head`, `tail`, `lineStart/lineEnd` |
20
+ | Read multiple files | `read_multiple_files` | `paths[]` — **preferred for 2+** |
21
+ | File metadata | `get_file_info` | `path` |
22
+ | Binary/media files | `read_media_file` | `maxSize` |
23
+
24
+ ---
25
+
26
+ ## Workflows
27
+
28
+ ### Project Discovery
29
+
30
+ ```text
31
+ list_allowed_directories → directory_tree(maxDepth=3) → analyze_directory → read_multiple_files([package.json, README.md])
32
+ ```
33
+
34
+ ### Find & Read Code
35
+
36
+ ```text
37
+ search_files(pattern="**/*.ts") → read_multiple_files([...results])
38
+ ```
39
+
40
+ ### Search Patterns
41
+
42
+ ```text
43
+ search_content(pattern="TODO|FIXME", filePattern="**/*.ts", contextLines=2)
44
+ ```
45
+
46
+ ### Common Glob Patterns
47
+
48
+ | Pattern | Matches |
49
+ | --------------------- | ----------------------------------------- |
50
+ | `**/*.ts` | All TypeScript files |
51
+ | `src/**/*.{js,jsx}` | JS/JSX files under `src/` |
52
+ | `**/test/**` | All files in any `test/` directory |
53
+ | `**/*.test.ts` | Test files by naming convention |
54
+ | `!**/node_modules/**` | Exclude `node_modules/` (use in excludes) |
55
+
56
+ ---
57
+
58
+ ## Best Practices
59
+
60
+ **Do:**
61
+
62
+ - Use `read_multiple_files` for 2+ files (parallel, resilient)
63
+ - Set `maxResults`, `maxDepth`, `maxEntries` limits
64
+ - Use `excludePatterns=["node_modules", ".git", "dist"]`
65
+ - Preview with `head=50` before full reads
66
+
67
+ **Don't:**
68
+
69
+ - Loop `read_file` — batch with `read_multiple_files`
70
+ - Recursive search without `maxDepth`
71
+ - Search without `maxResults` on large codebases
72
+
73
+ ## Tool Details
74
+
75
+ ### `directory_tree`
76
+
77
+ JSON tree structure for AI parsing.
78
+
79
+ | Parameter | Default | Description |
80
+ | ----------------- | ------- | --------------------- |
81
+ | `path` | — | Directory path |
82
+ | `maxDepth` | 5 | Depth limit (0-50) |
83
+ | `excludePatterns` | [] | Glob patterns to skip |
84
+ | `includeHidden` | false | Include dotfiles |
85
+ | `includeSize` | false | Show file sizes |
86
+ | `maxFiles` | — | Limit total files |
87
+
88
+ ### `search_files`
89
+
90
+ Find files by glob pattern.
91
+
92
+ | Parameter | Default | Description |
93
+ | ----------------- | ------- | ------------------------- |
94
+ | `path` | — | Base directory |
95
+ | `pattern` | — | Glob: `**/*.ts`, `src/**` |
96
+ | `excludePatterns` | [] | Patterns to skip |
97
+ | `maxResults` | — | Limit (up to 10,000) |
98
+ | `sortBy` | "path" | `name/size/modified/path` |
99
+
100
+ ### `search_content`
101
+
102
+ Grep-like regex search in files.
103
+
104
+ | Parameter | Default | Description |
105
+ | --------------- | ------- | ------------------------- |
106
+ | `path` | — | Base directory |
107
+ | `pattern` | — | Regex: `TODO\|FIXME` |
108
+ | `filePattern` | `**/*` | Glob filter |
109
+ | `contextLines` | 0 | Lines before/after (0-10) |
110
+ | `caseSensitive` | false | Case matching |
111
+ | `wholeWord` | false | Word boundaries |
112
+ | `isLiteral` | false | Escape regex |
113
+ | `maxResults` | 100 | Limit matches |
114
+ | `skipBinary` | true | Skip binary files |
115
+
116
+ ### `read_file`
117
+
118
+ Read single file with line selection.
119
+
120
+ | Parameter | Default | Description |
121
+ | ----------- | ------- | ------------------------------- |
122
+ | `path` | — | File path |
123
+ | `encoding` | utf-8 | `utf-8/ascii/base64/hex/latin1` |
124
+ | `maxSize` | 10MB | Size limit |
125
+ | `head` | — | First N lines |
126
+ | `tail` | — | Last N lines |
127
+ | `lineStart` | — | Start line (1-indexed) |
128
+ | `lineEnd` | — | End line (inclusive) |
129
+
130
+ > ⚠️ Cannot combine `head/tail` with `lineStart/lineEnd`
131
+
132
+ ### `read_multiple_files`
133
+
134
+ Parallel batch reads — failures don't block others.
135
+
136
+ | Parameter | Default | Description |
137
+ | ---------- | ------- | ------------------ |
138
+ | `paths` | — | Array (max 100) |
139
+ | `encoding` | utf-8 | Encoding for all |
140
+ | `maxSize` | 10MB | Per-file limit |
141
+ | `head` | — | First N lines each |
142
+ | `tail` | — | Last N lines each |
143
+
144
+ ### `list_directory`
145
+
146
+ Flat listing with metadata.
147
+
148
+ | Parameter | Default | Description |
149
+ | ------------ | ------- | ------------------------- |
150
+ | `path` | — | Directory path |
151
+ | `recursive` | false | Include subdirs |
152
+ | `sortBy` | "name" | `name/size/modified/type` |
153
+ | `maxDepth` | 10 | Depth when recursive |
154
+ | `maxEntries` | — | Limit (up to 100,000) |
155
+
156
+ ### `analyze_directory`
157
+
158
+ Statistics: counts, sizes, types, largest/recent files.
159
+
160
+ | Parameter | Default | Description |
161
+ | ----------------- | ------- | ------------------ |
162
+ | `path` | — | Directory path |
163
+ | `maxDepth` | 10 | Analysis depth |
164
+ | `topN` | 10 | Top largest/recent |
165
+ | `excludePatterns` | [] | Patterns to skip |
166
+
167
+ ### `read_media_file`
168
+
169
+ Binary files as base64 with MIME type and dimensions.
170
+
171
+ | Parameter | Default | Description |
172
+ | --------- | ------- | --------------- |
173
+ | `path` | — | Media file path |
174
+ | `maxSize` | 50MB | Size limit |
175
+
176
+ ### `get_file_info`
177
+
178
+ Detailed metadata about a file or directory.
179
+
180
+ | Parameter | Default | Description |
181
+ | --------- | ------- | ------------------------- |
182
+ | `path` | — | Path to file or directory |
183
+
184
+ **Returns:** name, path, type, size, created, modified, accessed, permissions, isHidden, mimeType, symlinkTarget (if applicable).
185
+
186
+ ---
187
+
188
+ ## Error Codes
189
+
190
+ | Code | Cause | Solution |
191
+ | --------------------- | ---------------------------- | ------------------------------------- |
192
+ | `E_ACCESS_DENIED` | Path outside allowed dirs | Check `list_allowed_directories` |
193
+ | `E_NOT_FOUND` | Path doesn't exist | Verify path with `list_directory` |
194
+ | `E_NOT_FILE` | Expected file, got directory | Use `list_directory` instead |
195
+ | `E_NOT_DIRECTORY` | Expected directory, got file | Use `read_file` instead |
196
+ | `E_TOO_LARGE` | File exceeds size limit | Use `head/tail` or increase `maxSize` |
197
+ | `E_BINARY_FILE` | Binary in text operation | Use `read_media_file` |
198
+ | `E_TIMEOUT` | Operation took too long | Reduce limits |
199
+ | `E_INVALID_PATTERN` | Malformed glob/regex | Check glob/regex syntax |
200
+ | `E_PERMISSION_DENIED` | OS-level access denied | Check file permissions |
201
+
202
+ ---
203
+
204
+ ## Security
205
+
206
+ - **Read-only** — no writes, deletes, or modifications
207
+ - **Path validation** — symlinks cannot escape allowed directories
208
+ - **Binary detection** — prevents accidental base64 bloat
209
+ - **Input sanitization** — patterns validated for ReDoS protection
@@ -0,0 +1,5 @@
1
+ export declare function createExcludeMatcher(excludePatterns: string[]): (name: string, relativePath: string) => boolean;
2
+ export declare function handleDirectoryError(error: unknown): void;
3
+ export declare function classifyAccessError(error: unknown): 'symlink' | 'inaccessible';
4
+ export declare function insertSorted<T>(arr: T[], item: T, compare: (a: T, b: T) => boolean, maxLen: number): void;
5
+ //# sourceMappingURL=directory-helpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"directory-helpers.d.ts","sourceRoot":"","sources":["../../src/lib/directory-helpers.ts"],"names":[],"mappings":"AAKA,wBAAgB,oBAAoB,CAClC,eAAe,EAAE,MAAM,EAAE,GACxB,CAAC,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,KAAK,OAAO,CAOjD;AAGD,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAEzD;AAGD,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,OAAO,GACb,SAAS,GAAG,cAAc,CAS5B;AAGD,wBAAgB,YAAY,CAAC,CAAC,EAC5B,GAAG,EAAE,CAAC,EAAE,EACR,IAAI,EAAE,CAAC,EACP,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,OAAO,EAChC,MAAM,EAAE,MAAM,GACb,IAAI,CASN"}
@@ -0,0 +1,39 @@
1
+ import { Minimatch } from 'minimatch';
2
+ import { ErrorCode, McpError } from './errors.js';
3
+ // Create matcher from exclude patterns
4
+ export function createExcludeMatcher(excludePatterns) {
5
+ if (excludePatterns.length === 0) {
6
+ return () => false;
7
+ }
8
+ const matchers = excludePatterns.map((pattern) => new Minimatch(pattern));
9
+ return (name, relativePath) => matchers.some((m) => m.match(name) || m.match(relativePath));
10
+ }
11
+ // Handle directory traversal errors (silently ignored to avoid log noise)
12
+ export function handleDirectoryError(error) {
13
+ void error.code;
14
+ }
15
+ // Classify symlink/access errors for summary tracking
16
+ export function classifyAccessError(error) {
17
+ if (error instanceof McpError &&
18
+ (error.code === ErrorCode.E_ACCESS_DENIED ||
19
+ error.code === ErrorCode.E_SYMLINK_NOT_ALLOWED)) {
20
+ return 'symlink';
21
+ }
22
+ return 'inaccessible';
23
+ }
24
+ // Insert item into sorted array maintaining sort order (descending by comparator)
25
+ export function insertSorted(arr, item, compare, maxLen) {
26
+ if (maxLen <= 0)
27
+ return;
28
+ const idx = arr.findIndex((el) => compare(item, el));
29
+ if (idx === -1) {
30
+ if (arr.length < maxLen)
31
+ arr.push(item);
32
+ }
33
+ else {
34
+ arr.splice(idx, 0, item);
35
+ if (arr.length > maxLen)
36
+ arr.pop();
37
+ }
38
+ }
39
+ //# sourceMappingURL=directory-helpers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"directory-helpers.js","sourceRoot":"","sources":["../../src/lib/directory-helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAElD,uCAAuC;AACvC,MAAM,UAAU,oBAAoB,CAClC,eAAyB;IAEzB,IAAI,eAAe,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACjC,OAAO,GAAG,EAAE,CAAC,KAAK,CAAC;IACrB,CAAC;IACD,MAAM,QAAQ,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,IAAI,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC;IAC1E,OAAO,CAAC,IAAY,EAAE,YAAoB,EAAW,EAAE,CACrD,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC;AACjE,CAAC;AAED,0EAA0E;AAC1E,MAAM,UAAU,oBAAoB,CAAC,KAAc;IACjD,KAAM,KAA+B,CAAC,IAAI,CAAC;AAC7C,CAAC;AAED,sDAAsD;AACtD,MAAM,UAAU,mBAAmB,CACjC,KAAc;IAEd,IACE,KAAK,YAAY,QAAQ;QACzB,CAAC,KAAK,CAAC,IAAI,KAAK,SAAS,CAAC,eAAe;YACvC,KAAK,CAAC,IAAI,KAAK,SAAS,CAAC,qBAAqB,CAAC,EACjD,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,OAAO,cAAc,CAAC;AACxB,CAAC;AAED,kFAAkF;AAClF,MAAM,UAAU,YAAY,CAC1B,GAAQ,EACR,IAAO,EACP,OAAgC,EAChC,MAAc;IAEd,IAAI,MAAM,IAAI,CAAC;QAAE,OAAO;IACxB,MAAM,GAAG,GAAG,GAAG,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC;IACrD,IAAI,GAAG,KAAK,CAAC,CAAC,EAAE,CAAC;QACf,IAAI,GAAG,CAAC,MAAM,GAAG,MAAM;YAAE,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1C,CAAC;SAAM,CAAC;QACN,GAAG,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC;QACzB,IAAI,GAAG,CAAC,MAAM,GAAG,MAAM;YAAE,GAAG,CAAC,GAAG,EAAE,CAAC;IACrC,CAAC;AACH,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"file-operations.d.ts","sourceRoot":"","sources":["../../src/lib/file-operations.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"file-operations.d.ts","sourceRoot":"","sources":["../../src/lib/file-operations.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EACV,sBAAsB,EAItB,mBAAmB,EACnB,QAAQ,EAER,mBAAmB,EACnB,eAAe,EACf,mBAAmB,EACnB,iBAAiB,EAGlB,MAAM,oBAAoB,CAAC;AAqB5B,OAAO,EAIL,QAAQ,EAET,MAAM,iBAAiB,CAAC;AA6IzB,wBAAsB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAgCrE;AAED,wBAAsB,aAAa,CACjC,OAAO,EAAE,MAAM,EACf,OAAO,GAAE;IACP,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,UAAU,GAAG,MAAM,CAAC;IAC/C,qBAAqB,CAAC,EAAE,OAAO,CAAC;CAC5B,GACL,OAAO,CAAC,mBAAmB,CAAC,CA6J9B;AAED,wBAAsB,WAAW,CAC/B,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,eAAe,GAAE,MAAM,EAAO,EAC9B,OAAO,GAAE;IACP,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,UAAU,GAAG,MAAM,CAAC;IAC/C,QAAQ,CAAC,EAAE,MAAM,CAAC;CACd,GACL,OAAO,CAAC,iBAAiB,CAAC,CAqF5B;AAED,OAAO,EAAE,QAAQ,EAAE,CAAC;AAEpB,wBAAsB,iBAAiB,CACrC,SAAS,EAAE,MAAM,EAAE,EACnB,OAAO,GAAE;IACP,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;CACV,GACL,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,EAAE,CAAC,CA0C/D;AAED,wBAAsB,aAAa,CACjC,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,MAAM,EACrB,OAAO,GAAE;IACP,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,SAAS,CAAC,EAAE,OAAO,CAAC;CAChB,GACL,OAAO,CAAC,mBAAmB,CAAC,CA2Q9B;AAED,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,MAAM,EACf,OAAO,GAAE;IACP,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,aAAa,CAAC,EAAE,OAAO,CAAC;CACpB,GACL,OAAO,CAAC,sBAAsB,CAAC,CAqHjC;AAED,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,MAAM,EACf,OAAO,GAAE;IACP,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACd,GACL,OAAO,CAAC,mBAAmB,CAAC,CAyK9B;AAED,wBAAsB,aAAa,CACjC,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE;IACP,OAAO,CAAC,EAAE,MAAM,CAAC;CACb,GACL,OAAO,CAAC,eAAe,CAAC,CAgD1B"}
@@ -3,21 +3,14 @@ import * as path from 'node:path';
3
3
  import * as readline from 'node:readline';
4
4
  import { createReadStream } from 'node:fs';
5
5
  import fg from 'fast-glob';
6
- import { Minimatch } from 'minimatch';
7
6
  import safeRegex from 'safe-regex2';
8
7
  import { DEFAULT_MAX_DEPTH, DEFAULT_MAX_RESULTS, DEFAULT_TOP_N, DIR_TRAVERSAL_CONCURRENCY, getMimeType, MAX_LINE_CONTENT_LENGTH, MAX_MEDIA_FILE_SIZE, MAX_SEARCHABLE_FILE_SIZE, MAX_TEXT_FILE_SIZE, PARALLEL_CONCURRENCY, REGEX_MATCH_TIMEOUT_MS, } from './constants.js';
8
+ import { classifyAccessError, createExcludeMatcher, handleDirectoryError, insertSorted, } from './directory-helpers.js';
9
9
  import { ErrorCode, McpError } from './errors.js';
10
10
  import { getFileType, isHidden, isProbablyBinary, readFile, runWorkQueue, } from './fs-helpers.js';
11
11
  import { parseImageDimensions } from './image-parsing.js';
12
12
  import { validateExistingPath, validateExistingPathDetailed, } from './path-validation.js';
13
- // Create matcher from exclude patterns
14
- function createExcludeMatcher(excludePatterns) {
15
- if (excludePatterns.length === 0) {
16
- return () => false;
17
- }
18
- const matchers = excludePatterns.map((pattern) => new Minimatch(pattern));
19
- return (name, relativePath) => matchers.some((m) => m.match(name) || m.match(relativePath));
20
- }
13
+ import { createSearchResultSorter, createSorter } from './sorting.js';
21
14
  // Process items in parallel with controlled concurrency
22
15
  async function processInParallel(items, processor, concurrency = PARALLEL_CONCURRENCY) {
23
16
  const results = [];
@@ -64,12 +57,10 @@ function countRegexMatches(line, regex, timeoutMs = REGEX_MATCH_TIMEOUT_MS) {
64
57
  }
65
58
  // Check timeout periodically
66
59
  if (count % 100 === 0 && Date.now() > deadline) {
67
- console.error(`[countRegexMatches] Regex matching timed out after ${timeoutMs}ms on line (length: ${line.length})`);
68
60
  return -1; // Signal timeout
69
61
  }
70
62
  // Safety check for runaway regex
71
63
  if (iterations > maxIterations) {
72
- console.error(`[countRegexMatches] Max iterations exceeded (${maxIterations}) on line (length: ${line.length})`);
73
64
  return -1; // Signal runaway regex
74
65
  }
75
66
  }
@@ -181,10 +172,7 @@ export async function listDirectory(dirPath, options = {}) {
181
172
  }
182
173
  catch (error) {
183
174
  skippedInaccessible++;
184
- const { code } = error;
185
- if (code !== 'ENOENT' && code !== 'EACCES' && code !== 'EPERM') {
186
- console.error(`[listDirectory] Error reading directory ${currentPath}:`, error);
187
- }
175
+ handleDirectoryError(error);
188
176
  return;
189
177
  }
190
178
  const visibleItems = includeHidden
@@ -268,22 +256,7 @@ export async function listDirectory(dirPath, options = {}) {
268
256
  enqueue(enqueueDir);
269
257
  }
270
258
  }, DIR_TRAVERSAL_CONCURRENCY);
271
- entries.sort((a, b) => {
272
- switch (sortBy) {
273
- case 'size':
274
- return (b.size ?? 0) - (a.size ?? 0);
275
- case 'modified':
276
- return (b.modified?.getTime() ?? 0) - (a.modified?.getTime() ?? 0);
277
- case 'type':
278
- if (a.type !== b.type) {
279
- return a.type === 'directory' ? -1 : 1;
280
- }
281
- return a.name.localeCompare(b.name);
282
- case 'name':
283
- default:
284
- return a.name.localeCompare(b.name);
285
- }
286
- });
259
+ entries.sort(createSorter(sortBy));
287
260
  return {
288
261
  path: validPath,
289
262
  entries,
@@ -359,19 +332,7 @@ export async function searchFiles(basePath, pattern, excludePatterns = [], optio
359
332
  }
360
333
  }
361
334
  await flushBatch();
362
- results.sort((a, b) => {
363
- switch (sortBy) {
364
- case 'size':
365
- return (b.size ?? 0) - (a.size ?? 0);
366
- case 'modified':
367
- return (b.modified?.getTime() ?? 0) - (a.modified?.getTime() ?? 0);
368
- case 'name':
369
- return path.basename(a.path).localeCompare(path.basename(b.path));
370
- case 'path':
371
- default:
372
- return a.path.localeCompare(b.path);
373
- }
374
- });
335
+ results.sort(createSearchResultSorter(sortBy));
375
336
  return {
376
337
  basePath: validPath,
377
338
  pattern,
@@ -427,11 +388,7 @@ export async function searchContent(basePath, searchPattern, options = {}) {
427
388
  const needsReDoSCheck = !isLiteral && !isSimpleSafePattern(finalPattern);
428
389
  if (needsReDoSCheck && !safeRegex(finalPattern)) {
429
390
  throw new McpError(ErrorCode.E_INVALID_PATTERN, `Potentially unsafe regular expression (ReDoS risk): ${searchPattern}. ` +
430
- 'Avoid patterns with nested quantifiers, overlapping alternations, or exponential backtracking.', basePath, {
431
- searchPattern,
432
- finalPattern,
433
- reason: 'ReDoS risk detected by safe-regex2',
434
- });
391
+ 'Avoid patterns with nested quantifiers, overlapping alternations, or exponential backtracking.', basePath, { reason: 'ReDoS risk detected' });
435
392
  }
436
393
  let regex;
437
394
  try {
@@ -568,7 +525,6 @@ export async function searchContent(basePath, searchPattern, options = {}) {
568
525
  const matchCount = countRegexMatches(line, regex);
569
526
  if (matchCount < 0) {
570
527
  linesSkippedDueToRegexTimeout++;
571
- console.error(`[searchContent] Skipping line ${lineNumber} in ${validFile} due to regex timeout`);
572
528
  if (lineBuffer) {
573
529
  lineBuffer.push(trimmedLine);
574
530
  }
@@ -646,20 +602,6 @@ export async function analyzeDirectory(dirPath, options = {}) {
646
602
  const largestFiles = [];
647
603
  const recentlyModified = [];
648
604
  const shouldExclude = createExcludeMatcher(excludePatterns);
649
- const insertSorted = (arr, item, compare, maxLen) => {
650
- if (maxLen <= 0)
651
- return;
652
- const idx = arr.findIndex((el) => compare(item, el));
653
- if (idx === -1) {
654
- if (arr.length < maxLen)
655
- arr.push(item);
656
- }
657
- else {
658
- arr.splice(idx, 0, item);
659
- if (arr.length > maxLen)
660
- arr.pop();
661
- }
662
- };
663
605
  await runWorkQueue([{ currentPath: validPath, depth: 0 }], async ({ currentPath, depth }, enqueue) => {
664
606
  if (depth > maxDepth)
665
607
  return;
@@ -670,10 +612,7 @@ export async function analyzeDirectory(dirPath, options = {}) {
670
612
  }
671
613
  catch (error) {
672
614
  skippedInaccessible++;
673
- const { code } = error;
674
- if (code !== 'ENOENT' && code !== 'EACCES' && code !== 'EPERM') {
675
- console.error(`[analyzeDirectory] Error reading directory ${currentPath}:`, error);
676
- }
615
+ handleDirectoryError(error);
677
616
  return;
678
617
  }
679
618
  for (const item of items) {
@@ -711,9 +650,7 @@ export async function analyzeDirectory(dirPath, options = {}) {
711
650
  }
712
651
  }
713
652
  catch (error) {
714
- if (error instanceof McpError &&
715
- (error.code === ErrorCode.E_ACCESS_DENIED ||
716
- error.code === ErrorCode.E_SYMLINK_NOT_ALLOWED)) {
653
+ if (classifyAccessError(error) === 'symlink') {
717
654
  symlinksNotFollowed++;
718
655
  }
719
656
  else {
@@ -770,9 +707,7 @@ export async function getDirectoryTree(dirPath, options = {}) {
770
707
  await validateExistingPathDetailed(currentPath));
771
708
  }
772
709
  catch (error) {
773
- if (error instanceof McpError &&
774
- (error.code === ErrorCode.E_ACCESS_DENIED ||
775
- error.code === ErrorCode.E_SYMLINK_NOT_ALLOWED)) {
710
+ if (classifyAccessError(error) === 'symlink') {
776
711
  symlinksNotFollowed++;
777
712
  }
778
713
  else {