@j0hanz/filesystem-mcp 1.8.0 → 1.9.1

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 (84) hide show
  1. package/README.md +635 -377
  2. package/dist/cli.js +2 -2
  3. package/dist/completions.js +2 -3
  4. package/dist/index.js +2 -2
  5. package/dist/lib/file-operations/{common.d.ts → core.d.ts} +6 -0
  6. package/dist/lib/file-operations/{common.js → core.js} +45 -0
  7. package/dist/lib/file-operations/metadata.d.ts +73 -0
  8. package/dist/lib/file-operations/metadata.js +889 -0
  9. package/dist/lib/file-operations/{search-content.d.ts → search.d.ts} +40 -7
  10. package/dist/lib/file-operations/{search-content.js → search.js} +418 -20
  11. package/dist/lib/file-operations/{glob-engine.d.ts → traversal.d.ts} +18 -1
  12. package/dist/lib/file-operations/{glob-engine.js → traversal.js} +25 -2
  13. package/dist/lib/fs-helpers.js +1 -2
  14. package/dist/lib/observability.js +1 -1
  15. package/dist/lib/{path-validation.d.ts → paths.d.ts} +11 -0
  16. package/dist/lib/{path-validation.js → paths.js} +145 -12
  17. package/dist/lib/utils.d.ts +15 -0
  18. package/dist/lib/utils.js +33 -0
  19. package/dist/resources/generated-instructions.js +6 -6
  20. package/dist/resources/tool-catalog.js +9 -9
  21. package/dist/resources/tool-info.js +3 -3
  22. package/dist/resources/workflows.js +10 -23
  23. package/dist/schemas.d.ts +11 -11
  24. package/dist/schemas.js +18 -31
  25. package/dist/server/bootstrap.d.ts +19 -1
  26. package/dist/server/bootstrap.js +130 -44
  27. package/dist/server/roots-manager.d.ts +5 -2
  28. package/dist/server/roots-manager.js +17 -5
  29. package/dist/tools/apply-patch.js +4 -3
  30. package/dist/tools/calculate-hash.js +4 -4
  31. package/dist/tools/create-directory.js +1 -1
  32. package/dist/tools/delete-file.js +3 -3
  33. package/dist/tools/diff-files.js +2 -2
  34. package/dist/tools/edit-file.js +14 -13
  35. package/dist/tools/list-directory.js +5 -7
  36. package/dist/tools/move-file.js +2 -1
  37. package/dist/tools/read-multiple.js +3 -4
  38. package/dist/tools/read.js +3 -3
  39. package/dist/tools/replace-in-files.js +8 -10
  40. package/dist/tools/roots.js +4 -6
  41. package/dist/tools/search-content.js +7 -9
  42. package/dist/tools/search-files.js +4 -6
  43. package/dist/tools/shared.d.ts +2 -1
  44. package/dist/tools/shared.js +2 -1
  45. package/dist/tools/stat-many.js +4 -3
  46. package/dist/tools/stat.js +4 -3
  47. package/dist/tools/task-support.js +1 -1
  48. package/dist/tools/tree.js +3 -4
  49. package/dist/tools/write-file.js +1 -1
  50. package/package.json +4 -4
  51. package/dist/lib/file-operations/file-info.d.ts +0 -10
  52. package/dist/lib/file-operations/file-info.js +0 -143
  53. package/dist/lib/file-operations/gitignore.d.ts +0 -6
  54. package/dist/lib/file-operations/gitignore.js +0 -45
  55. package/dist/lib/file-operations/glob-helpers.d.ts +0 -18
  56. package/dist/lib/file-operations/glob-helpers.js +0 -23
  57. package/dist/lib/file-operations/list-directory.d.ts +0 -14
  58. package/dist/lib/file-operations/list-directory.js +0 -252
  59. package/dist/lib/file-operations/read-multiple-files.d.ts +0 -25
  60. package/dist/lib/file-operations/read-multiple-files.js +0 -252
  61. package/dist/lib/file-operations/search-files.d.ts +0 -27
  62. package/dist/lib/file-operations/search-files.js +0 -216
  63. package/dist/lib/file-operations/search-matcher.d.ts +0 -10
  64. package/dist/lib/file-operations/search-matcher.js +0 -72
  65. package/dist/lib/file-operations/search-worker.d.ts +0 -2
  66. package/dist/lib/file-operations/search-worker.js +0 -131
  67. package/dist/lib/file-operations/tree.d.ts +0 -28
  68. package/dist/lib/file-operations/tree.js +0 -265
  69. package/dist/lib/option-utils.d.ts +0 -3
  70. package/dist/lib/option-utils.js +0 -15
  71. package/dist/lib/path-format.d.ts +0 -1
  72. package/dist/lib/path-format.js +0 -7
  73. package/dist/lib/path-policy.d.ts +0 -2
  74. package/dist/lib/path-policy.js +0 -100
  75. package/dist/lib/progress-reporting.d.ts +0 -11
  76. package/dist/lib/progress-reporting.js +0 -13
  77. package/dist/lib/type-guards.d.ts +0 -1
  78. package/dist/lib/type-guards.js +0 -3
  79. package/dist/server/capabilities.d.ts +0 -10
  80. package/dist/server/capabilities.js +0 -48
  81. package/dist/server/logging.d.ts +0 -7
  82. package/dist/server/logging.js +0 -41
  83. package/dist/server/types.d.ts +0 -4
  84. package/dist/server/types.js +0 -1
package/README.md CHANGED
@@ -1,31 +1,30 @@
1
- # Filesystem MCP
1
+ # Filesystem MCP Server
2
2
 
