@j0hanz/filesystem-context-mcp 1.0.1 β†’ 1.0.3

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 (79) hide show
  1. package/README.md +571 -532
  2. package/dist/__tests__/lib/errors.test.js +36 -1
  3. package/dist/__tests__/lib/errors.test.js.map +1 -1
  4. package/dist/__tests__/lib/file-operations.test.js +1 -1
  5. package/dist/__tests__/lib/file-operations.test.js.map +1 -1
  6. package/dist/__tests__/lib/formatters.test.d.ts +2 -0
  7. package/dist/__tests__/lib/formatters.test.d.ts.map +1 -0
  8. package/dist/__tests__/lib/formatters.test.js +251 -0
  9. package/dist/__tests__/lib/formatters.test.js.map +1 -0
  10. package/dist/__tests__/lib/image-parsing.test.d.ts +2 -0
  11. package/dist/__tests__/lib/image-parsing.test.d.ts.map +1 -0
  12. package/dist/__tests__/lib/image-parsing.test.js +265 -0
  13. package/dist/__tests__/lib/image-parsing.test.js.map +1 -0
  14. package/dist/__tests__/schemas/validators.test.d.ts +2 -0
  15. package/dist/__tests__/schemas/validators.test.d.ts.map +1 -0
  16. package/dist/__tests__/schemas/validators.test.js +142 -0
  17. package/dist/__tests__/schemas/validators.test.js.map +1 -0
  18. package/dist/config/types.d.ts +29 -3
  19. package/dist/config/types.d.ts.map +1 -1
  20. package/dist/config/types.js.map +1 -1
  21. package/dist/index.js +5 -12
  22. package/dist/index.js.map +1 -1
  23. package/dist/lib/constants.d.ts +8 -0
  24. package/dist/lib/constants.d.ts.map +1 -1
  25. package/dist/lib/constants.js +10 -0
  26. package/dist/lib/constants.js.map +1 -1
  27. package/dist/lib/errors.d.ts +2 -6
  28. package/dist/lib/errors.d.ts.map +1 -1
  29. package/dist/lib/errors.js +59 -58
  30. package/dist/lib/errors.js.map +1 -1
  31. package/dist/lib/file-operations.d.ts +0 -12
  32. package/dist/lib/file-operations.d.ts.map +1 -1
  33. package/dist/lib/file-operations.js +70 -207
  34. package/dist/lib/file-operations.js.map +1 -1
  35. package/dist/lib/fs-helpers.d.ts.map +1 -1
  36. package/dist/lib/fs-helpers.js +50 -11
  37. package/dist/lib/fs-helpers.js.map +1 -1
  38. package/dist/lib/image-parsing.d.ts +8 -0
  39. package/dist/lib/image-parsing.d.ts.map +1 -0
  40. package/dist/lib/image-parsing.js +119 -0
  41. package/dist/lib/image-parsing.js.map +1 -0
  42. package/dist/lib/path-validation.d.ts.map +1 -1
  43. package/dist/lib/path-validation.js +1 -4
  44. package/dist/lib/path-validation.js.map +1 -1
  45. package/dist/schemas/index.d.ts +1 -0
  46. package/dist/schemas/index.d.ts.map +1 -1
  47. package/dist/schemas/index.js +2 -0
  48. package/dist/schemas/index.js.map +1 -1
  49. package/dist/schemas/inputs.d.ts.map +1 -1
  50. package/dist/schemas/inputs.js +9 -4
  51. package/dist/schemas/inputs.js.map +1 -1
  52. package/dist/schemas/outputs.d.ts +12 -9
  53. package/dist/schemas/outputs.d.ts.map +1 -1
  54. package/dist/schemas/outputs.js +10 -3
  55. package/dist/schemas/outputs.js.map +1 -1
  56. package/dist/schemas/validators.d.ts +12 -0
  57. package/dist/schemas/validators.d.ts.map +1 -0
  58. package/dist/schemas/validators.js +35 -0
  59. package/dist/schemas/validators.js.map +1 -0
  60. package/dist/server.d.ts +3 -2
  61. package/dist/server.d.ts.map +1 -1
  62. package/dist/server.js +26 -15
  63. package/dist/server.js.map +1 -1
  64. package/dist/tools/analyze-directory.js +1 -1
  65. package/dist/tools/analyze-directory.js.map +1 -1
  66. package/dist/tools/directory-tree.js +1 -1
  67. package/dist/tools/directory-tree.js.map +1 -1
  68. package/dist/tools/list-directory.js +1 -1
  69. package/dist/tools/list-directory.js.map +1 -1
  70. package/dist/tools/read-file.d.ts.map +1 -1
  71. package/dist/tools/read-file.js +3 -0
  72. package/dist/tools/read-file.js.map +1 -1
  73. package/dist/tools/read-multiple-files.d.ts.map +1 -1
  74. package/dist/tools/read-multiple-files.js +3 -0
  75. package/dist/tools/read-multiple-files.js.map +1 -1
  76. package/dist/tools/search-content.d.ts.map +1 -1
  77. package/dist/tools/search-content.js +4 -3
  78. package/dist/tools/search-content.js.map +1 -1
  79. package/package.json +1 -1