3
- ![npm version](https://img.shields.io/npm/v/@j0hanz/filesystem-mcp) ![License](https://img.shields.io/npm/l/@j0hanz/filesystem-mcp) ![Node.js Version](https://img.shields.io/node/v/@j0hanz/filesystem-mcp) ![Docker Image](https://ghcr-badge.egpl.dev/j0hanz/filesystem-mcp/latest_tag?trim=major&label=docker)
3
+ [![npm version](https://img.shields.io/npm/v/%40j0hanz%2Ffilesystem-mcp?style=flat-square&logo=npm)](https://www.npmjs.com/package/%40j0hanz%2Ffilesystem-mcp) [![License: MIT](https://img.shields.io/badge/license-MIT-blue?style=flat-square)](#contributing-and-license)
4
4
 
5
- [![Install in VS Code](https://img.shields.io/badge/VS_Code-Install_Server-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)](https://insiders.vscode.dev/redirect/mcp/install?name=filesystem-mcp&config=%7B%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40j0hanz%2Ffilesystem-mcp%40latest%22%5D%7D) [![Install in VS Code Insiders](https://img.shields.io/badge/VS_Code_Insiders-Install_Server-24bfa5?style=flat-square&logo=visualstudiocode&logoColor=white)](https://insiders.vscode.dev/redirect/mcp/install?name=filesystem-mcp&config=%7B%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40j0hanz%2Ffilesystem-mcp%40latest%22%5D%7D&quality=insiders)
5
+ [![Install in VS Code](https://img.shields.io/badge/VS_Code-Install_Server-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)](https://insiders.vscode.dev/redirect/mcp/install?name=filesystem-mcp&config=%7B%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40j0hanz%2Ffilesystem-mcp%40latest%22%5D%7D) [![Install in VS Code Insiders](https://img.shields.io/badge/VS_Code_Insiders-Install_Server-24bfa5?style=flat-square&logo=visualstudiocode&logoColor=white)](https://insiders.vscode.dev/redirect/mcp/install?name=filesystem-mcp&config=%7B%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40j0hanz%2Ffilesystem-mcp%40latest%22%5D%7D&quality=insiders) [![Install in Visual Studio](https://img.shields.io/badge/Visual_Studio-Install_Server-C16FDE?logo=visualstudio&logoColor=white)](https://vs-open.link/mcp-install?%7B%22filesystem-mcp%22%3A%7B%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40j0hanz%2Ffilesystem-mcp%40latest%22%5D%7D%7D)
6
6
 
7
- [![Install in Cursor](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/deeplink/mcp-install?name=filesystem-mcp&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkBqMGhhbnovZmlsZXN5c3RlbS1tY3BAbGF0ZXN0Il19)
7
+ [![Add to LM Studio](https://files.lmstudio.ai/deeplink/mcp-install-light.svg)](https://lmstudio.ai/install-mcp?name=filesystem-mcp&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkBqMGhhbnovZmlsZXN5c3RlbS1tY3BAbGF0ZXN0Il19) [![Install in Cursor](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en/install-mcp?name=filesystem-mcp&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkBqMGhhbnovZmlsZXN5c3RlbS1tY3BAbGF0ZXN0Il19) [![Install in Goose](https://block.github.io/goose/img/extension-install-dark.svg)](https://block.github.io/goose/extension?cmd=npx&arg=-y&arg=%40j0hanz%2Ffilesystem-mcp%40latest&id=%40j0hanz%2Ffilesystem-mcp&name=filesystem-mcp&description=MCP%20Server%20that%20enables%20LLMs%20to%20interact%20with%20the%20local%20filesystem.)
8
8
 
9
- MCP Server that enables LLMs to interact with the local filesystem. Provides tools for navigation, search, file management, and analysis — all scoped to allowed directories.
9
+ MCP Server that enables LLMs to interact with the local filesystem. Provides 18 tools for navigation, search, file management, and analysis — all scoped to allowed directories.
10
10
 
11
11
  ## Overview
12
12
 
13
- Filesystem MCP exposes a rich set of tools for reading, writing, searching, and inspecting files and directories. All operations are strictly bounded to the directories you provide at startup, preventing access to any path outside those roots.
13
+ A secure, production-ready [Model Context Protocol](https://modelcontextprotocol.io) server that gives AI assistants controlled access to the local filesystem. All operations are sandboxed to explicitly allowed directories with path traversal prevention, sensitive file blocking, and optional Bearer token authentication.
14
+
15
+ Supports **stdio** (default) and **Streamable HTTP + SSE** transports with per-session isolation.
14
16
 
15
17
  ## Key Features
16
18
 
17
- - **Navigation**: List directory contents (`ls`), render trees (`tree`), and query workspace roots (`roots`).
18
- - **File I/O**: Read single or multiple files (`read`, `read_many`); write, edit, move, and delete (`write`, `edit`, `mv`, `rm`).
19
- - **Search**: Find files by glob pattern (`find`) or search content with full regex support (`grep`).
20
- - **Analysis**: Metadata and token estimates (`stat`, `stat_many`), SHA-256 hashing (`calculate_hash`), and unified diffs (`diff_files`).
21
- - **Patch & Replace**: Apply unified patches (`apply_patch`) and bulk search-and-replace across files (`search_and_replace`).
22
- - **Tasks**: Long-running tools support background task execution with progress notifications and cancellation.
23
- - **Large Output Handling**: Oversized results are externalized to ephemeral resource URIs instead of truncating inline.
24
- - **Security**: Strict path validation, safe regex via RE2, `.gitignore`-aware operations, and atomic writes.
19
+ - **18 filesystem tools** read, write, search, diff, patch, hash, and bulk operations with structured output schemas
20
+ - **Security-first** path validation, symlink escape prevention, sensitive file denylist, localhost-only CORS, optional API key auth
21
+ - **Dual transport** stdio for local use, Streamable HTTP with SSE for networked/multi-session deployments
22
+ - **Structured output** all tools return typed `outputSchema` / `structuredContent` for reliable LLM parsing
23
+ - **Self-documenting** 6 built-in resources (`internal://instructions`, `internal://tool-catalog`, etc.) and a `get-help` prompt
25
24
 
26
25
  ## Requirements
27
26
 
28
- - **Node.js** `>= 24`
27
+ - Node.js >= 24
29
28
 
30
29
  ## Quick Start
31
30
 
@@ -34,16 +33,48 @@ Filesystem MCP exposes a rich set of tools for reading, writing, searching, and
34
33
  "mcpServers": {
35
34
  "filesystem-mcp": {
36
35
  "command": "npx",
37
- "args": ["-y", "@j0hanz/filesystem-mcp@latest", "/path/to/allowed/dir"]
36
+ "args": ["-y", "@j0hanz/filesystem-mcp@latest"]
38
37
  }
39
38
  }
40
39
  }
41
40
  ```
42
41
 
43
- Run directly:
42
+ ### Docker
44
43
 
45
44
  ```bash
46
- npx -y @j0hanz/filesystem-mcp@latest /path/to/allowed/dir
45
+ docker run -i --rm -v /path/to/project:/workspace:ro ghcr.io/j0hanz/filesystem-mcp /workspace
46
+ ```
47
+
48
+ Or using Docker Compose:
49
+
50
+ ```yaml
51
+ services:
52
+ filesystem-mcp:
53
+ build: .
54
+ stdin_open: true
55
+ volumes:
56
+ - ./:/projects/workspace:ro
57
+ command: ['/projects/workspace']
58
+ ```
59
+
60
+ ### CLI Usage
61
+
62
+ ```
63
+ filesystem-mcp [options] [allowedDirs...]
64
+
65
+ Arguments:
66
+ allowedDirs Directories the server can access
67
+
68
+ Options:
69
+ --allow-cwd Allow the current working directory as an additional root
70
+ --port <number> Enable HTTP transport on the given port
71
+ -v, --version Display server version
72
+ -h, --help Display help
73
+
74
+ Examples:
75
+ $ npx @j0hanz/filesystem-mcp@latest /path/to/project
76
+ $ npx @j0hanz/filesystem-mcp@latest --allow-cwd
77
+ $ npx @j0hanz/filesystem-mcp@latest --port 3000 /path/to/project
47
78
  ```
48
79
 
49
80
  ## Client Configuration
@@ -53,23 +84,23 @@ npx -y @j0hanz/filesystem-mcp@latest /path/to/allowed/dir
53
84
 
54
85
  [![Install in VS Code](https://img.shields.io/badge/VS_Code-Install_Server-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)](https://insiders.vscode.dev/redirect/mcp/install?name=filesystem-mcp&config=%7B%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40j0hanz%2Ffilesystem-mcp%40latest%22%5D%7D)
55
86
 
56
- Or add manually to `.vscode/mcp.json`:
87
+ Add to `.vscode/mcp.json`:
57
88
 
58
89
  ```json
59
90
  {
60
91
  "servers": {
61
92
  "filesystem-mcp": {
62
93
  "command": "npx",
63
- "args": ["-y", "@j0hanz/filesystem-mcp@latest", "${workspaceFolder}"]
94
+ "args": ["-y", "@j0hanz/filesystem-mcp@latest"]
64
95
  }
65
96
  }
66
97
  }
67
98
  ```
68
99
 
69
- CLI:
100
+ Or install via CLI:
70
101
 
71
- ```bash
72
- code --add-mcp '{"name":"filesystem-mcp","command":"npx","args":["-y","@j0hanz/filesystem-mcp@latest","${workspaceFolder}"]}'
102
+ ```sh
103
+ code --add-mcp '{"name":"filesystem-mcp","command":"npx","args":["-y","@j0hanz/filesystem-mcp@latest"]}'
73
104
  ```
74
105
 
75
106
  </details>
@@ -79,10 +110,23 @@ code --add-mcp '{"name":"filesystem-mcp","command":"npx","args":["-y","@j0hanz/f
79
110
 
80
111
  [![Install in VS Code Insiders](https://img.shields.io/badge/VS_Code_Insiders-Install_Server-24bfa5?style=flat-square&logo=visualstudiocode&logoColor=white)](https://insiders.vscode.dev/redirect/mcp/install?name=filesystem-mcp&config=%7B%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40j0hanz%2Ffilesystem-mcp%40latest%22%5D%7D&quality=insiders)
81
112
 
82
- CLI:
113
+ Add to `.vscode/mcp.json`:
83
114
 
84
- ```bash
85
- code-insiders --add-mcp '{"name":"filesystem-mcp","command":"npx","args":["-y","@j0hanz/filesystem-mcp@latest","${workspaceFolder}"]}'
115
+ ```json
116
+ {
117
+ "servers": {
118
+ "filesystem-mcp": {
119
+ "command": "npx",
120
+ "args": ["-y", "@j0hanz/filesystem-mcp@latest"]
121
+ }
122
+ }
123
+ }
124
+ ```
125
+
126
+ Or install via CLI:
127
+
128
+ ```sh
129
+ code-insiders --add-mcp '{"name":"filesystem-mcp","command":"npx","args":["-y","@j0hanz/filesystem-mcp@latest"]}'
86
130
  ```
87
131
 
88
132
  </details>
@@ -90,16 +134,70 @@ code-insiders --add-mcp '{"name":"filesystem-mcp","command":"npx","args":["-y","
90
134
  <details>
91
135
  <summary><b>Install in Cursor</b></summary>
92
136
 
93
- [![Install in Cursor](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/deeplink/mcp-install?name=filesystem-mcp&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkBqMGhhbnovZmlsZXN5c3RlbS1tY3BAbGF0ZXN0Il19)
137
+ [![Install in Cursor](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en/install-mcp?name=filesystem-mcp&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkBqMGhhbnovZmlsZXN5c3RlbS1tY3BAbGF0ZXN0Il19)
138
+
139
+ Add to `~/.cursor/mcp.json`:
140
+
141
+ ```json
142
+ {
143
+ "mcpServers": {
144
+ "filesystem-mcp": {
145
+ "command": "npx",
146
+ "args": ["-y", "@j0hanz/filesystem-mcp@latest"]
147
+ }
148
+ }
149
+ }
150
+ ```
151
+
152
+ </details>
153
+
154
+ <details>
155
+ <summary><b>Install in Visual Studio</b></summary>
156
+
157
+ [![Install in Visual Studio](https://img.shields.io/badge/Visual_Studio-Install_Server-C16FDE?logo=visualstudio&logoColor=white)](https://vs-open.link/mcp-install?%7B%22filesystem-mcp%22%3A%7B%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40j0hanz%2Ffilesystem-mcp%40latest%22%5D%7D%7D)
158
+
159
+ ```json
160
+ {
161
+ "mcpServers": {
162
+ "filesystem-mcp": {
163
+ "command": "npx",
164
+ "args": ["-y", "@j0hanz/filesystem-mcp@latest"]
165
+ }
166
+ }
167
+ }
168
+ ```
169
+
170
+ </details>
171
+
172
+ <details>
173
+ <summary><b>Install in Goose</b></summary>
174
+
175
+ [![Install in Goose](https://block.github.io/goose/img/extension-install-dark.svg)](https://block.github.io/goose/extension?cmd=npx&arg=-y&arg=%40j0hanz%2Ffilesystem-mcp%40latest&id=%40j0hanz%2Ffilesystem-mcp&name=filesystem-mcp&description=MCP%20Server%20that%20enables%20LLMs%20to%20interact%20with%20the%20local%20filesystem.)
176
+
177
+ ```json
178
+ {
179
+ "mcpServers": {
180
+ "filesystem-mcp": {
181
+ "command": "npx",
182
+ "args": ["-y", "@j0hanz/filesystem-mcp@latest"]
183
+ }
184
+ }
185
+ }
186
+ ```
187
+
188
+ </details>
189
+
190
+ <details>
191
+ <summary><b>Add to LM Studio</b></summary>
94
192
 
95
- Or add to `~/.cursor/mcp.json`:
193
+ [![Add to LM Studio](https://files.lmstudio.ai/deeplink/mcp-install-light.svg)](https://lmstudio.ai/install-mcp?name=filesystem-mcp&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkBqMGhhbnovZmlsZXN5c3RlbS1tY3BAbGF0ZXN0Il19)
96
194
 
97
195
  ```json
98
196
  {
99
197
  "mcpServers": {
100
198
  "filesystem-mcp": {
101
199
  "command": "npx",
102
- "args": ["-y", "@j0hanz/filesystem-mcp@latest", "/path/to/dir"]
200
+ "args": ["-y", "@j0hanz/filesystem-mcp@latest"]
103
201
  }
104
202
  }
105
203
  }
@@ -117,7 +215,7 @@ Add to `claude_desktop_config.json`:
117
215
  "mcpServers": {
118
216
  "filesystem-mcp": {
119
217
  "command": "npx",
120
- "args": ["-y", "@j0hanz/filesystem-mcp@latest", "/path/to/dir"]
218
+ "args": ["-y", "@j0hanz/filesystem-mcp@latest"]
121
219
  }
122
220
  }
123
221
  }
@@ -128,8 +226,21 @@ Add to `claude_desktop_config.json`:
128
226
  <details>
129
227
  <summary><b>Install in Claude Code</b></summary>
130
228
 
131
- ```bash
132
- claude mcp add filesystem-mcp -- npx -y @j0hanz/filesystem-mcp@latest /path/to/dir
229
+ ```sh
230
+ claude mcp add filesystem-mcp -- npx -y @j0hanz/filesystem-mcp@latest
231
+ ```
232
+
233
+ Or add to config:
234
+
235
+ ```json
236
+ {
237
+ "mcpServers": {
238
+ "filesystem-mcp": {
239
+ "command": "npx",
240
+ "args": ["-y", "@j0hanz/filesystem-mcp@latest"]
241
+ }
242
+ }
243
+ }
133
244
  ```
134
245
 
135
246
  </details>
@@ -137,12 +248,14 @@ claude mcp add filesystem-mcp -- npx -y @j0hanz/filesystem-mcp@latest /path/to/d
137
248
  <details>
138
249
  <summary><b>Install in Windsurf</b></summary>
139
250
 
251
+ Add to `~/.codeium/windsurf/mcp_config.json`:
252
+
140
253
  ```json
141
254
  {
142
255
  "mcpServers": {
143
256
  "filesystem-mcp": {
144
257
  "command": "npx",
145
- "args": ["-y", "@j0hanz/filesystem-mcp@latest", "/path/to/dir"]
258
+ "args": ["-y", "@j0hanz/filesystem-mcp@latest"]
146
259
  }
147
260
  }
148
261
  }
@@ -151,42 +264,54 @@ claude mcp add filesystem-mcp -- npx -y @j0hanz/filesystem-mcp@latest /path/to/d
151
264
  </details>
152
265
 
153
266
  <details>
154
- <summary><b>Install in Codex</b></summary>
267
+ <summary><b>Install in Amp</b></summary>
268
+
269
+ ```sh
270
+ amp mcp add filesystem-mcp -- npx -y @j0hanz/filesystem-mcp@latest
271
+ ```
272
+
273
+ Or add to config:
155
274
 
156
- ```toml
157
- [mcp_servers.filesystem-mcp]
158
- command = "npx"
159
- args = ["-y", "@j0hanz/filesystem-mcp@latest", "${workspaceFolder}"]
275
+ ```json
276
+ {
277
+ "mcpServers": {
278
+ "filesystem-mcp": {
279
+ "command": "npx",
280
+ "args": ["-y", "@j0hanz/filesystem-mcp@latest"]
281
+ }
282
+ }
283
+ }
160
284
  ```
161
285
 
162
286
  </details>
163
287
 
164
288
  <details>
165
- <summary><b>Docker</b></summary>
289
+ <summary><b>Install in Cline</b></summary>
166
290
 
167
- ```bash
168
- docker run -i --rm \
169
- -v /path/to/your/project:/projects/workspace:ro \
170
- ghcr.io/j0hanz/filesystem-mcp:latest \
171
- /projects/workspace
291
+ Add to `cline_mcp_settings.json`:
292
+
293
+ ```json
294
+ {
295
+ "mcpServers": {
296
+ "filesystem-mcp": {
297
+ "command": "npx",
298
+ "args": ["-y", "@j0hanz/filesystem-mcp@latest"]
299
+ }
300
+ }
301
+ }
172
302
  ```
173
303
 
174
- MCP config:
304
+ </details>
305
+
306
+ <details>
307
+ <summary><b>Install in Codex CLI</b></summary>
175
308
 
176
309
  ```json
177
310
  {
178
311
  "mcpServers": {
179
312
  "filesystem-mcp": {
180
- "command": "docker",
181
- "args": [
182
- "run",
183
- "-i",
184
- "--rm",
185
- "-v",
186
- "/path/to/project:/projects/workspace:ro",
187
- "ghcr.io/j0hanz/filesystem-mcp:latest",
188
- "/projects/workspace"
189
- ]
313
+ "command": "npx",
314
+ "args": ["-y", "@j0hanz/filesystem-mcp@latest"]
190
315
  }
191
316
  }
192
317
  }
@@ -194,476 +319,609 @@ MCP config:
194
319
 
195
320
  </details>
196
321
 
197
- ## MCP Surface
322
+ <details>
323
+ <summary><b>Install in GitHub Copilot</b></summary>
198
324
 
199
- ### Tools
325
+ Add to `.vscode/mcp.json`:
200
326
 
201
- | Tool | Description |
202
- | :------------------- | :--------------------------------------------------- |
203
- | `roots` | List workspace roots the server can access |
204
- | `ls` | List directory contents (non-recursive) |
205
- | `find` | Find files by glob pattern |
206
- | `tree` | Render a bounded directory tree |
207
- | `read` | Read text content of a file |
208
- | `read_many` | Read multiple files in one request |
209
- | `stat` | Get file or directory metadata |
210
- | `stat_many` | Get metadata for multiple paths |
211
- | `grep` | Search file content by literal or RE2 regex |
212
- | `calculate_hash` | Compute SHA-256 hash of a file or directory |
213
- | `diff_files` | Generate a unified diff between two files |
214
- | `mkdir` | Create a directory (recursive) |
215
- | `write` | Write content to a file (create or overwrite) |
216
- | `edit` | Edit a file via sequential string replacements |
217
- | `mv` | Move or rename a file or directory |
218
- | `rm` | Delete a file or directory |
219
- | `apply_patch` | Apply a unified diff patch to a file |
220
- | `search_and_replace` | Search and replace text across files matching a glob |
327
+ ```json
328
+ {
329
+ "servers": {
330
+ "filesystem-mcp": {
331
+ "command": "npx",
332
+ "args": ["-y", "@j0hanz/filesystem-mcp@latest"]
333
+ }
334
+ }
335
+ }
336
+ ```
221
337
 
222
- ---
338
+ </details>
339
+
340
+ <details>
341
+ <summary><b>Install in Warp</b></summary>
342
+
343
+ ```json
344
+ {
345
+ "mcpServers": {
346
+ "filesystem-mcp": {
347
+ "command": "npx",
348
+ "args": ["-y", "@j0hanz/filesystem-mcp@latest"]
349
+ }
350
+ }
351
+ }
352
+ ```
223
353
 
224
- #### `roots` — List workspace roots
354
+ </details>
225
355
 
226
- Enumerate the directories the server is allowed to access. Call this first in any session.
356
+ <details>
357
+ <summary><b>Install in Kiro</b></summary>
227
358
 
228
- No input parameters.
359
+ Add to `.kiro/settings/mcp.json`:
229
360
 
230
- ---
361
+ ```json
362
+ {
363
+ "mcpServers": {
364
+ "filesystem-mcp": {
365
+ "command": "npx",
366
+ "args": ["-y", "@j0hanz/filesystem-mcp@latest"]
367
+ }
368
+ }
369
+ }
370
+ ```
231
371
 
232
- #### `ls` — List directory contents
372
+ </details>
233
373
 
234
- List immediate directory contents (non-recursive). Returns name, type, size, and modified date per entry.
374
+ <details>
375
+ <summary><b>Install in Gemini CLI</b></summary>
235
376
 
236
- | Parameter | Type | Required | Default | Description |
237
- | :---------------------- | :--------------------------------- | :------: | :------ | :-------------------------------------------------------- |
238
- | `path` | string | No | root | Base directory |
239
- | `includeHidden` | boolean | No | `false` | Include hidden items (`.`) |
240
- | `includeIgnored` | boolean | No | `false` | Include `node_modules`, `.git`, etc. |
241
- | `pattern` | string | No | — | Glob filter enabling recursive traversal (e.g. `**/*.ts`) |
242
- | `sortBy` | `name`\|`size`\|`modified`\|`type` | No | `name` | Sort field |
243
- | `maxDepth` | integer | No | — | Max recursion depth when `pattern` is set (1–50) |
244
- | `maxEntries` | integer | No | — | Truncation limit (1–20,000) |
245
- | `includeSymlinkTargets` | boolean | No | `false` | Resolve and include symlink targets |
377
+ Add to `~/.gemini/settings.json`:
246
378
 
247
- ---
379
+ ```json
380
+ {
381
+ "mcpServers": {
382
+ "filesystem-mcp": {
383
+ "command": "npx",
384
+ "args": ["-y", "@j0hanz/filesystem-mcp@latest"]
385
+ }
386
+ }
387
+ }
388
+ ```
248
389
 
249
- #### `find` — Find files by glob
390
+ </details>
250
391
 
251
- Locate files matching a glob pattern. Returns relative paths and metadata.
392
+ <details>
393
+ <summary><b>Install in Zed</b></summary>
252
394
 
253
- | Parameter | Type | Required | Default | Description |
254
- | :--------------- | :--------------------------------- | :------: | :------ | :-------------------------------------------------- |
255
- | `pattern` | string | Yes | — | Glob pattern (e.g. `**/*.ts`, `src/*.js`) |
256
- | `path` | string | No | root | Search root |
257
- | `maxResults` | integer | No | `100` | Max results (1–10,000) |
258
- | `maxDepth` | integer | No | — | Max directory depth to scan (0–100) |
259
- | `sortBy` | `name`\|`size`\|`modified`\|`path` | No | `path` | Sort field |
260
- | `includeHidden` | boolean | No | `false` | Include hidden files |
261
- | `includeIgnored` | boolean | No | `false` | Include ignored directories (disables `.gitignore`) |
395
+ Add to `~/.config/zed/settings.json`:
262
396
 
263
- > [!TIP]
264
- > Supports background task execution with progress reporting.
397
+ ```json
398
+ {
399
+ "context_servers": {
400
+ "filesystem-mcp": {
401
+ "settings": {
402
+ "command": "npx",
403
+ "args": ["-y", "@j0hanz/filesystem-mcp@latest"]
404
+ }
405
+ }
406
+ }
407
+ }
408
+ ```
265
409
 
266
- ---
410
+ </details>
267
411
 
268
- #### `tree` — Render directory tree
412
+ <details>
413
+ <summary><b>Install in Augment</b></summary>
269
414
 
270
- Returns both an ASCII tree (text) and a structured JSON tree.
415
+ Add to VS Code `settings.json` under `augment.advanced`:
271
416
 
272
- | Parameter | Type | Required | Default | Description |
273
- | :--------------- | :------ | :------: | :------ | :-------------------------------------------------- |
274
- | `path` | string | No | root | Base directory |
275
- | `maxDepth` | integer | No | `5` | Max depth (0–50); `0` = root node only, no children |
276
- | `maxEntries` | integer | No | `1000` | Max entries (1–20,000) |
277
- | `includeHidden` | boolean | No | `false` | Include hidden items |
278
- | `includeIgnored` | boolean | No | `false` | Include ignored items (disables `.gitignore`) |
417
+ ```json
418
+ {
419
+ "augment.advanced": {
420
+ "mcpServers": [
421
+ {
422
+ "id": "filesystem-mcp",
423
+ "command": "npx",
424
+ "args": ["-y", "@j0hanz/filesystem-mcp@latest"]
425
+ }
426
+ ]
427
+ }
428
+ }
429
+ ```
279
430
 
280
- ---
431
+ </details>
281
432
 
282
- #### `read` — Read file content
433
+ <details>
434
+ <summary><b>Install in Roo Code</b></summary>
283
435
 
284
- Read text content of a single file with optional line-range or head preview.
436
+ ```json
437
+ {
438
+ "mcpServers": {
439
+ "filesystem-mcp": {
440
+ "command": "npx",
441
+ "args": ["-y", "@j0hanz/filesystem-mcp@latest"]
442
+ }
443
+ }
444
+ }
445
+ ```
285
446
 
286
- | Parameter | Type | Required | Default | Description |
287
- | :---------- | :------ | :------: | :------ | :---------------------------------------------------------------------------- |
288
- | `path` | string | Yes | — | Absolute path to file |
289
- | `head` | integer | No | — | Read first N lines (1–100,000); mutually exclusive with `startLine`/`endLine` |
290
- | `startLine` | integer | No | — | Start line (1-based, inclusive) |
291
- | `endLine` | integer | No | — | End line (1-based, inclusive); requires `startLine` |
447
+ </details>
292
448
 
293
- Large files return a `resourceUri`; call `resources/read` on that URI for full content.
449
+ <details>
450
+ <summary><b>Install in Kilo Code</b></summary>
294
451
 
295
- ---
452
+ ```json
453
+ {
454
+ "mcpServers": {
455
+ "filesystem-mcp": {
456
+ "command": "npx",
457
+ "args": ["-y", "@j0hanz/filesystem-mcp@latest"]
458
+ }
459
+ }
460
+ }
461
+ ```
296
462
 
297
- #### `read_many` — Read multiple files
463
+ </details>
298
464
 
299
- Batch-read up to 100 files in a single request.
465
+ ## Use Cases
300
466
 
301
- | Parameter | Type | Required | Default | Description |
302
- | :---------- | :------- | :------: | :------ | :--------------------------------------- |
303
- | `paths` | string[] | Yes | — | File paths (1–100 items) |
304
- | `head` | integer | No | — | Read first N lines of each file |
305
- | `startLine` | integer | No | — | Start line per file |
306
- | `endLine` | integer | No | — | End line per file (requires `startLine`) |
467
+ ### Explore and Understand a Codebase
307
468
 
308
- Per-file `truncationReason` can be `head`, `range`, or `externalized`. Total read budget is capped internally.
469
+ Discover project structure and navigate unfamiliar repositories. Start with `roots` to see allowed directories, use `tree` for an overview, `find` to locate files by pattern, and `read` or `read_many` to inspect contents.
309
470
 
310
- ---
471
+ **Relevant tools:** `roots`, `ls`, `find`, `tree`, `read`, `read_many`, `stat`
311
472
 
312
- #### `stat` Get file/directory metadata
473
+ ### Search Across Files
313
474
 
314
- Returns name, type, size, created/modified/accessed timestamps, permissions, MIME type, and a token estimate (`size ÷ 4`).
475
+ Locate specific code patterns, function definitions, or configuration values across a project. Use `grep` for content search with regex support and `find` for file name matching.
315
476
 
316
- | Parameter | Type | Required | Default | Description |
317
- | :-------- | :----- | :------: | :------ | :------------ |
318
- | `path` | string | Yes | — | Absolute path |
477
+ **Relevant tools:** `grep`, `find`
319
478
 
320
- ---
479
+ ### Edit and Refactor Code
321
480
 
322
- #### `stat_many` Get metadata for multiple paths
481
+ Make precise, targeted edits to source files. Use `edit` for surgical replacements with dry-run preview, or `search_and_replace` for bulk changes across multiple files matching a glob pattern.
323
482
 
324
- Batch version of `stat`.
483
+ **Relevant tools:** `edit`, `search_and_replace`, `write`
325
484
 
326
- | Parameter | Type | Required | Default | Description |
327
- | :-------- | :------- | :------: | :------ | :------------------ |
328
- | `paths` | string[] | Yes | — | Paths (1–100 items) |
485
+ ### Diff and Patch Workflow
329
486
 
330
- ---
487
+ Compare file versions and apply patches. Generate a unified diff with `diff_files`, preview with `apply_patch(dryRun: true)`, then apply. Useful for code review assistance and conflict resolution.
331
488
 
332
- #### `grep` — Search file content
489
+ **Relevant tools:** `diff_files`, `apply_patch`
333
490
 
334
- Search for text within files using literal match or RE2 regex. Returns matching lines with optional context.
491
+ ### File Management
335
492
 
336
- | Parameter | Type | Required | Default | Description |
337
- | :--------------- | :------ | :------: | :------ | :------------------------------------------------------------------ |
338
- | `pattern` | string | Yes | — | Text to search (literal by default, RE2 regex when `isRegex: true`) |
339
- | `path` | string | No | root | Search root (file or directory) |
340
- | `isRegex` | boolean | No | `false` | Treat `pattern` as RE2 regex |
341
- | `caseSensitive` | boolean | No | `false` | Case-sensitive matching |
342
- | `wholeWord` | boolean | No | `false` | Match whole words only |
343
- | `contextLines` | integer | No | `0` | Lines of context before/after each match (0–50) |
344
- | `maxResults` | integer | No | `500` | Max match rows returned (0–10,000) |
345
- | `filePattern` | string | No | `**/*` | Glob to restrict candidate files (e.g. `**/*.ts`) |
346
- | `includeHidden` | boolean | No | `false` | Include hidden files |
347
- | `includeIgnored` | boolean | No | `false` | Include ignored directories |
493
+ Create directories, move/rename files, delete files, and verify file integrity via SHA-256 hashing.
348
494
 
349
- > [!NOTE]
350
- > RE2 does not support lookahead, lookbehind, or backreferences. Results exceeding 50 inline matches are externalized via `resourceUri`.
495
+ **Relevant tools:** `mkdir`, `mv`, `rm`, `calculate_hash`, `write`
351
496
 
352
- ---
497
+ ## Architecture
353
498
 
354
- #### `calculate_hash` — SHA-256 hash
499
+ ```text
500
+ [MCP Client]
501
+ |
502
+ | Transport: stdio (default) or Streamable HTTP + SSE (--port)
503
+ v
504
+ [MCP Server: filesystem-mcp]
505
+ | Entry: src/index.ts -> src/server/bootstrap.ts
506
+ |
507
+ +-- initialize / initialized
508
+ |
509
+ +-- tools/call ──────────────────────────────────────────
510
+ | +-- [roots] — List allowed workspace roots
511
+ | +-- [ls] — List directory contents
512
+ | +-- [find] — Find files by glob
513
+ | +-- [tree] — Render directory tree
514
+ | +-- [read] — Read file contents
515
+ | +-- [read_many] — Read multiple files
516
+ | +-- [stat] — Get file metadata
517
+ | +-- [stat_many] — Get multiple file metadata
518
+ | +-- [grep] — Search file contents
519
+ | +-- [mkdir] — Create directory
520
+ | +-- [write] — Write file
521
+ | +-- [edit] — Edit file (string replacements)
522
+ | +-- [mv] — Move/rename file
523
+ | +-- [rm] — Delete file
524
+ | +-- [calculate_hash] — SHA-256 hash
525
+ | +-- [diff_files] — Unified diff
526
+ | +-- [apply_patch] — Apply unified patch
527
+ | +-- [search_and_replace]— Bulk search & replace
528
+ |
529
+ +-- resources/read ──────────────────────────────────────
530
+ | +-- internal://instructions
531
+ | +-- internal://tool-catalog
532
+ | +-- internal://workflows
533
+ | +-- internal://tool-info/{name}
534
+ | +-- filesystem-mcp://result/{id}
535
+ | +-- filesystem-mcp://metrics
536
+ |
537
+ +-- prompts/get ─────────────────────────────────────────
538
+ | +-- get-help (optional topic argument)
539
+ |
540
+ +-- Capabilities: logging, resources, tools, prompts, completions, tasks
541
+ ```
355
542
 
356
- Compute a SHA-256 hash. For directories, produces a deterministic composite hash of all contained files (lexicographically sorted, `.gitignore`-aware).
543
+ ### Request Lifecycle
357
544
 
358
- | Parameter | Type | Required | Default | Description |
359
- | :-------- | :----- | :------: | :------ | :--------------------- |
360
- | `path` | string | Yes | — | File or directory path |
545
+ ```text
546
+ [Client] -- initialize {protocolVersion, capabilities} --> [Server]
547
+ [Server] -- {protocolVersion, capabilities, serverInfo} --> [Client]
548
+ [Client] -- notifications/initialized --> [Server]
549
+ [Client] -- tools/call {name, arguments} --> [Server]
550
+ [Server] -- validate(inputSchema) --> [Handler]
551
+ [Handler] -- {content: [{type, text}], structuredContent?, isError?} --> [Client]
552
+ ```
361
553
 
362
- ---
554
+ ## MCP Surface
363
555
 
364
- #### `diff_files` — Generate unified diff
556
+ ### Tools
365
557
 
366
- Create a unified diff between two files. Check `isIdentical` in the response — if `true`, the files match and no patch is needed.
558
+ #### `roots`
367
559
 
368
- | Parameter | Type | Required | Default | Description |
369
- | :----------------- | :------ | :------: | :------ | :--------------------------------- |
370
- | `original` | string | Yes | — | Original file path |
371
- | `modified` | string | Yes | — | Modified file path |
372
- | `context` | integer | No | — | Lines of context in the diff |
373
- | `ignoreWhitespace` | boolean | No | `false` | Ignore leading/trailing whitespace |
374
- | `stripTrailingCr` | boolean | No | `false` | Strip trailing carriage returns |
560
+ List allowed workspace roots. Call first all other tools are scoped to these directories.
375
561
 
376
- Large diffs are externalized to a `resourceUri`.
562
+ _No parameters._
377
563
 
378
564
  ---
379
565
 
380
- #### `mkdir` — Create directory
566
+ #### `ls`
381
567
 
382
- Create a directory and all missing parent directories (recursive).
568
+ List immediate directory contents: name, path, type, size, modified date.
383
569
 
384
- | Parameter | Type | Required | Default | Description |
385
- | :-------- | :----- | :------: | :------ | :----------------------- |
386
- | `path` | string | Yes | | Directory path to create |
570
+ | Parameter | Type | Required | Description |
571
+ | ----------------------- | ------- | -------- | ------------------------------------------------------------ |
572
+ | `path` | string | no | Base directory (default: root) |
573
+ | `includeHidden` | boolean | no | Include dotfiles. Default: `false` |
574
+ | `includeIgnored` | boolean | no | Include ignored items (node_modules, .git). Default: `false` |
575
+ | `maxDepth` | integer | no | Max recursion depth (1-100) when pattern is provided |
576
+ | `maxEntries` | integer | no | Max entries before truncation. Default: 1000, Max: 10000 |
577
+ | `sortBy` | enum | no | `name` \| `size` \| `modified` \| `type`. Default: `name` |
578
+ | `pattern` | string | no | Glob filter (e.g. `**/*.ts`) |
579
+ | `includeSymlinkTargets` | boolean | no | Resolve symlink targets. Default: `false` |
580
+ | `cursor` | string | no | Pagination cursor from a previous response |
387
581
 
388
582
  ---
389
583
 
390
- #### `write` — Write file
391
-
392
- Create or overwrite a file. Parent directories are created automatically.
584
+ #### `find`
393
585
 
394
- | Parameter | Type | Required | Default | Description |
395
- | :-------- | :----- | :------: | :------ | :--------------- |
396
- | `path` | string | Yes | — | File path |
397
- | `content` | string | Yes | — | Content to write |
586
+ Find files by glob pattern. Returns matching files with metadata.
398
587
 
399
- > [!CAUTION]
400
- > Overwrites existing file content without confirmation.
588
+ | Parameter | Type | Required | Description |
589
+ | ---------------- | ------- | -------- | --------------------------------------------------------- |
590
+ | `path` | string | no | Base directory (default: root) |
591
+ | `pattern` | string | **yes** | Glob pattern (e.g. `**/*.ts`) |
592
+ | `maxResults` | integer | no | Max results (1-100000). Default: 1000 |
593
+ | `includeIgnored` | boolean | no | Include ignored items. Default: `false` |
594
+ | `includeHidden` | boolean | no | Include dotfiles. Default: `false` |
595
+ | `sortBy` | enum | no | `path` \| `name` \| `size` \| `modified`. Default: `path` |
596
+ | `maxDepth` | integer | no | Max directory depth (0-1000) |
597
+ | `cursor` | string | no | Pagination cursor |
401
598
 
402
599
  ---
403
600
 
404
- #### `edit` — Edit file
601
+ #### `tree`
405
602
 
406
- Apply sequential literal string replacements to an existing file. Replaces the **first** occurrence of each `oldText`.
603
+ Render a directory tree with bounded recursion. Returns ASCII tree + structured JSON.
407
604
 
408
- | Parameter | Type | Required | Default | Description |
409
- | :-------- | :--------------------- | :------: | :------ | :------------------------------------- |
410
- | `path` | string | Yes | | File to edit |
411
- | `edits` | `{oldText, newText}[]` | Yes | | Ordered list of replacement operations |
412
- | `dryRun` | boolean | No | `false` | Validate edits without writing |
413
-
414
- Include 3–5 lines of surrounding context in `oldText` to uniquely target the location. Unmatched edits are reported in `unmatchedEdits`.
605
+ | Parameter | Type | Required | Description |
606
+ | ---------------- | ------- | -------- | ------------------------------------------------- |
607
+ | `path` | string | no | Base directory (default: root) |
608
+ | `maxDepth` | integer | no | Depth (0 = root node only). Default: 10, Max: 100 |
609
+ | `maxEntries` | integer | no | Max entries. Default: 5000, Max: 100000 |
610
+ | `includeHidden` | boolean | no | Include dotfiles. Default: `false` |
611
+ | `includeIgnored` | boolean | no | Include ignored items. Default: `false` |
415
612
 
416
613
  ---
417
614
 
418
- #### `mv` — Move or rename
615
+ #### `read`
419
616
 
420
- Move or rename a file or directory. Parent directories of the destination are created automatically. Falls back to copy+delete for cross-device moves.
617
+ Read text file contents. Use `head` to preview first N lines of large files.
421
618
 
422
- | Parameter | Type | Required | Default | Description |
423
- | :------------ | :----- | :------: | :------ | :--------------- |
424
- | `source` | string | Yes | | Source path |
425
- | `destination` | string | Yes | | Destination path |
619
+ | Parameter | Type | Required | Description |
620
+ | ----------- | ------- | -------- | --------------------------------------------------- |
621
+ | `path` | string | **yes** | Absolute path to file |
622
+ | `head` | integer | no | Read first N lines (1-100000) |
623
+ | `startLine` | integer | no | Start line (1-based, inclusive) |
624
+ | `endLine` | integer | no | End line (1-based, inclusive). Requires `startLine` |
426
625
 
427
626
  ---
428
627
 
429
- #### `rm` — Delete file or directory
430
-
431
- Delete a file or directory.
628
+ #### `read_many`
432
629
 
433
- | Parameter | Type | Required | Default | Description |
434
- | :------------------ | :------ | :------: | :------ | :------------------------------ |
435
- | `path` | string | Yes | — | Path to delete |
436
- | `recursive` | boolean | No | `false` | Delete non-empty directories |
437
- | `ignoreIfNotExists` | boolean | No | `false` | No error if the path is missing |
630
+ Read multiple text files in one request.
438
631
 
439
- > [!WARNING]
440
- > Non-empty directories with `recursive: false` return `E_INVALID_INPUT` with guidance to retry using `recursive: true`.
632
+ | Parameter | Type | Required | Description |
633
+ | ----------- | -------- | -------- | ------------------------------- |
634
+ | `paths` | string[] | **yes** | Files to read (1-100 paths) |
635
+ | `head` | integer | no | Read first N lines of each file |
636
+ | `startLine` | integer | no | Start line (1-based) per file |
637
+ | `endLine` | integer | no | End line (1-based) per file |
441
638
 
442
639
  ---
443
640
 
444
- #### `apply_patch` — Apply unified patch
641
+ #### `stat`
445
642
 
446
- Apply a unified diff patch to a file. Always validate with `dryRun: true` before writing.
643
+ Get file/directory metadata: size, modified, permissions, mime, tokenEstimate.
447
644
 
448
- | Parameter | Type | Required | Default | Description |
449
- | :----------------------- | :------ | :------: | :------ | :----------------------------------------------------- |
450
- | `path` | string | Yes | | Target file path |
451
- | `patch` | string | Yes | — | Unified diff patch content (must include hunk headers) |
452
- | `fuzzFactor` | integer | No | `0` | Fuzzy matching tolerance |
453
- | `autoConvertLineEndings` | boolean | No | `true` | Auto-convert line endings to match the target file |
454
- | `dryRun` | boolean | No | `false` | Validate without writing |
455
-
456
- If patch application fails, regenerate a fresh patch via `diff_files` against the current file content and retry.
645
+ | Parameter | Type | Required | Description |
646
+ | --------- | ------ | -------- | ---------------------------------- |
647
+ | `path` | string | **yes** | Absolute path to file or directory |
457
648
 
458
649
  ---
459
650
 
460
- #### `search_and_replace` — Search and replace across files
651
+ #### `stat_many`
461
652
 
462
- Replace text in all files matching a glob. Replaces **all** occurrences per file. Use `dryRun: true` to preview scope before writing.
653
+ Get metadata for multiple files/directories in one request.
463
654
 
464
- | Parameter | Type | Required | Default | Description |
465
- | :-------------- | :------ | :------: | :------ | :----------------------------------------------------------------------- |
466
- | `filePattern` | string | Yes | | Glob for target files (e.g. `**/*.ts`) |
467
- | `searchPattern` | string | Yes | — | Text to find |
468
- | `replacement` | string | Yes | — | Replacement text |
469
- | `path` | string | No | root | Search root directory |
470
- | `isRegex` | boolean | No | `false` | Treat `searchPattern` as RE2 regex; supports capture groups (`$1`, `$2`) |
471
- | `dryRun` | boolean | No | `false` | Preview matches without writing |
655
+ | Parameter | Type | Required | Description |
656
+ | --------- | -------- | -------- | ---------------------------- |
657
+ | `paths` | string[] | **yes** | File/directory paths (1-100) |
472
658
 
473
659
  ---
474
660
 
475
- ### Resources
661
+ #### `grep`
476
662
 
477
- | URI | Description | MIME Type |
478
- | :----------------------------- | :---------------------------------- | :----------------- |
479
- | `internal://instructions` | Usage guidance for models | `text/markdown` |
480
- | `internal://tool-catalog` | Tool routing and data-flow guide | `text/markdown` |
481
- | `internal://workflows` | Explore/search/edit/patch workflows | `text/markdown` |
482
- | `internal://tool-info/{name}` | Per-tool nuances and gotchas | `text/markdown` |
483
- | `filesystem-mcp://metrics` | Live per-tool metrics snapshot | `application/json` |
484
- | `filesystem-mcp://result/{id}` | Ephemeral cached large tool output | varies |
663
+ Search file contents (grep-like). Returns matching lines with optional context.
485
664
 
486
- When a tool response includes a `resource_link`/`resourceUri`, treat it as authoritative for full payload retrieval and call `resources/read` with that URI.
665
+ | Parameter | Type | Required | Description |
666
+ | ---------------- | ------- | -------- | ------------------------------------------------ |
667
+ | `path` | string | no | Base directory (default: root) |
668
+ | `pattern` | string | **yes** | Search text or RE2 regex when `isRegex=true` |
669
+ | `isRegex` | boolean | no | Treat pattern as RE2 regex. Default: `false` |
670
+ | `caseSensitive` | boolean | no | Case-sensitive matching. Default: `false` |
671
+ | `wholeWord` | boolean | no | Match whole words only. Default: `false` |
672
+ | `contextLines` | integer | no | Lines of context before/after (0-50). Default: 0 |
673
+ | `maxResults` | integer | no | Max match rows (1-100000). Default: 100 |
674
+ | `filePattern` | string | no | Glob for candidate files (e.g. `**/*.ts`) |
675
+ | `includeHidden` | boolean | no | Include dotfiles. Default: `false` |
676
+ | `includeIgnored` | boolean | no | Include ignored items. Default: `false` |
487
677
 
488
- ### Prompts
678
+ ---
489
679
 
490
- | Prompt | Description |
491
- | :--------- | :---------------------------------------- |
492
- | `get-help` | Returns usage instructions for the server |
680
+ #### `mkdir`
493
681
 
494
- ### Tasks (Background Execution)
682
+ Create a new directory (recursive). Idempotent.
495
683
 
496
- The server declares full task capabilities (`tasks/list`, `tasks/cancel`). The following tools support task-based invocation with progress notifications:
684
+ | Parameter | Type | Required | Description |
685
+ | --------- | -------- | -------- | ----------------------------------------------------------------- |
686
+ | `path` | string | no | Absolute path to directory to create |
687
+ | `paths` | string[] | no | Multiple directories to create. Either `path` or `paths` required |
497
688
 
498
- `find`, `tree`, `read`, `read_many`, `stat_many`, `grep`, `mkdir`, `write`, `mv`, `rm`, `calculate_hash`, `apply_patch`, `search_and_replace`
689
+ ---
499
690
 
500
- Include `_meta.progressToken` in a `tools/call` request to receive `notifications/progress` updates. Use `tools/call` with a `task` field to invoke as a background task, then poll `tasks/get` and retrieve output via `tasks/result`.
691
+ #### `write`
501
692
 
502
- Recommended task follow-up loop:
693
+ Write content to a file, **overwriting all existing content**. Creates parent directories if needed.
503
694
 
504
- 1. Start with `tools/call` + `task` (optional `_meta.progressToken`).
505
- 2. Poll `tasks/get` until terminal status (`completed`, `failed`, `cancelled`).
506
- 3. Fetch final payload with `tasks/result`.
695
+ | Parameter | Type | Required | Description |
696
+ | --------- | ------ | -------- | --------------------- |
697
+ | `path` | string | **yes** | Absolute path to file |
698
+ | `content` | string | **yes** | Content to write |
507
699
 
508
- Task status notifications (`notifications/tasks/status`) are best-effort and emitted only when the transport/runtime provides a notification sender.
700
+ ---
509
701
 
510
- Cancellation semantics:
702
+ #### `edit`
511
703
 
512
- - `tasks/cancel` is the canonical cancellation API.
513
- - Clients should treat `E_CANCELLED` as cancellation even if a transport/client surfaces a terminal failure shape.
704
+ Apply sequential literal string replacements (first occurrence per edit). Use `dryRun` to preview.
514
705
 
515
- ## Configuration
706
+ | Parameter | Type | Required | Description |
707
+ | ------------------ | ------- | -------- | ---------------------------------------------------------- |
708
+ | `path` | string | **yes** | Absolute path to file |
709
+ | `edits` | array | **yes** | List of `{oldText, newText}` replacements |
710
+ | `dryRun` | boolean | no | Preview edits without writing. Default: `false` |
711
+ | `ignoreWhitespace` | boolean | no | Treat whitespace sequences as equivalent. Default: `false` |
516
712
 
517
- ### CLI
713
+ ---
518
714
 
519
- ```text
520
- filesystem-mcp [options] [allowedDirs...]
521
- ```
715
+ #### `mv`
522
716
 
523
- | Option | Description |
524
- | :----------------- | :-------------------------------------------------------- |
525
- | `[allowedDirs...]` | Positional: one or more directories the server may access |
526
- | `--allow-cwd` | Allow the current working directory as an additional root |
527
- | `-v, --version` | Display server version |
528
- | `-h, --help` | Display help |
717
+ Move or rename a file or directory.
529
718
 
530
- Examples:
719
+ | Parameter | Type | Required | Description |
720
+ | ------------- | -------- | -------- | ---------------------------------------------------- |
721
+ | `source` | string | no | Single path to move (deprecated: use `sources`) |
722
+ | `sources` | string[] | no | Paths to move. Either `source` or `sources` required |
723
+ | `destination` | string | **yes** | Destination path |
531
724
 
532
- ```bash
533
- # Single directory
534
- filesystem-mcp /project/src
725
+ ---
535
726
 
536
- # Multiple directories
537
- filesystem-mcp /project/src /project/tests
727
+ #### `rm`
538
728
 
539
- # Current working directory
540
- filesystem-mcp --allow-cwd
729
+ Permanently delete a file or directory. **Irreversible.**
541
730
 
542
- # Combined
543
- filesystem-mcp /project/src --allow-cwd
544
- ```
731
+ | Parameter | Type | Required | Description |
732
+ | ------------------- | ------- | -------- | ---------------------------------------------- |
733
+ | `path` | string | **yes** | Absolute path to file or directory |
734
+ | `recursive` | boolean | no | Delete non-empty directories. Default: `false` |
735
+ | `ignoreIfNotExists` | boolean | no | No error if missing. Default: `false` |
545
736
 
546
- ### Allowed Directories
737
+ ---
547
738
 
548
- Directories are resolved from three sources, merged at runtime:
739
+ #### `calculate_hash`
549
740
 
550
- 1. **CLI arguments** positional directory paths passed at startup.
551
- 2. **MCP Roots protocol** — directories provided by the connected client after initialization (accepted only if they are within the CLI baseline when CLI directories are set).
552
- 3. **`--allow-cwd`** — the current working directory is added automatically.
741
+ Calculate SHA-256 hash of a file or directory.
553
742
 
554
- > [!TIP]
555
- > If no directories are configured at startup and the connected client does not supply MCP Roots, all tool calls will fail. Pass at least one directory argument or use `--allow-cwd`.
743
+ | Parameter | Type | Required | Description |
744
+ | --------- | ------ | -------- | ---------------------------------- |
745
+ | `path` | string | **yes** | Absolute path to file or directory |
556
746
 
557
- ### Compatibility
747
+ ---
558
748
 
559
- Set `FS_CONTEXT_STRIP_STRUCTURED=1` to strip `structuredContent` from tool results and `outputSchema` from tool definitions for compatibility with clients that only consume text content.
749
+ #### `diff_files`
560
750
 
561
- ## Security
751
+ Generate a unified diff between two files. Output feeds directly into `apply_patch`.
562
752
 
563
- - **Path validation**: All operations use `isPathWithinDirectories` to prevent path traversal attacks.
564
- - **Glob safety**: Glob patterns are validated to reject absolute paths and `..` traversal before execution.
565
- - **Safe regex**: `re2` executes regex (no catastrophic backtracking); `safe-regex2` rejects unsafe patterns before use.
566
- - **Hidden files**: Excluded from listings and searches by default; opt in with `includeHidden: true`.
567
- - **Ignored directories**: `node_modules`, `.git`, `dist`, and similar directories are excluded by default; opt in with `includeIgnored: true`.
568
- - **Windows safety**: Reserved device names (e.g. `CON`, `NUL`, `COM1`) and drive-relative paths (e.g. `C:path`) are rejected at the CLI.
569
- - **Input limits**: Paths are bounded to 4,096 characters; patterns to 1,000 characters.
570
- - **Atomic writes**: File writes use an atomic write-then-rename strategy to prevent partial writes.
571
- - **Docker**: The container runs as a non-root user (`mcp`).
572
- - **HTTP host binding**: The HTTP transport binds to `127.0.0.1` by default. Setting `FILESYSTEM_MCP_HTTP_HOST=0.0.0.0` binds to all network interfaces and exposes the server externally — only do this behind a trusted reverse proxy with `FILESYSTEM_MCP_API_KEY` configured.
753
+ | Parameter | Type | Required | Description |
754
+ | ------------------ | ------- | -------- | ---------------------------------------------------- |
755
+ | `original` | string | **yes** | Path to original file |
756
+ | `modified` | string | **yes** | Path to modified file |
757
+ | `context` | integer | no | Lines of context in diff output |
758
+ | `ignoreWhitespace` | boolean | no | Ignore leading/trailing whitespace. Default: `false` |
759
+ | `stripTrailingCr` | boolean | no | Strip trailing carriage returns. Default: `false` |
573
760
 
574
- > [!IMPORTANT]
575
- > All diagnostic output goes to `stderr`. Tool handlers must never write to `stdout`, as doing so would corrupt the stdio transport.
761
+ ---
576
762
 
577
- ## Development
763
+ #### `apply_patch`
578
764
 
579
- ### Install
765
+ Apply a unified diff patch to a file. Workflow: `diff_files` -> `apply_patch(dryRun)` -> `apply_patch`.
580
766
 
581
- ```bash
582
- npm ci
583
- ```
767
+ | Parameter | Type | Required | Description |
768
+ | ------------------------ | ------- | -------- | ------------------------------------------ |
769
+ | `path` | string | **yes** | Path to file to patch |
770
+ | `patch` | string | **yes** | Unified diff with `@@` hunk headers |
771
+ | `fuzzFactor` | integer | no | Max fuzzy mismatches per hunk (0-20) |
772
+ | `autoConvertLineEndings` | boolean | no | Auto-convert line endings. Default: `true` |
773
+ | `dryRun` | boolean | no | Validate without writing. Default: `false` |
584
774
 
585
- ### Scripts
775
+ ---
586
776
 
587
- | Script | Command | Purpose |
588
- | :----------- | :---------------------------------- | :---------------------------------- |
589
- | `dev` | `tsc --watch` | Watch-mode TypeScript compilation |
590
- | `dev:run` | `node --watch dist/index.js` | Run built server with file watching |
591
- | `build` | `node scripts/tasks.mjs build` | Production build |
592
- | `test` | `node scripts/tasks.mjs test` | Run full test suite |
593
- | `lint` | `eslint .` | Lint source files |
594
- | `lint:fix` | `eslint . --fix` | Auto-fix lint issues |
595
- | `format` | `prettier --write .` | Format all files |
596
- | `type-check` | `node scripts/tasks.mjs type-check` | TypeScript type checking |
777
+ #### `search_and_replace`
597
778
 
598
- ### MCP Inspector
779
+ Bulk search-and-replace across files matching a glob. Replaces **all** occurrences per file. Always `dryRun: true` first.
599
780
 
600
- ```bash
601
- npm run inspector
602
- ```
781
+ | Parameter | Type | Required | Description |
782
+ | ---------------- | ------- | -------- | --------------------------------------------------- |
783
+ | `path` | string | no | Base directory (default: root) |
784
+ | `filePattern` | string | **yes** | Glob pattern (e.g. `**/*.ts`) |
785
+ | `searchPattern` | string | **yes** | Text to search. RE2 regex when `isRegex=true` |
786
+ | `replacement` | string | **yes** | Replacement text. Supports `$1`, `$2` with regex |
787
+ | `isRegex` | boolean | no | Treat as RE2 regex. Default: `false` |
788
+ | `dryRun` | boolean | no | Preview matches with diff. Default: `false` |
789
+ | `includeHidden` | boolean | no | Include dotfiles. Default: `false` |
790
+ | `includeIgnored` | boolean | no | Include ignored items. Default: `false` |
791
+ | `returnDiff` | boolean | no | Return diff even when not dry-run. Default: `false` |
603
792
 
604
- Or manually:
793
+ ### Resources
605
794
 
606
- ```bash
607
- npx @modelcontextprotocol/inspector node dist/index.js /path/to/dir
608
- ```
795
+ | Resource | URI | MIME Type | Description |
796
+ | ------------ | ------------------------------ | ------------- | ------------------------------------------------------------------ |
797
+ | Instructions | `internal://instructions` | text/markdown | Comprehensive usage rules and guidelines |
798
+ | Tool Catalog | `internal://tool-catalog` | text/markdown | Tool selection guide and data flow map |
799
+ | Workflows | `internal://workflows` | text/markdown | Standard operating procedures for exploration, search, edit, patch |
800
+ | Tool Info | `internal://tool-info/{name}` | text/markdown | Per-tool contract details, nuances, gotchas |
801
+ | Result Cache | `filesystem-mcp://result/{id}` | text/markdown | Ephemeral cached tool output (large results externalized here) |
802
+ | Metrics | `filesystem-mcp://metrics` | text/markdown | Live per-tool call/error/avgDurationMs snapshot |
609
803
 
610
- ## Build & Release
804
+ ### Prompts
611
805
 
612
- Releases are triggered manually via [GitHub Actions](.github/workflows/release.yml) (`workflow_dispatch`). The pipeline:
806
+ | Prompt | Arguments | Description |
807
+ | ---------- | ------------------ | ---------------------------------------------------------------------- |
808
+ | `get-help` | `topic` (optional) | Return usage instructions. Optionally filter by section heading prefix |
613
809
 
614
- 1. Bumps `package.json` and `server.json` to the selected version (patch / minor / major or custom).
615
- 2. Runs lint, type-check, tests, and build.
616
- 3. Commits, tags (`vX.Y.Z`), and creates a GitHub Release with auto-generated notes.
617
- 4. Publishes to **npm** (`@j0hanz/filesystem-mcp`) with OIDC provenance.
618
- 5. Publishes to the **MCP Registry** (`io.github.j0hanz/filesystem-mcp`).
619
- 6. Builds and pushes the **Docker image** (`ghcr.io/j0hanz/filesystem-mcp`) for `linux/amd64` and `linux/arm64`.
810
+ ## MCP Capabilities
620
811
 
621
- The [Glama](https://glama.ai/mcp/servers/j0hanz/filesystem-mcp) listing requires a separate manual release step on the Glama dashboard.
812
+ | Capability | Status | Evidence |
813
+ | ------------- | --------- | -------------------------------------------------------------------------- |
814
+ | `logging` | confirmed | `src/server/bootstrap.ts` — registered in capabilities |
815
+ | `resources` | confirmed | `src/server/bootstrap.ts` — 6 resources registered |
816
+ | `tools` | confirmed | `src/server/bootstrap.ts` — 18 tools registered |
817
+ | `prompts` | confirmed | `src/server/bootstrap.ts` — `get-help` prompt registered |
818
+ | `completions` | confirmed | `src/completions.ts` — path + topic auto-completion |
819
+ | `tasks` | confirmed | `src/server/bootstrap.ts` — optional task support (list, cancel, requests) |
622
820
 
623
- ### Docker Build (local)
821
+ ### Tool Annotations
624
822
 
625
- ```bash
626
- docker build -t filesystem-mcp .
627
- ```
823
+ | Annotation | Tools | Value |
824
+ | ----------------------- | --------------------------------------------------------------------------------------------------------------- | -------------------------------------- |
825
+ | `readOnlyHint: true` | `roots`, `ls`, `find`, `tree`, `read`, `read_many`, `stat`, `stat_many`, `grep`, `calculate_hash`, `diff_files` | Read-only, idempotent, non-destructive |
826
+ | `destructiveHint: true` | `write`, `edit`, `rm`, `mv`, `search_and_replace`, `apply_patch` | Destructive writes, not idempotent |
827
+ | `idempotentHint: true` | `mkdir` | Idempotent write, non-destructive |
628
828
 
629
- ## HTTP Conformance Notes
829
+ ### Structured Output
630
830
 
631
- For Streamable HTTP clients, this server enforces the following behavior:
831
+ All 18 tools define `outputSchema` (Zod -> JSON Schema) and return `structuredContent` alongside text `content`. Set `FS_CONTEXT_STRIP_STRUCTURED=true` to strip output schemas from tool definitions (reduces token usage for LLMs that don't use structured output).
632
832
 
633
- - Session-bound requests must include `MCP-Protocol-Version: 2025-11-25`; missing or unsupported values return `400`.
634
- - Requests with invalid or expired `mcp-session-id` return `404`.
635
- - Initialize requests continue to be accepted without a session ID.
833
+ ## Configuration
636
834
 
637
- ## Backlog Hardening (Planned)
835
+ | Variable | Default | Description |
836
+ | ---------------------------------- | ---------------- | ------------------------------------------------------------------------------ |
837
+ | `FILESYSTEM_MCP_API_KEY` | _(none)_ | Bearer token required when binding HTTP to a non-loopback host |
838
+ | `FILESYSTEM_MCP_MAX_HTTP_SESSIONS` | `100` | Max concurrent HTTP sessions (1-10,000) |
839
+ | `FILESYSTEM_MCP_HTTP_HOST` | `127.0.0.1` | HTTP server bind address |
840
+ | `FS_CONTEXT_MAX_REQUEST_BYTES` | `4194304` (4 MB) | Max HTTP request body size (1 KB - 256 MB) |
841
+ | `FS_CONTEXT_MAX_INLINE_CHARS` | _(auto)_ | Max inline result chars before externalizing to `filesystem-mcp://result/{id}` |
842
+ | `FS_CONTEXT_MAX_INLINE_MATCHES` | `50` | Max inline search matches before truncation |
843
+ | `FS_CONTEXT_STRIP_STRUCTURED` | `false` | Strip `outputSchema` from tool definitions |
844
+ | `FS_CONTEXT_DIAGNOSTICS` | `false` | Enable diagnostic logging |
845
+ | `FS_CONTEXT_DIAGNOSTICS_DETAIL` | `false` | Enable detailed diagnostic output |
846
+ | `FS_CONTEXT_TOOL_LOG_ERRORS` | `false` | Log tool errors to stderr |
847
+ | `FS_CONTEXT_SEARCH_WORKERS_DEBUG` | `false` | Debug logging for search worker pool |
638
848
 
639
- The following hardening items are intentionally tracked as follow-up work:
849
+ ## HTTP Endpoints
640
850
 
641
- - Add a TTL-evicting task store for long-lived HTTP deployments to bound memory usage.
642
- - Add an optional per-session roots isolation mode for multi-tenant HTTP deployments.
851
+ When started with `--port <number>`, the server exposes a single MCP endpoint:
643
852
 
644
- ## Troubleshooting
853
+ | Method | Path | Purpose |
854
+ | -------- | ------ | ----------------------------------------------------- |
855
+ | `POST` | `/mcp` | Initialize session or send requests (Streamable HTTP) |
856
+ | `GET` | `/mcp` | Server-Sent Events stream for a session |
857
+ | `DELETE` | `/mcp` | Terminate a session |
645
858
 
646
- **No directories configured**
647
- If no directories are provided at startup and the client doesn't supply MCP Roots, all tool calls fail with `E_ACCESS_DENIED`. Use `roots` to inspect configured roots.
859
+ **Required headers:**
648
860
 
649
- **Path outside allowed directories**
650
- Tools return `E_ACCESS_DENIED` when a path is outside all allowed roots. Use `roots` first to see what is available.
861
+ - `mcp-protocol-version` use the negotiated MCP protocol version on post-initialize HTTP requests
862
+ - `mcp-session-id` required for `GET`/`DELETE` (returned by `POST` on initialize)
651
863
 
652
- **Empty directory or no matches**
653
- `find` and `grep` return empty results rather than errors when nothing matches. Verify the pattern and root path.
864
+ **Authentication:** Requests to non-loopback HTTP binds require `FILESYSTEM_MCP_API_KEY`; clients must then send `Authorization: Bearer <key>`. Loopback-only binds may omit auth for local use. Uses SHA-256 timing-safe comparison.
654
865
 
655
- **Pattern rejected (`E_INVALID_PATTERN`)**
656
- Glob patterns cannot be absolute or use `..` to traverse upward. RE2 patterns are validated before use.
866
+ **CORS:** Only localhost origins allowed (`127.0.0.1`, `::1`, `localhost`).
657
867
 
658
- **Non-empty directory delete fails**
659
- `rm` returns `E_INVALID_INPUT` for non-empty directories without `recursive: true`. Either set `recursive: true` or remove contents first.
868
+ ## Security
660
869
 
661
- **Patch application failed**
662
- `apply_patch` requires valid unified hunk headers (`@@ -N,M +N,M @@`). Regenerate the patch with `diff_files` against the current file content and retry.
870
+ | Control | Status | Evidence |
871
+ | ------------------------- | --------- | -------------------------------------------------------------------------------------- |
872
+ | Path sandboxing | confirmed | `src/lib/paths.ts` — all paths validated against allowed roots |
873
+ | Traversal prevention | confirmed | `src/lib/paths.ts` — resolved paths checked after normalization |
874
+ | Symlink escape prevention | confirmed | `src/__tests__/security.test.ts` — symlink boundary enforcement |
875
+ | Sensitive file denylist | confirmed | `src/lib/constants.ts` — blocks `.git`, `.env*`, SSH keys, certs, secrets |
876
+ | Origin validation | confirmed | `src/server/bootstrap.ts` — localhost-only Origin allowlist |
877
+ | Bearer auth | confirmed | `src/server/bootstrap.ts` — optional `FILESYSTEM_MCP_API_KEY` with timing-safe compare |
878
+ | Input validation | confirmed | `src/schemas.ts` — Zod strict schemas on all tool inputs |
879
+ | Request body limit | confirmed | `src/server/bootstrap.ts` — configurable max request size (413 on overflow) |
880
+ | Remote bind guard | confirmed | `src/server/bootstrap.ts` — refuses non-loopback bind without `FILESYSTEM_MCP_API_KEY` |
663
881
 
664
- **Stdout contamination**
665
- The server uses stdio transport. Never write to `stdout` in custom integrations. All diagnostic output goes to `stderr`. For Claude Desktop, check `~/Library/Logs/Claude/mcp*.log` (macOS) or the equivalent on Windows.
882
+ ## Development
883
+
884
+ | Script | Command | Purpose |
885
+ | ------------ | --------------------------------------------------------- | --------------------------------- |
886
+ | `dev` | `tsc --watch` | Watch mode TypeScript compilation |
887
+ | `dev:run` | `node --env-file=.env --watch dist/index.js` | Run server with auto-reload |
888
+ | `start` | `node dist/index.js` | Run production server |
889
+ | `build` | `node scripts/tasks.mjs build` | Clean build |
890
+ | `test` | `node scripts/tasks.mjs test` | Build + run all tests |
891
+ | `test:fast` | `node --test --import tsx/esm src/__tests__/**/*.test.ts` | Run tests without build |
892
+ | `lint` | `eslint .` | Lint source |
893
+ | `type-check` | `node scripts/tasks.mjs type-check` | Type-check src + tests |
894
+ | `format` | `prettier --write .` | Format code |
895
+ | `inspector` | `npm run build && npx @modelcontextprotocol/inspector` | Launch MCP Inspector |
896
+
897
+ ## Build and Release
898
+
899
+ - **CI:** `.github/workflows/release.yml` — runs lint, type-check, test, build before tagging/publishing.
900
+ - **Docker:** Multi-stage build with `node:24-alpine`. Builder compiles TypeScript + native modules (re2); release stage runs as non-root `mcp` user.
901
+ - **npm:** `npm run prepublishOnly` runs lint + type-check + build.
666
902
 
667
- ## License
903
+ ## Troubleshooting
668
904
 
669
- [MIT](LICENSE)
905
+ - **"No allowed directories"** — Pass at least one directory argument or use `--allow-cwd`.
906
+ - **Sensitive file blocked** — Files matching the denylist (`.env*`, `.git`, SSH keys) are blocked by design. Check `src/lib/constants.ts` for the full list.
907
+ - **Large result externalized** — When tool output exceeds inline limits, it's cached as a resource at `filesystem-mcp://result/{id}`. Read the resource URI to get the full content.
908
+ - **Stdio: logs on stdout** — Keep logs on stderr only. The server uses `console.error` for diagnostics.
909
+ - **HTTP 413** — Request body exceeds `FS_CONTEXT_MAX_REQUEST_BYTES`. Increase the limit or reduce payload size.
910
+ - **HTTP 401** — `FILESYSTEM_MCP_API_KEY` is set but the request is missing or has an incorrect `Authorization: Bearer` header.
911
+
912
+ ## Credits
913
+
914
+ | Dependency | Description |
915
+ | ------------------------------------------------------------------------------------ | --------------------------------------------- |
916
+ | [@modelcontextprotocol/sdk](https://www.npmjs.com/package/@modelcontextprotocol/sdk) | MCP TypeScript SDK |
917
+ | [commander](https://www.npmjs.com/package/commander) | CLI argument parsing |
918
+ | [diff](https://www.npmjs.com/package/diff) | Unified diff generation and patch application |
919
+ | [ignore](https://www.npmjs.com/package/ignore) | `.gitignore` pattern matching |
920
+ | [re2](https://www.npmjs.com/package/re2) | Safe RE2 regex engine (no ReDoS) |
921
+ | [safe-regex2](https://www.npmjs.com/package/safe-regex2) | Regex safety validation |
922
+ | [zod](https://www.npmjs.com/package/zod) | Schema validation and JSON Schema generation |
923
+
924
+ ## Contributing and License
925
+
926
+ - **License:** MIT
927
+ - Contributions welcome via pull requests.