package/README.md CHANGED
@@ -1,532 +1,571 @@
1
- # Filesystem Context MCP Server
2
-
3
- A secure, read-only MCP server for filesystem scanning, searching, and analysis with comprehensive security validation.
4
-
5
- [![npm version](https://img.shields.io/npm/v/@j0hanz/filesystem-context-mcp.svg)](https://www.npmjs.com/package/@j0hanz/filesystem-context-mcp)
6
- [![License](https://img.shields.io/npm/l/@j0hanz/filesystem-context-mcp)](LICENSE)
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/)
9
- [![MCP SDK](https://img.shields.io/badge/MCP%20SDK-1.12.0-purple)](https://modelcontextprotocol.io)
10
-
11
- ## ✨ Features
12
-
13
- | Feature | Description |
14
- | -------------------------- | ---------------------------------------------------------------------- |
15
- | πŸ“‚ **Directory Listing** | List and explore directory contents with recursive support |
16
- | πŸ” **File Search** | Find files using glob patterns like `**/*.ts` |
17
- | πŸ“ **Content Search** | Search text within files using regex with context lines |
18
- | πŸ“Š **Directory Analysis** | Get statistics, file types, largest files, and recently modified files |
19
- | 🌳 **Directory Tree** | JSON tree structure optimized for AI parsing |
20
- | πŸ“„ **File Reading** | Read single or multiple files with head/tail and line range support |
21
- | πŸ–ΌοΈ **Media File Support** | Read binary files (images, audio, video) as base64 |
22
- | πŸ”’ **Security First** | Path validation, symlink escape protection, and access control |
23
- | ⚑ **Parallel Operations** | Efficient batch file reading with configurable concurrency |
24
-
25
- ## 🎯 When to Use
26
-
27
- | Task | Tool |
28
- | -------------------------------- | -------------------------- |
29
- | Explore project structure | `list_directory` |
30
- | Find specific file types | `search_files` |
31
- | Search for code patterns/text | `search_content` |
32
- | Understand codebase statistics | `analyze_directory` |
33
- | Get AI-friendly project overview | `directory_tree` |
34
- | Read source code | `read_file` |
35
- | Batch read multiple files | `read_multiple_files` |
36
- | Get file metadata (size, dates) | `get_file_info` |
37
- | Read images or binary files | `read_media_file` |
38
- | Check available directories | `list_allowed_directories` |
39
-
40
- ## πŸš€ Quick Start
41
-
42
- ### NPX (Recommended)
43
-
44
- ```bash
45
- npx -y @j0hanz/filesystem-context-mcp@latest /path/to/your/project
46
- ```
47
-
48
- ### VS Code
49
-
50
- Add to your VS Code settings (`.vscode/settings.json` or User Settings):
51
-
52
- ```json
53
- {
54
- "mcp": {
55
- "servers": {
56
- "filesystem-context": {
57
- "command": "npx",
58
- "args": ["-y", "@j0hanz/filesystem-context-mcp@latest"]
59
- }
60
- }
61
- }
62
- }
63
- ```
64
-
65
- ### Claude Desktop
66
-
67
- Add to your Claude Desktop configuration (`claude_desktop_config.json`):
68
-
69
- ```json
70
- {
71
- "mcpServers": {
72
- "filesystem-context": {
73
- "command": "npx",
74
- "args": ["-y", "@j0hanz/filesystem-context-mcp@latest"]
75
- }
76
- }
77
- }
78
- ```
79
-
80
- ## πŸ“¦ Installation
81
-
82
- ### NPX (No Installation)
83
-
84
- ```bash
85
- npx -y @j0hanz/filesystem-context-mcp@latest /path/to/dir1 /path/to/dir2
86
- ```
87
-
88
- ### Global Installation
89
-
90
- ```bash
91
- npm install -g @j0hanz/filesystem-context-mcp
92
- filesystem-context-mcp /path/to/your/project
93
- ```
94
-
95
- ### From Source
96
-
97
- ```bash
98
- git clone https://github.com/j0hanz/filesystem-context-mcp-server.git
99
- cd filesystem-context-mcp-server
100
- npm install
101
- npm run build
102
- node dist/index.js /path/to/your/project
103
- ```
104
-
105
- ## βš™οΈ Configuration
106
-
107
- ### Command Line Arguments
108
-
109
- The server accepts one or more directory paths as arguments. Only these directories (and their contents) will be accessible:
110
-
111
- ```bash
112
- filesystem-context-mcp /home/user/project /home/user/docs
113
- ```
114
-
115
- ### MCP Roots Protocol
116
-
117
- If no CLI arguments are provided, the server will use the MCP Roots protocol to receive allowed directories from the client. This is useful for dynamic directory configuration.
118
-
119
- ### Environment Variables
120
-
121
- | Variable | Description |
122
- | ---------- | --------------------------------------------- |
123
- | `NODE_ENV` | Set to `production` for optimized performance |
124
-
125
- ## πŸ”§ Tools
126
-
127
- ### `list_allowed_directories`
128
-
129
- List all directories that this server is allowed to access.
130
-
131
- | Parameter | Type | Required | Default | Description |
132
- | --------- | ---- | -------- | ------- | ---------------------- |
133
- | _(none)_ | - | - | - | No parameters required |
134
-
135
- **Returns:** Array of allowed directory paths.
136
-
137
- ---
138
-
139
- ### `list_directory`
140
-
141
- List contents of a directory with optional recursive listing.
142
-
143
- | Parameter | Type | Required | Default | Description |
144
- | ----------------------- | ------- | -------- | ------- | ------------------------------------------- |
145
- | `path` | string | βœ… | - | Directory path to list |
146
- | `recursive` | boolean | ❌ | `false` | List recursively |
147
- | `includeHidden` | boolean | ❌ | `false` | Include hidden files |
148
- | `maxDepth` | number | ❌ | `10` | Maximum depth for recursive listing (0-100) |
149
- | `maxEntries` | number | ❌ | - | Maximum entries to return (1-100,000) |
150
- | `sortBy` | string | ❌ | `name` | Sort by: `name`, `size`, `modified`, `type` |
151
- | `includeSymlinkTargets` | boolean | ❌ | `false` | Include symlink target paths |
152
-
153
- **Returns:** List of entries with name, type, size, and modified date.
154
-
155
- ---
156
-
157
- ### `search_files`
158
-
159
- Search for files using glob patterns.
160
-
161
- | Parameter | Type | Required | Default | Description |
162
- | ----------------- | -------- | -------- | ------- | --------------------------------------------- |
163
- | `path` | string | βœ… | - | Base directory to search from |
164
- | `pattern` | string | βœ… | - | Glob pattern (e.g., `**/*.ts`, `src/**/*.js`) |
165
- | `excludePatterns` | string[] | ❌ | `[]` | Patterns to exclude |
166
- | `maxResults` | number | ❌ | - | Maximum matches to return (1-10,000) |
167
- | `sortBy` | string | ❌ | `path` | Sort by: `name`, `size`, `modified`, `path` |
168
- | `maxDepth` | number | ❌ | - | Maximum directory depth to search (1-100) |
169
-
170
- **Returns:** List of matching files with path, type, size, and modified date.
171
-
172
- **Example:**
173
-
174
- ```json
175
- {
176
- "path": "/project",
177
- "pattern": "**/*.ts",
178
- "excludePatterns": ["node_modules/**", "dist/**"]
179
- }
180
- ```
181
-
182
- ---
183
-
184
- ### `read_file`
185
-
186
- Read the contents of a text file.
187
-
188
- | Parameter | Type | Required | Default | Description |
189
- | ----------- | ------ | -------- | ------- | ------------------------------------------------ |
190
- | `path` | string | βœ… | - | File path to read |
191
- | `encoding` | string | ❌ | `utf-8` | File encoding (`utf-8`, `ascii`, `base64`, etc.) |
192
- | `maxSize` | number | ❌ | 10MB | Maximum file size in bytes |
193
- | `lineStart` | number | ❌ | - | Start line (1-indexed) for reading a range |
194
- | `lineEnd` | number | ❌ | - | End line (inclusive) for reading a range |
195
- | `head` | number | ❌ | - | Read only first N lines |
196
- | `tail` | number | ❌ | - | Read only last N lines |
197
-
198
- > **Note:** Cannot specify both `head` and `tail` simultaneously. Use `lineStart`/`lineEnd` for range reading.
199
-
200
- **Returns:** File contents as text.
201
-
202
- ---
203
-
204
- ### `read_multiple_files`
205
-
206
- Read multiple files in parallel for efficient batch operations.
207
-
208
- | Parameter | Type | Required | Default | Description |
209
- | ---------- | -------- | -------- | ------- | ------------------------------------ |
210
- | `paths` | string[] | βœ… | - | Array of file paths (max 100) |
211
- | `encoding` | string | ❌ | `utf-8` | File encoding |
212
- | `maxSize` | number | ❌ | 10MB | Maximum file size per file |
213
- | `head` | number | ❌ | - | Read only first N lines of each file |
214
- | `tail` | number | ❌ | - | Read only last N lines of each file |
215
-
216
- **Returns:** Array of results with content or error for each file.
217
-
218
- ---
219
-
220
- ### `get_file_info`
221
-
222
- Get detailed metadata about a file or directory.
223
-
224
- | Parameter | Type | Required | Default | Description |
225
- | --------- | ------ | -------- | ------- | ------------------------- |
226
- | `path` | string | βœ… | - | Path to file or directory |
227
-
228
- **Returns:** Metadata including name, type, size, created/modified/accessed timestamps, permissions, MIME type, and symlink target (if applicable).
229
-
230
- ---
231
-
232
- ### `search_content`
233
-
234
- Search for text content within files using regular expressions.
235
-
236
- | Parameter | Type | Required | Default | Description |
237
- | ----------------- | -------- | -------- | ------- | ------------------------------------------------ |
238
- | `path` | string | βœ… | - | Base directory to search in |
239
- | `pattern` | string | βœ… | - | Regex pattern to search for |
240
- | `filePattern` | string | ❌ | `**/*` | Glob pattern to filter files |
241
- | `excludePatterns` | string[] | ❌ | `[]` | Glob patterns to exclude |
242
- | `caseSensitive` | boolean | ❌ | `false` | Case-sensitive search |
243
- | `maxResults` | number | ❌ | `100` | Maximum number of results (1-10,000) |
244
- | `maxFileSize` | number | ❌ | 1MB | Maximum file size to scan |
245
- | `maxFilesScanned` | number | ❌ | - | Maximum files to scan before stopping |
246
- | `timeoutMs` | number | ❌ | - | Timeout in milliseconds (100-3,600,000) |
247
- | `skipBinary` | boolean | ❌ | `true` | Skip binary files |
248
- | `contextLines` | number | ❌ | `0` | Lines of context before/after match (0-10) |
249
- | `wholeWord` | boolean | ❌ | `false` | Match whole words only |
250
- | `isLiteral` | boolean | ❌ | `false` | Treat pattern as literal string (escape special) |
251
-
252
- **Returns:** Matching lines with file path, line number, content, and optional context.
253
-
254
- **Example:**
255
-
256
- ```json
257
- {
258
- "path": "/project/src",
259
- "pattern": "TODO|FIXME",
260
- "filePattern": "**/*.ts",
261
- "contextLines": 2
262
- }
263
- ```
264
-
265
- ---
266
-
267
- ### `analyze_directory`
268
-
269
- Analyze a directory structure and return statistics.
270
-
271
- | Parameter | Type | Required | Default | Description |
272
- | ----------------- | -------- | -------- | ------- | -------------------------------------- |
273
- | `path` | string | βœ… | - | Directory to analyze |
274
- | `maxDepth` | number | ❌ | `10` | Maximum depth to analyze (0-100) |
275
- | `topN` | number | ❌ | `10` | Number of top items to return (1-1000) |
276
- | `excludePatterns` | string[] | ❌ | `[]` | Glob patterns to exclude |
277
- | `includeHidden` | boolean | ❌ | `false` | Include hidden files and directories |
278
-
279
- **Returns:** Statistics including total files/directories, total size, file type distribution, largest files, and recently modified files.
280
-
281
- ---
282
-
283
- ### `directory_tree`
284
-
285
- Get a JSON tree structure of a directory, optimized for AI parsing.
286
-
287
- | Parameter | Type | Required | Default | Description |
288
- | ----------------- | -------- | -------- | ------- | --------------------------------------- |
289
- | `path` | string | βœ… | - | Directory path to build tree from |
290
- | `maxDepth` | number | ❌ | `5` | Maximum depth to traverse (0-50) |
291
- | `excludePatterns` | string[] | ❌ | `[]` | Glob patterns to exclude |
292
- | `includeHidden` | boolean | ❌ | `false` | Include hidden files and directories |
293
- | `includeSize` | boolean | ❌ | `false` | Include file sizes in the tree |
294
- | `maxFiles` | number | ❌ | - | Maximum total files to include (1-100k) |
295
-
296
- **Returns:** Hierarchical tree structure with file/directory nodes.
297
-
298
- ---
299
-
300
- ### `read_media_file`
301
-
302
- Read a binary/media file and return it as base64-encoded data.
303
-
304
- | Parameter | Type | Required | Default | Description |
305
- | --------- | ------ | -------- | ------- | -------------------------------------- |
306
- | `path` | string | βœ… | - | Path to the media file |
307
- | `maxSize` | number | ❌ | 50MB | Maximum file size in bytes (max 500MB) |
308
-
309
- **Supported formats:** Images (PNG, JPG, GIF, WebP, SVG, etc.), Audio (MP3, WAV, FLAC, etc.), Video (MP4, WebM, etc.), Fonts (TTF, WOFF, etc.), PDFs, and more.
310
-
311
- **Returns:** Base64-encoded data with MIME type, size, and dimensions (for images).
312
-
313
- ## πŸ”Œ Client Configuration
314
-
315
- <details>
316
- <summary><b>VS Code</b></summary>
317
-
318
- Add to `.vscode/settings.json`:
319
-
320
- ```json
321
- {
322
- "mcp": {
323
- "servers": {
324
- "filesystem-context": {
325
- "command": "npx",
326
- "args": ["-y", "@j0hanz/filesystem-context-mcp@latest"]
327
- }
328
- }
329
- }
330
- }
331
- ```
332
-
333
- </details>
334
-
335
- <details>
336
- <summary><b>Claude Desktop</b></summary>
337
-
338
- **macOS:** `~/Library/Application Support/Claude/claude_desktop_config.json`
339
- **Windows:** `%APPDATA%\Claude\claude_desktop_config.json`
340
-
341
- ```json
342
- {
343
- "mcpServers": {
344
- "filesystem-context": {
345
- "command": "npx",
346
- "args": ["-y", "@j0hanz/filesystem-context-mcp@latest"]
347
- }
348
- }
349
- }
350
- ```
351
-
352
- </details>
353
-
354
- <details>
355
- <summary><b>Cursor</b></summary>
356
-
357
- Add to Cursor's MCP configuration:
358
-
359
- ```json
360
- {
361
- "mcpServers": {
362
- "filesystem-context": {
363
- "command": "npx",
364
- "args": ["-y", "@j0hanz/filesystem-context-mcp@latest"]
365
- }
366
- }
367
- }
368
- ```
369
-
370
- </details>
371
-
372
- <details>
373
- <summary><b>Windsurf</b></summary>
374
-
375
- Add to Windsurf's MCP configuration:
376
-
377
- ```json
378
- {
379
- "mcpServers": {
380
- "filesystem-context": {
381
- "command": "npx",
382
- "args": ["-y", "@j0hanz/filesystem-context-mcp@latest"]
383
- }
384
- }
385
- }
386
- ```
387
-
388
- </details>
389
-
390
- ## πŸ”’ Security
391
-
392
- This server implements multiple layers of security:
393
-
394
- | Protection | Description |
395
- | ----------------------------- | ------------------------------------------------------------------------- |
396
- | **Access Control** | Only explicitly allowed directories are accessible |
397
- | **Path Validation** | All paths are validated before any filesystem operation |
398
- | **Symlink Protection** | Symlinks that resolve outside allowed directories are blocked |
399
- | **Path Traversal Prevention** | Attempts to escape via `../` are detected and blocked |
400
- | **Read-Only Operations** | Server only performs read operationsβ€”no writes, deletes, or modifications |
401
- | **Safe Regex** | Regular expressions are validated to prevent ReDoS attacks |
402
- | **Size Limits** | Configurable limits prevent resource exhaustion |
403
-
404
- ### Security Model
405
-
406
- ```text
407
- β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
408
- β”‚ MCP Client β”‚
409
- β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
410
- β”‚
411
- β–Ό
412
- β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
413
- β”‚ Filesystem Context MCP Server β”‚
414
- β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
415
- β”‚ β”‚ Path Validation Layer β”‚ β”‚
416
- β”‚ β”‚ β€’ Normalize paths β”‚ β”‚
417
- β”‚ β”‚ β€’ Check against allowed directories β”‚ β”‚
418
- β”‚ β”‚ β€’ Resolve and validate symlinks β”‚ β”‚
419
- β”‚ β”‚ β€’ Block traversal attempts β”‚ β”‚
420
- β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
421
- β”‚ β”‚ β”‚
422
- β”‚ β–Ό β”‚
423
- β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
424
- β”‚ β”‚ Read-Only File Operations β”‚ β”‚
425
- β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
426
- β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
427
- β”‚
428
- β–Ό
429
- β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
430
- β”‚ Allowed Directories Only β”‚
431
- β”‚ /home/user/project βœ… β”‚
432
- β”‚ /home/user/docs βœ… β”‚
433
- β”‚ /etc/passwd ❌ (blocked) β”‚
434
- β”‚ ../../../etc ❌ (blocked) β”‚
435
- β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
436
- ```
437
-
438
- ## πŸ› οΈ Development
439
-
440
- ### Prerequisites
441
-
442
- - Node.js >= 20.0.0
443
- - npm
444
-
445
- ### Scripts
446
-
447
- | Command | Description |
448
- | ----------------------- | -------------------------------- |
449
- | `npm run build` | Compile TypeScript to JavaScript |
450
- | `npm run dev` | Watch mode with tsx |
451
- | `npm run start` | Run compiled server |
452
- | `npm run test` | Run tests with Vitest |
453
- | `npm run test:watch` | Run tests in watch mode |
454
- | `npm run test:coverage` | Run tests with coverage report |
455
- | `npm run lint` | Run ESLint |
456
- | `npm run format` | Format code with Prettier |
457
- | `npm run type-check` | TypeScript type checking |
458
- | `npm run inspector` | Test with MCP Inspector |
459
-
460
- ### Project Structure
461
-
462
- ```text
463
- src/
464
- β”œβ”€β”€ index.ts # Entry point, CLI argument parsing
465
- β”œβ”€β”€ server.ts # MCP server setup, roots protocol handling
466
- β”œβ”€β”€ config/
467
- β”‚ └── types.ts # Shared TypeScript types
468
- β”œβ”€β”€ lib/
469
- β”‚ β”œβ”€β”€ constants.ts # Configuration constants and limits
470
- β”‚ β”œβ”€β”€ errors.ts # Error handling utilities
471
- β”‚ β”œβ”€β”€ file-operations.ts# Core filesystem operations
472
- β”‚ β”œβ”€β”€ formatters.ts # Output formatting utilities
473
- β”‚ β”œβ”€β”€ fs-helpers.ts # Low-level filesystem helpers
474
- β”‚ β”œβ”€β”€ path-utils.ts # Path manipulation utilities
475
- β”‚ └── path-validation.ts# Security: path validation layer
476
- β”œβ”€β”€ schemas/
477
- β”‚ β”œβ”€β”€ common.ts # Shared Zod schemas
478
- β”‚ β”œβ”€β”€ inputs.ts # Input validation schemas
479
- β”‚ β”œβ”€β”€ outputs.ts # Output validation schemas
480
- β”‚ └── index.ts # Schema exports
481
- β”œβ”€β”€ tools/
482
- β”‚ β”œβ”€β”€ analyze-directory.ts
483
- β”‚ β”œβ”€β”€ directory-tree.ts
484
- β”‚ β”œβ”€β”€ get-file-info.ts
485
- β”‚ β”œβ”€β”€ list-allowed-dirs.ts
486
- β”‚ β”œβ”€β”€ list-directory.ts
487
- β”‚ β”œβ”€β”€ read-file.ts
488
- β”‚ β”œβ”€β”€ read-media-file.ts
489
- β”‚ β”œβ”€β”€ read-multiple-files.ts
490
- β”‚ β”œβ”€β”€ search-content.ts
491
- β”‚ β”œβ”€β”€ search-files.ts
492
- β”‚ └── index.ts # Tool registration
493
- └── __tests__/ # Test files
494
- ```
495
-
496
- ### Testing with MCP Inspector
497
-
498
- ```bash
499
- npm run inspector
500
- ```
501
-
502
- This launches the MCP Inspector for interactive testing of all tools.
503
-
504
- ## ❓ Troubleshooting
505
-
506
- | Issue | Solution |
507
- | --------------------------- | ---------------------------------------------------------------------------------------- |
508
- | "Access denied" error | Ensure the path is within an allowed directory. Use `list_allowed_directories` to check. |
509
- | "Path does not exist" error | Verify the path exists. Use `list_directory` to explore available files. |
510
- | "File too large" error | Use `head` or `tail` parameters for partial reading, or increase `maxSize`. |
511
- | "Binary file" warning | Use `read_media_file` for binary files, or set `skipBinary=false` in content search. |
512
- | No directories configured | Pass directories as CLI arguments or ensure client provides roots via MCP protocol. |
513
- | Symlink blocked | Symlinks that resolve outside allowed directories are blocked for security. |
514
- | Regex timeout | Simplify the regex pattern or use `isLiteral=true` for literal string search. |
515
-
516
- ## 🀝 Contributing
517
-
518
- Contributions are welcome! Please follow these steps:
519
-
520
- 1. Fork the repository
521
- 2. Create a feature branch (`git checkout -b feature/amazing-feature`)
522
- 3. Run tests and linting (`npm run lint && npm run test`)
523
- 4. Commit your changes (`git commit -m 'Add amazing feature'`)
524
- 5. Push to the branch (`git push origin feature/amazing-feature`)
525
- 6. Open a Pull Request
526
-
527
- ### Code Style
528
-
529
- - Use TypeScript with strict mode
530
- - Follow ESLint configuration
531
- - Use Prettier for formatting
532
- - Write tests for new features
1
+ # Filesystem Context MCP Server
2
+
3
+ A secure, read-only MCP server for filesystem scanning, searching, and analysis with comprehensive security validation.
4
+
5
+ [![npm version](https://img.shields.io/npm/v/@j0hanz/filesystem-context-mcp.svg)](https://www.npmjs.com/package/@j0hanz/filesystem-context-mcp)
6
+ [![License](https://img.shields.io/npm/l/@j0hanz/filesystem-context-mcp)](LICENSE)
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/)
9
+ [![MCP SDK](https://img.shields.io/badge/MCP%20SDK-1.12.0-purple)](https://modelcontextprotocol.io)
10
+
11
+ ## One-Click Install
12
+
13
+ [![Install with NPX in VS Code](https://img.shields.io/badge/VS_Code-Install-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)](https://insiders.vscode.dev/redirect/mcp/install?name=filesystem-context&inputs=%5B%5D&config=%7B%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40j0hanz%2Ffilesystem-context-mcp%40latest%22%2C%22%24%7BworkspaceFolder%7D%22%5D%7D)[![Install with NPX in VS Code Insiders](https://img.shields.io/badge/VS_Code_Insiders-Install-24bfa5?style=flat-square&logo=visualstudiocode&logoColor=white)](https://insiders.vscode.dev/redirect/mcp/install?name=filesystem-context&inputs=%5B%5D&config=%7B%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40j0hanz%2Ffilesystem-context-mcp%40latest%22%2C%22%24%7BworkspaceFolder%7D%22%5D%7D&quality=insiders)
14
+
15
+ [![Install in Cursor](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/install-mcp?name=filesystem-context&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkBqMGhhbnovZmlsZXN5c3RlbS1jb250ZXh0LW1jcEBsYXRlc3QiLCIke3dvcmtzcGFjZUZvbGRlcn0iXX0=)
16
+
17
+ ## ✨ Features
18
+
19
+ | Feature | Description |
20
+ | -------------------------- | ---------------------------------------------------------------------- |
21
+ | πŸ“‚ **Directory Listing** | List and explore directory contents with recursive support |
22
+ | πŸ” **File Search** | Find files using glob patterns like `**/*.ts` |
23
+ | πŸ“ **Content Search** | Search text within files using regex with context lines |
24
+ | πŸ“Š **Directory Analysis** | Get statistics, file types, largest files, and recently modified files |
25
+ | 🌳 **Directory Tree** | JSON tree structure optimized for AI parsing |
26
+ | πŸ“„ **File Reading** | Read single or multiple files with head/tail and line range support |
27
+ | πŸ–ΌοΈ **Media File Support** | Read binary files (images, audio, video) as base64 |
28
+ | πŸ”’ **Security First** | Path validation, symlink escape protection, and access control |
29
+ | ⚑ **Parallel Operations** | Efficient batch file reading with configurable concurrency |
30
+
31
+ ## 🎯 When to Use
32
+
33
+ | Task | Tool |
34
+ | -------------------------------- | -------------------------- |
35
+ | Explore project structure | `list_directory` |
36
+ | Find specific file types | `search_files` |
37
+ | Search for code patterns/text | `search_content` |
38
+ | Understand codebase statistics | `analyze_directory` |
39
+ | Get AI-friendly project overview | `directory_tree` |
40
+ | Read source code | `read_file` |
41
+ | Batch read multiple files | `read_multiple_files` |
42
+ | Get file metadata (size, dates) | `get_file_info` |
43
+ | Read images or binary files | `read_media_file` |
44
+ | Check available directories | `list_allowed_directories` |
45
+
46
+ ## πŸš€ Quick Start
47
+
48
+ ### NPX (Recommended - Zero Config)
49
+
50
+ ```bash
51
+ # Works in current directory automatically!
52
+ npx -y @j0hanz/filesystem-context-mcp@latest
53
+ ```
54
+
55
+ Or specify directories explicitly:
56
+
57
+ ```bash
58
+ npx -y @j0hanz/filesystem-context-mcp@latest /path/to/your/project
59
+ ```
60
+
61
+ ### VS Code (with workspace folder)
62
+
63
+ Add to your VS Code settings (`.vscode/mcp.json`):
64
+
65
+ ```json
66
+ {
67
+ "servers": {
68
+ "filesystem-context": {
69
+ "command": "npx",
70
+ "args": [
71
+ "-y",
72
+ "@j0hanz/filesystem-context-mcp@latest",
73
+ "${workspaceFolder}"
74
+ ]
75
+ }
76
+ }
77
+ }
78
+ ```
79
+
80
+ > **Tip:** `${workspaceFolder}` automatically uses your current VS Code workspace. You can also omit it and the server will use its current working directory.
81
+
82
+ ### Claude Desktop
83
+
84
+ Add to your Claude Desktop configuration (`claude_desktop_config.json`):
85
+
86
+ ```json
87
+ {
88
+ "mcpServers": {
89
+ "filesystem-context": {
90
+ "command": "npx",
91
+ "args": ["-y", "@j0hanz/filesystem-context-mcp@latest"]
92
+ }
93
+ }
94
+ }
95
+ ```
96
+
97
+ > **Note:** Claude Desktop will use the current working directory automatically. No path arguments needed!
98
+
99
+ ## πŸ“¦ Installation
100
+
101
+ ### NPX (No Installation)
102
+
103
+ ```bash
104
+ npx -y @j0hanz/filesystem-context-mcp@latest /path/to/dir1 /path/to/dir2
105
+ ```
106
+
107
+ ### Global Installation
108
+
109
+ ```bash
110
+ npm install -g @j0hanz/filesystem-context-mcp
111
+ filesystem-context-mcp /path/to/your/project
112
+ ```
113
+
114
+ ### From Source
115
+
116
+ ```bash
117
+ git clone https://github.com/j0hanz/filesystem-context-mcp-server.git
118
+ cd filesystem-context-mcp-server
119
+ npm install
120
+ npm run build
121
+ node dist/index.js /path/to/your/project
122
+ ```
123
+
124
+ ## βš™οΈ Configuration
125
+
126
+ ### Directory Resolution (Priority Order)
127
+
128
+ The server determines which directories to access in this order:
129
+
130
+ 1. **CLI Arguments** - Explicitly passed paths take highest priority
131
+ 2. **MCP Roots Protocol** - Directories provided by the MCP client
132
+ 3. **Current Working Directory** - Automatic fallback for plug-and-play experience
133
+
134
+ This means you can run the server with zero configuration and it will work!
135
+
136
+ ### Command Line Arguments
137
+
138
+ Optionally specify one or more directory paths as arguments:
139
+
140
+ ```bash
141
+ filesystem-context-mcp /home/user/project /home/user/docs
142
+ ```
143
+
144
+ ### MCP Roots Protocol
145
+
146
+ If no CLI arguments are provided, the server will use the MCP Roots protocol to receive allowed directories from the client (if supported).
147
+
148
+ ### Zero-Config Mode
149
+
150
+ If neither CLI arguments nor MCP Roots provide directories, the server automatically uses the current working directory. This makes it truly plug-and-play!
151
+
152
+ ### Environment Variables
153
+
154
+ | Variable | Description |
155
+ | ---------- | --------------------------------------------- |
156
+ | `NODE_ENV` | Set to `production` for optimized performance |
157
+
158
+ ## πŸ”§ Tools
159
+
160
+ ### `list_allowed_directories`
161
+
162
+ List all directories that this server is allowed to access.
163
+
164
+ | Parameter | Type | Required | Default | Description |
165
+ | --------- | ---- | -------- | ------- | ---------------------- |
166
+ | _(none)_ | - | - | - | No parameters required |
167
+
168
+ **Returns:** Array of allowed directory paths.
169
+
170
+ ---
171
+
172
+ ### `list_directory`
173
+
174
+ List contents of a directory with optional recursive listing.
175
+
176
+ | Parameter | Type | Required | Default | Description |
177
+ | ----------------------- | ------- | -------- | ------- | ------------------------------------------- |
178
+ | `path` | string | βœ… | - | Directory path to list |
179
+ | `recursive` | boolean | ❌ | `false` | List recursively |
180
+ | `includeHidden` | boolean | ❌ | `false` | Include hidden files |
181
+ | `maxDepth` | number | ❌ | `10` | Maximum depth for recursive listing (0-100) |
182
+ | `maxEntries` | number | ❌ | - | Maximum entries to return (1-100,000) |
183
+ | `sortBy` | string | ❌ | `name` | Sort by: `name`, `size`, `modified`, `type` |
184
+ | `includeSymlinkTargets` | boolean | ❌ | `false` | Include symlink target paths |
185
+
186
+ **Returns:** List of entries with name, type, size, and modified date.
187
+
188
+ ---
189
+
190
+ ### `search_files`
191
+
192
+ Search for files using glob patterns.
193
+
194
+ | Parameter | Type | Required | Default | Description |
195
+ | ----------------- | -------- | -------- | ------- | --------------------------------------------- |
196
+ | `path` | string | βœ… | - | Base directory to search from |
197
+ | `pattern` | string | βœ… | - | Glob pattern (e.g., `**/*.ts`, `src/**/*.js`) |
198
+ | `excludePatterns` | string[] | ❌ | `[]` | Patterns to exclude |
199
+ | `maxResults` | number | ❌ | - | Maximum matches to return (1-10,000) |
200
+ | `sortBy` | string | ❌ | `path` | Sort by: `name`, `size`, `modified`, `path` |
201
+ | `maxDepth` | number | ❌ | - | Maximum directory depth to search (1-100) |
202
+
203
+ **Returns:** List of matching files with path, type, size, and modified date.
204
+
205
+ **Example:**
206
+
207
+ ```json
208
+ {
209
+ "path": "/project",
210
+ "pattern": "**/*.ts",
211
+ "excludePatterns": ["node_modules/**", "dist/**"]
212
+ }
213
+ ```
214
+
215
+ ---
216
+
217
+ ### `read_file`
218
+
219
+ Read the contents of a text file.
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 |
230
+
231
+ > **Note:** Cannot specify both `head` and `tail` simultaneously. Use `lineStart`/`lineEnd` for range reading.
232
+
233
+ **Returns:** File contents as text.
234
+
235
+ ---
236
+
237
+ ### `read_multiple_files`
238
+
239
+ Read multiple files in parallel for efficient batch operations.
240
+
241
+ | Parameter | Type | Required | Default | Description |
242
+ | ---------- | -------- | -------- | ------- | ------------------------------------ |
243
+ | `paths` | string[] | βœ… | - | Array of file paths (max 100) |
244
+ | `encoding` | string | ❌ | `utf-8` | File encoding |
245
+ | `maxSize` | number | ❌ | 10MB | Maximum file size per file |
246
+ | `head` | number | ❌ | - | Read only first N lines of each file |
247
+ | `tail` | number | ❌ | - | Read only last N lines of each file |
248
+
249
+ **Returns:** Array of results with content or error for each file.
250
+
251
+ ---
252
+
253
+ ### `get_file_info`
254
+
255
+ Get detailed metadata about a file or directory.
256
+
257
+ | Parameter | Type | Required | Default | Description |
258
+ | --------- | ------ | -------- | ------- | ------------------------- |
259
+ | `path` | string | βœ… | - | Path to file or directory |
260
+
261
+ **Returns:** Metadata including name, type, size, created/modified/accessed timestamps, permissions, MIME type, and symlink target (if applicable).
262
+
263
+ ---
264
+
265
+ ### `search_content`
266
+
267
+ Search for text content within files using regular expressions.
268
+
269
+ | Parameter | Type | Required | Default | Description |
270
+ | ----------------- | -------- | -------- | ------- | ------------------------------------------------ |
271
+ | `path` | string | βœ… | - | Base directory to search in |
272
+ | `pattern` | string | βœ… | - | Regex pattern to search for |
273
+ | `filePattern` | string | ❌ | `**/*` | Glob pattern to filter files |
274
+ | `excludePatterns` | string[] | ❌ | `[]` | Glob patterns to exclude |
275
+ | `caseSensitive` | boolean | ❌ | `false` | Case-sensitive search |
276
+ | `maxResults` | number | ❌ | `100` | Maximum number of results (1-10,000) |
277
+ | `maxFileSize` | number | ❌ | 1MB | Maximum file size to scan |
278
+ | `maxFilesScanned` | number | ❌ | - | Maximum files to scan before stopping |
279
+ | `timeoutMs` | number | ❌ | - | Timeout in milliseconds (100-3,600,000) |
280
+ | `skipBinary` | boolean | ❌ | `true` | Skip binary files |
281
+ | `contextLines` | number | ❌ | `0` | Lines of context before/after match (0-10) |
282
+ | `wholeWord` | boolean | ❌ | `false` | Match whole words only |
283
+ | `isLiteral` | boolean | ❌ | `false` | Treat pattern as literal string (escape special) |
284
+
285
+ **Returns:** Matching lines with file path, line number, content, and optional context.
286
+
287
+ **Example:**
288
+
289
+ ```json
290
+ {
291
+ "path": "/project/src",
292
+ "pattern": "TODO|FIXME",
293
+ "filePattern": "**/*.ts",
294
+ "contextLines": 2
295
+ }
296
+ ```
297
+
298
+ ---
299
+
300
+ ### `analyze_directory`
301
+
302
+ Analyze a directory structure and return statistics.
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 |
311
+
312
+ **Returns:** Statistics including total files/directories, total size, file type distribution, largest files, and recently modified files.
313
+
314
+ ---
315
+
316
+ ### `directory_tree`
317
+
318
+ Get a JSON tree structure of a directory, optimized for AI parsing.
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) |
328
+
329
+ **Returns:** Hierarchical tree structure with file/directory nodes.
330
+
331
+ ---
332
+
333
+ ### `read_media_file`
334
+
335
+ Read a binary/media file and return it as base64-encoded data.
336
+
337
+ | Parameter | Type | Required | Default | Description |
338
+ | --------- | ------ | -------- | ------- | -------------------------------------- |
339
+ | `path` | string | βœ… | - | Path to the media file |
340
+ | `maxSize` | number | ❌ | 50MB | Maximum file size in bytes (max 500MB) |
341
+
342
+ **Supported formats:** Images (PNG, JPG, GIF, WebP, SVG, etc.), Audio (MP3, WAV, FLAC, etc.), Video (MP4, WebM, etc.), Fonts (TTF, WOFF, etc.), PDFs, and more.
343
+
344
+ **Returns:** Base64-encoded data with MIME type, size, and dimensions (for images).
345
+
346
+ ## πŸ”Œ Client Configuration
347
+
348
+ <details>
349
+ <summary><b>VS Code</b></summary>
350
+
351
+ Add to `.vscode/mcp.json` (recommended) or `.vscode/settings.json`:
352
+
353
+ ```json
354
+ {
355
+ "servers": {
356
+ "filesystem-context": {
357
+ "command": "npx",
358
+ "args": [
359
+ "-y",
360
+ "@j0hanz/filesystem-context-mcp@latest",
361
+ "${workspaceFolder}"
362
+ ]
363
+ }
364
+ }
365
+ }
366
+ ```
367
+
368
+ > **Note:** `${workspaceFolder}` is expanded by VS Code to the current workspace path.
369
+
370
+ </details>
371
+
372
+ <details>
373
+ <summary><b>Claude Desktop</b></summary>
374
+
375
+ **macOS:** `~/Library/Application Support/Claude/claude_desktop_config.json`
376
+ **Windows:** `%APPDATA%\Claude\claude_desktop_config.json`
377
+
378
+ ```json
379
+ {
380
+ "mcpServers": {
381
+ "filesystem-context": {
382
+ "command": "npx",
383
+ "args": ["-y", "@j0hanz/filesystem-context-mcp@latest"]
384
+ }
385
+ }
386
+ }
387
+ ```
388
+
389
+ </details>
390
+
391
+ <details>
392
+ <summary><b>Cursor</b></summary>
393
+
394
+ Add to Cursor's MCP configuration:
395
+
396
+ ```json
397
+ {
398
+ "mcpServers": {
399
+ "filesystem-context": {
400
+ "command": "npx",
401
+ "args": ["-y", "@j0hanz/filesystem-context-mcp@latest"]
402
+ }
403
+ }
404
+ }
405
+ ```
406
+
407
+ </details>
408
+
409
+ <details>
410
+ <summary><b>Windsurf</b></summary>
411
+
412
+ Add to Windsurf's MCP configuration:
413
+
414
+ ```json
415
+ {
416
+ "mcpServers": {
417
+ "filesystem-context": {
418
+ "command": "npx",
419
+ "args": ["-y", "@j0hanz/filesystem-context-mcp@latest"]
420
+ }
421
+ }
422
+ }
423
+ ```
424
+
425
+ </details>
426
+
427
+ ## πŸ”’ Security
428
+
429
+ This server implements multiple layers of security:
430
+
431
+ | Protection | Description |
432
+ | ----------------------------- | ------------------------------------------------------------------------- |
433
+ | **Access Control** | Only explicitly allowed directories are accessible |
434
+ | **Path Validation** | All paths are validated before any filesystem operation |
435
+ | **Symlink Protection** | Symlinks that resolve outside allowed directories are blocked |
436
+ | **Path Traversal Prevention** | Attempts to escape via `../` are detected and blocked |
437
+ | **Read-Only Operations** | Server only performs read operationsβ€”no writes, deletes, or modifications |
438
+ | **Safe Regex** | Regular expressions are validated to prevent ReDoS attacks |
439
+ | **Size Limits** | Configurable limits prevent resource exhaustion |
440
+
441
+ ### Security Model
442
+
443
+ ```text
444
+ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
445
+ β”‚ MCP Client β”‚
446
+ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
447
+ β”‚
448
+ β–Ό
449
+ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
450
+ β”‚ Filesystem Context MCP Server β”‚
451
+ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
452
+ β”‚ β”‚ Path Validation Layer β”‚ β”‚
453
+ β”‚ β”‚ β€’ Normalize paths β”‚ β”‚
454
+ β”‚ β”‚ β€’ Check against allowed directories β”‚ β”‚
455
+ β”‚ β”‚ β€’ Resolve and validate symlinks β”‚ β”‚
456
+ β”‚ β”‚ β€’ Block traversal attempts β”‚ β”‚
457
+ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
458
+ β”‚ β”‚ β”‚
459
+ β”‚ β–Ό β”‚
460
+ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
461
+ β”‚ β”‚ Read-Only File Operations β”‚ β”‚
462
+ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
463
+ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
464
+ β”‚
465
+ β–Ό
466
+ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
467
+ β”‚ Allowed Directories Only β”‚
468
+ β”‚ /home/user/project βœ… β”‚
469
+ β”‚ /home/user/docs βœ… β”‚
470
+ β”‚ /etc/passwd ❌ (blocked) β”‚
471
+ β”‚ ../../../etc ❌ (blocked) β”‚
472
+ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
473
+ ```
474
+
475
+ ## πŸ› οΈ Development
476
+
477
+ ### Prerequisites
478
+
479
+ - Node.js >= 20.0.0
480
+ - npm
481
+
482
+ ### Scripts
483
+
484
+ | Command | Description |
485
+ | ----------------------- | -------------------------------- |
486
+ | `npm run build` | Compile TypeScript to JavaScript |
487
+ | `npm run dev` | Watch mode with tsx |
488
+ | `npm run start` | Run compiled server |
489
+ | `npm run test` | Run tests with Vitest |
490
+ | `npm run test:watch` | Run tests in watch mode |
491
+ | `npm run test:coverage` | Run tests with coverage report |
492
+ | `npm run lint` | Run ESLint |
493
+ | `npm run format` | Format code with Prettier |
494
+ | `npm run type-check` | TypeScript type checking |
495
+ | `npm run inspector` | Test with MCP Inspector |
496
+
497
+ ### Project Structure
498
+
499
+ ```text
500
+ src/
501
+ β”œβ”€β”€ index.ts # Entry point, CLI argument parsing
502
+ β”œβ”€β”€ server.ts # MCP server setup, roots protocol handling
503
+ β”œβ”€β”€ config/
504
+ β”‚ └── types.ts # Shared TypeScript types
505
+ β”œβ”€β”€ lib/
506
+ β”‚ β”œβ”€β”€ constants.ts # Configuration constants and limits
507
+ β”‚ β”œβ”€β”€ errors.ts # Error handling utilities
508
+ β”‚ β”œβ”€β”€ file-operations.ts# Core filesystem operations
509
+ β”‚ β”œβ”€β”€ formatters.ts # Output formatting utilities
510
+ β”‚ β”œβ”€β”€ fs-helpers.ts # Low-level filesystem helpers
511
+ β”‚ β”œβ”€β”€ image-parsing.ts # Image dimension parsing
512
+ β”‚ β”œβ”€β”€ path-utils.ts # Path manipulation utilities
513
+ β”‚ └── path-validation.ts# Security: path validation layer
514
+ β”œβ”€β”€ schemas/
515
+ β”‚ β”œβ”€β”€ common.ts # Shared Zod schemas
516
+ β”‚ β”œβ”€β”€ inputs.ts # Input validation schemas
517
+ β”‚ β”œβ”€β”€ outputs.ts # Output validation schemas
518
+ β”‚ β”œβ”€β”€ validators.ts # Custom validation functions
519
+ β”‚ └── index.ts # Schema exports
520
+ β”œβ”€β”€ tools/
521
+ β”‚ β”œβ”€β”€ analyze-directory.ts
522
+ β”‚ β”œβ”€β”€ directory-tree.ts
523
+ β”‚ β”œβ”€β”€ get-file-info.ts
524
+ β”‚ β”œβ”€β”€ list-allowed-dirs.ts
525
+ β”‚ β”œβ”€β”€ list-directory.ts
526
+ β”‚ β”œβ”€β”€ read-file.ts
527
+ β”‚ β”œβ”€β”€ read-media-file.ts
528
+ β”‚ β”œβ”€β”€ read-multiple-files.ts
529
+ β”‚ β”œβ”€β”€ search-content.ts
530
+ β”‚ β”œβ”€β”€ search-files.ts
531
+ β”‚ └── index.ts # Tool registration
532
+ └── __tests__/ # Test files
533
+ ```
534
+
535
+ ### Testing with MCP Inspector
536
+
537
+ ```bash
538
+ npm run inspector
539
+ ```
540
+
541
+ This launches the MCP Inspector for interactive testing of all tools.
542
+
543
+ ## ❓ Troubleshooting
544
+
545
+ | Issue | Solution |
546
+ | --------------------------- | ---------------------------------------------------------------------------------------- |
547
+ | "Access denied" error | Ensure the path is within an allowed directory. Use `list_allowed_directories` to check. |
548
+ | "Path does not exist" error | Verify the path exists. Use `list_directory` to explore available files. |
549
+ | "File too large" error | Use `head` or `tail` parameters for partial reading, or increase `maxSize`. |
550
+ | "Binary file" warning | Use `read_media_file` for binary files, or set `skipBinary=false` in content search. |
551
+ | Unexpected directory access | Server defaults to CWD if no args/roots provided. Pass explicit paths to restrict. |
552
+ | Symlink blocked | Symlinks that resolve outside allowed directories are blocked for security. |
553
+ | Regex timeout | Simplify the regex pattern or use `isLiteral=true` for literal string search. |
554
+
555
+ ## 🀝 Contributing
556
+
557
+ Contributions are welcome! Please follow these steps:
558
+
559
+ 1. Fork the repository
560
+ 2. Create a feature branch (`git checkout -b feature/amazing-feature`)
561
+ 3. Run tests and linting (`npm run lint && npm run test`)
562
+ 4. Commit your changes (`git commit -m 'Add amazing feature'`)
563
+ 5. Push to the branch (`git push origin feature/amazing-feature`)
564
+ 6. Open a Pull Request
565
+
566
+ ### Code Style
567
+
568
+ - Use TypeScript with strict mode
569
+ - Follow ESLint configuration
570
+ - Use Prettier for formatting
571
+ - Write tests for new features