@j0hanz/filesystem-mcp 1.19.1 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (301) hide show
  1. package/README.md +333 -838
  2. package/dist/cli-help.d.ts +3 -0
  3. package/dist/cli-help.d.ts.map +1 -0
  4. package/dist/cli-help.js +169 -0
  5. package/dist/cli-help.js.map +1 -0
  6. package/dist/cli.d.ts +28 -0
  7. package/dist/cli.d.ts.map +1 -0
  8. package/dist/cli.js +168 -123
  9. package/dist/cli.js.map +1 -0
  10. package/dist/core/concurrency.d.ts +70 -0
  11. package/dist/core/concurrency.d.ts.map +1 -0
  12. package/dist/core/concurrency.js +173 -0
  13. package/dist/core/concurrency.js.map +1 -0
  14. package/dist/core/config.d.ts +19 -0
  15. package/dist/core/config.d.ts.map +1 -0
  16. package/dist/core/config.js +11 -0
  17. package/dist/core/config.js.map +1 -0
  18. package/dist/core/cursor.d.ts +23 -0
  19. package/dist/core/cursor.d.ts.map +1 -0
  20. package/dist/core/cursor.js +62 -0
  21. package/dist/core/cursor.js.map +1 -0
  22. package/dist/core/errors.d.ts +96 -0
  23. package/dist/core/errors.d.ts.map +1 -0
  24. package/dist/core/errors.js +356 -0
  25. package/dist/core/errors.js.map +1 -0
  26. package/dist/core/file-uri.d.ts +24 -0
  27. package/dist/core/file-uri.d.ts.map +1 -0
  28. package/dist/core/file-uri.js +52 -0
  29. package/dist/core/file-uri.js.map +1 -0
  30. package/dist/core/fmt.d.ts +38 -0
  31. package/dist/core/fmt.d.ts.map +1 -0
  32. package/dist/core/fmt.js +109 -0
  33. package/dist/core/fmt.js.map +1 -0
  34. package/dist/core/fs.d.ts +108 -0
  35. package/dist/core/fs.d.ts.map +1 -0
  36. package/dist/core/fs.js +243 -0
  37. package/dist/core/fs.js.map +1 -0
  38. package/dist/core/glob.d.ts +41 -0
  39. package/dist/core/glob.d.ts.map +1 -0
  40. package/dist/core/glob.js +399 -0
  41. package/dist/core/glob.js.map +1 -0
  42. package/dist/core/input-required.d.ts +147 -0
  43. package/dist/core/input-required.d.ts.map +1 -0
  44. package/dist/core/input-required.js +261 -0
  45. package/dist/core/input-required.js.map +1 -0
  46. package/dist/core/mime.d.ts +15 -0
  47. package/dist/core/mime.d.ts.map +1 -0
  48. package/dist/core/mime.js +188 -0
  49. package/dist/core/mime.js.map +1 -0
  50. package/dist/core/observability.d.ts +10 -0
  51. package/dist/core/observability.d.ts.map +1 -0
  52. package/dist/core/observability.js +76 -0
  53. package/dist/core/observability.js.map +1 -0
  54. package/dist/core/page-store.d.ts +41 -0
  55. package/dist/core/page-store.d.ts.map +1 -0
  56. package/dist/core/page-store.js +74 -0
  57. package/dist/core/page-store.js.map +1 -0
  58. package/dist/core/path-completer.d.ts +10 -0
  59. package/dist/core/path-completer.d.ts.map +1 -0
  60. package/dist/core/path-completer.js +227 -0
  61. package/dist/core/path-completer.js.map +1 -0
  62. package/dist/core/path-discovery.d.ts +8 -0
  63. package/dist/core/path-discovery.d.ts.map +1 -0
  64. package/dist/core/path-discovery.js +105 -0
  65. package/dist/core/path-discovery.js.map +1 -0
  66. package/dist/core/path-utils.d.ts +9 -0
  67. package/dist/core/path-utils.d.ts.map +1 -0
  68. package/dist/core/path-utils.js +121 -0
  69. package/dist/core/path-utils.js.map +1 -0
  70. package/dist/core/path.d.ts +148 -0
  71. package/dist/core/path.d.ts.map +1 -0
  72. package/dist/core/path.js +674 -0
  73. package/dist/core/path.js.map +1 -0
  74. package/dist/core/primitives.d.ts +23 -0
  75. package/dist/core/primitives.d.ts.map +1 -0
  76. package/dist/core/primitives.js +54 -0
  77. package/dist/core/primitives.js.map +1 -0
  78. package/dist/core/read.d.ts +74 -0
  79. package/dist/core/read.d.ts.map +1 -0
  80. package/dist/core/read.js +562 -0
  81. package/dist/core/read.js.map +1 -0
  82. package/dist/core/schema.d.ts +139 -0
  83. package/dist/core/schema.d.ts.map +1 -0
  84. package/dist/core/schema.js +345 -0
  85. package/dist/core/schema.js.map +1 -0
  86. package/dist/core/search.d.ts +100 -0
  87. package/dist/core/search.d.ts.map +1 -0
  88. package/dist/core/search.js +248 -0
  89. package/dist/core/search.js.map +1 -0
  90. package/dist/core/sensitive.d.ts +6 -0
  91. package/dist/core/sensitive.d.ts.map +1 -0
  92. package/dist/core/sensitive.js +142 -0
  93. package/dist/core/sensitive.js.map +1 -0
  94. package/dist/core/store.d.ts +57 -0
  95. package/dist/core/store.d.ts.map +1 -0
  96. package/dist/core/store.js +162 -0
  97. package/dist/core/store.js.map +1 -0
  98. package/dist/core/util.d.ts +26 -0
  99. package/dist/core/util.d.ts.map +1 -0
  100. package/dist/core/util.js +66 -0
  101. package/dist/core/util.js.map +1 -0
  102. package/dist/core/watcher-registry.d.ts +68 -0
  103. package/dist/core/watcher-registry.d.ts.map +1 -0
  104. package/dist/core/watcher-registry.js +312 -0
  105. package/dist/core/watcher-registry.js.map +1 -0
  106. package/dist/http-policy.d.ts +121 -0
  107. package/dist/http-policy.d.ts.map +1 -0
  108. package/dist/http-policy.js +340 -0
  109. package/dist/http-policy.js.map +1 -0
  110. package/dist/index.d.ts +1 -0
  111. package/dist/index.d.ts.map +1 -0
  112. package/dist/index.js +77 -41
  113. package/dist/index.js.map +1 -0
  114. package/dist/instructions.d.ts +12 -0
  115. package/dist/instructions.d.ts.map +1 -0
  116. package/dist/instructions.js +71 -0
  117. package/dist/instructions.js.map +1 -0
  118. package/dist/prompts.d.ts +8 -6
  119. package/dist/prompts.d.ts.map +1 -0
  120. package/dist/prompts.js +74 -168
  121. package/dist/prompts.js.map +1 -0
  122. package/dist/resources.d.ts +73 -9
  123. package/dist/resources.d.ts.map +1 -0
  124. package/dist/resources.js +392 -163
  125. package/dist/resources.js.map +1 -0
  126. package/dist/server.d.ts +62 -1
  127. package/dist/server.d.ts.map +1 -0
  128. package/dist/server.js +139 -1
  129. package/dist/server.js.map +1 -0
  130. package/dist/tools/batch.d.ts +89 -0
  131. package/dist/tools/batch.d.ts.map +1 -0
  132. package/dist/tools/batch.js +157 -0
  133. package/dist/tools/batch.js.map +1 -0
  134. package/dist/tools/create.d.ts +2 -0
  135. package/dist/tools/create.d.ts.map +1 -0
  136. package/dist/tools/create.js +142 -0
  137. package/dist/tools/create.js.map +1 -0
  138. package/dist/tools/define.d.ts +110 -0
  139. package/dist/tools/define.d.ts.map +1 -0
  140. package/dist/tools/define.js +394 -0
  141. package/dist/tools/define.js.map +1 -0
  142. package/dist/tools/delete-file.d.ts +2 -4
  143. package/dist/tools/delete-file.d.ts.map +1 -0
  144. package/dist/tools/delete-file.js +330 -87
  145. package/dist/tools/delete-file.js.map +1 -0
  146. package/dist/tools/diff.d.ts +2 -0
  147. package/dist/tools/diff.d.ts.map +1 -0
  148. package/dist/tools/diff.js +94 -0
  149. package/dist/tools/diff.js.map +1 -0
  150. package/dist/tools/edit.d.ts +2 -0
  151. package/dist/tools/edit.d.ts.map +1 -0
  152. package/dist/tools/edit.js +442 -0
  153. package/dist/tools/edit.js.map +1 -0
  154. package/dist/tools/index.d.ts +26 -0
  155. package/dist/tools/index.d.ts.map +1 -0
  156. package/dist/tools/index.js +52 -0
  157. package/dist/tools/index.js.map +1 -0
  158. package/dist/tools/list.d.ts +2 -0
  159. package/dist/tools/list.d.ts.map +1 -0
  160. package/dist/tools/list.js +291 -0
  161. package/dist/tools/list.js.map +1 -0
  162. package/dist/tools/move.d.ts +2 -0
  163. package/dist/tools/move.d.ts.map +1 -0
  164. package/dist/tools/move.js +321 -0
  165. package/dist/tools/move.js.map +1 -0
  166. package/dist/tools/patch.d.ts +2 -0
  167. package/dist/tools/patch.d.ts.map +1 -0
  168. package/dist/tools/patch.js +155 -0
  169. package/dist/tools/patch.js.map +1 -0
  170. package/dist/tools/progress.d.ts +52 -0
  171. package/dist/tools/progress.d.ts.map +1 -0
  172. package/dist/tools/progress.js +172 -0
  173. package/dist/tools/progress.js.map +1 -0
  174. package/dist/tools/read.d.ts +2 -4
  175. package/dist/tools/read.d.ts.map +1 -0
  176. package/dist/tools/read.js +398 -152
  177. package/dist/tools/read.js.map +1 -0
  178. package/dist/tools/replace-in-files.d.ts +2 -4
  179. package/dist/tools/replace-in-files.d.ts.map +1 -0
  180. package/dist/tools/replace-in-files.js +435 -264
  181. package/dist/tools/replace-in-files.js.map +1 -0
  182. package/dist/tools/roots.d.ts +2 -4
  183. package/dist/tools/roots.d.ts.map +1 -0
  184. package/dist/tools/roots.js +29 -52
  185. package/dist/tools/roots.js.map +1 -0
  186. package/dist/tools/search-content.d.ts +2 -4
  187. package/dist/tools/search-content.d.ts.map +1 -0
  188. package/dist/tools/search-content.js +262 -228
  189. package/dist/tools/search-content.js.map +1 -0
  190. package/dist/tools/search-files.d.ts +2 -4
  191. package/dist/tools/search-files.d.ts.map +1 -0
  192. package/dist/tools/search-files.js +162 -161
  193. package/dist/tools/search-files.js.map +1 -0
  194. package/dist/tools/stat.d.ts +2 -4
  195. package/dist/tools/stat.d.ts.map +1 -0
  196. package/dist/tools/stat.js +202 -62
  197. package/dist/tools/stat.js.map +1 -0
  198. package/dist/transport/http.d.ts +5 -0
  199. package/dist/transport/http.d.ts.map +1 -0
  200. package/dist/transport/http.js +276 -0
  201. package/dist/transport/http.js.map +1 -0
  202. package/dist/transport/shared.d.ts +45 -0
  203. package/dist/transport/shared.d.ts.map +1 -0
  204. package/dist/transport/shared.js +65 -0
  205. package/dist/transport/shared.js.map +1 -0
  206. package/dist/transport/stdio.d.ts +32 -0
  207. package/dist/transport/stdio.d.ts.map +1 -0
  208. package/dist/transport/stdio.js +279 -0
  209. package/dist/transport/stdio.js.map +1 -0
  210. package/dist/transport.d.ts +5 -0
  211. package/dist/transport.d.ts.map +1 -0
  212. package/dist/transport.js +4 -0
  213. package/dist/transport.js.map +1 -0
  214. package/package.json +37 -46
  215. package/dist/assets/logo.svg +0 -35
  216. package/dist/completions.d.ts +0 -2
  217. package/dist/completions.js +0 -572
  218. package/dist/config.d.ts +0 -119
  219. package/dist/config.js +0 -31
  220. package/dist/lib/abort.d.ts +0 -7
  221. package/dist/lib/abort.js +0 -81
  222. package/dist/lib/constants.d.ts +0 -42
  223. package/dist/lib/constants.js +0 -313
  224. package/dist/lib/errors.d.ts +0 -28
  225. package/dist/lib/errors.js +0 -301
  226. package/dist/lib/file-operations/core.d.ts +0 -53
  227. package/dist/lib/file-operations/core.js +0 -144
  228. package/dist/lib/file-operations/metadata.d.ts +0 -77
  229. package/dist/lib/file-operations/metadata.js +0 -878
  230. package/dist/lib/file-operations/search.d.ts +0 -46
  231. package/dist/lib/file-operations/search.js +0 -1194
  232. package/dist/lib/file-operations/traversal.d.ts +0 -40
  233. package/dist/lib/file-operations/traversal.js +0 -310
  234. package/dist/lib/fs-helpers.d.ts +0 -46
  235. package/dist/lib/fs-helpers.js +0 -606
  236. package/dist/lib/globs.d.ts +0 -2
  237. package/dist/lib/globs.js +0 -19
  238. package/dist/lib/logger.d.ts +0 -27
  239. package/dist/lib/logger.js +0 -91
  240. package/dist/lib/observability.d.ts +0 -33
  241. package/dist/lib/observability.js +0 -373
  242. package/dist/lib/paths.d.ts +0 -35
  243. package/dist/lib/paths.js +0 -634
  244. package/dist/lib/resource-store.d.ts +0 -28
  245. package/dist/lib/resource-store.js +0 -195
  246. package/dist/lib/utils.d.ts +0 -7
  247. package/dist/lib/utils.js +0 -37
  248. package/dist/lib/zod-codecs.d.ts +0 -2
  249. package/dist/lib/zod-codecs.js +0 -18
  250. package/dist/pkg-info.d.ts +0 -7
  251. package/dist/pkg-info.js +0 -9
  252. package/dist/resources/generated-instructions.d.ts +0 -1
  253. package/dist/resources/generated-instructions.js +0 -105
  254. package/dist/resources/tool-catalog.d.ts +0 -2
  255. package/dist/resources/tool-catalog.js +0 -78
  256. package/dist/resources/tool-info.d.ts +0 -9
  257. package/dist/resources/tool-info.js +0 -206
  258. package/dist/resources/workflows.d.ts +0 -1
  259. package/dist/resources/workflows.js +0 -72
  260. package/dist/schemas.d.ts +0 -505
  261. package/dist/schemas.js +0 -676
  262. package/dist/server/bootstrap.d.ts +0 -6
  263. package/dist/server/bootstrap.js +0 -585
  264. package/dist/server/event-store.d.ts +0 -18
  265. package/dist/server/event-store.js +0 -71
  266. package/dist/server/roots-manager.d.ts +0 -28
  267. package/dist/server/roots-manager.js +0 -227
  268. package/dist/server/task-store.d.ts +0 -10
  269. package/dist/server/task-store.js +0 -91
  270. package/dist/tools/apply-patch.d.ts +0 -4
  271. package/dist/tools/apply-patch.js +0 -235
  272. package/dist/tools/calculate-hash.d.ts +0 -4
  273. package/dist/tools/calculate-hash.js +0 -187
  274. package/dist/tools/contract.d.ts +0 -50
  275. package/dist/tools/contract.js +0 -1
  276. package/dist/tools/create-directory.d.ts +0 -4
  277. package/dist/tools/create-directory.js +0 -68
  278. package/dist/tools/diff-files.d.ts +0 -4
  279. package/dist/tools/diff-files.js +0 -136
  280. package/dist/tools/edit-file.d.ts +0 -4
  281. package/dist/tools/edit-file.js +0 -256
  282. package/dist/tools/icons.d.ts +0 -15
  283. package/dist/tools/icons.js +0 -24
  284. package/dist/tools/list-directory.d.ts +0 -4
  285. package/dist/tools/list-directory.js +0 -218
  286. package/dist/tools/move-file.d.ts +0 -4
  287. package/dist/tools/move-file.js +0 -178
  288. package/dist/tools/read-multiple.d.ts +0 -4
  289. package/dist/tools/read-multiple.js +0 -207
  290. package/dist/tools/shared.d.ts +0 -172
  291. package/dist/tools/shared.js +0 -599
  292. package/dist/tools/stat-many.d.ts +0 -4
  293. package/dist/tools/stat-many.js +0 -104
  294. package/dist/tools/task-support.d.ts +0 -29
  295. package/dist/tools/task-support.js +0 -473
  296. package/dist/tools/tree.d.ts +0 -4
  297. package/dist/tools/tree.js +0 -102
  298. package/dist/tools/write-file.d.ts +0 -4
  299. package/dist/tools/write-file.js +0 -60
  300. package/dist/tools.d.ts +0 -5
  301. package/dist/tools.js +0 -54
package/README.md CHANGED
@@ -1,132 +1,91 @@
1
1
  # Filesystem MCP Server
2
2
 
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)
3
+ [![License](https://img.shields.io/github/license/j0hanz/filesystem-mcp?style=for-the-badge)](https://github.com/j0hanz/filesystem-mcp/blob/main/LICENSE) [![npm version](https://img.shields.io/npm/v/%40j0hanz%2Ffilesystem-mcp?style=for-the-badge&logo=npm&logoColor=white)](https://www.npmjs.com/package/@j0hanz/filesystem-mcp) [![Build](https://img.shields.io/github/actions/workflow/status/j0hanz/filesystem-mcp/release.yml?style=for-the-badge&logo=githubactions&logoColor=white&label=build)](https://github.com/j0hanz/filesystem-mcp/actions) [![GitHub stars](https://img.shields.io/github/stars/j0hanz/filesystem-mcp?style=for-the-badge&logo=github)](https://github.com/j0hanz/filesystem-mcp/stargazers)
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&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&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
-
7
- [![Add to LM Studio](https://files.lmstudio.ai/deeplink/mcp-install-light.svg)](https://lmstudio.ai/install-mcp?name=filesystem&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkBqMGhhbnovZmlsZXN5c3RlbS1tY3BAbGF0ZXN0Il19) [![Install in Cursor](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en/install-mcp?name=filesystem&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkBqMGhhbnovZmlsZXN5c3RlbS1tY3BAbGF0ZXN0Il19)
8
-
9
- Secure filesystem MCP server for reading, writing, searching, diffing, and patching files.
10
-
11
- ## Table of Contents
12
-
13
- - [Overview](#overview)
14
- - [Key Features](#key-features)
15
- - [Quick Start](#quick-start) — [Docker](#docker) · [CLI Usage](#cli-usage)
16
- - [Client Configuration](#client-configuration)
17
- - [Use Cases](#use-cases)
18
- - [Architecture](#architecture)
19
- - [MCP Surface](#mcp-surface) — [Tools](#tools) · [Resources](#resources) · [Prompts](#prompts)
20
- - [MCP Capabilities](#mcp-capabilities) — [Tool Annotations](#tool-annotations) · [Structured Output](#structured-output)
21
- - [Configuration](#configuration) — [HTTP & Auth](#http--auth) · [File Size Limits](#file-size-limits) · [Access Control](#access-control) · [Output & Inline Limits](#output--inline-limits) · [Tasks](#tasks) · [Logging & Diagnostics](#logging--diagnostics) · [Performance](#performance)
22
- - [HTTP Endpoints](#http-endpoints)
23
- - [Security](#security)
24
- - [Development](#development)
25
- - [Troubleshooting](#troubleshooting)
26
- - [Credits](#credits)
27
- - [Contributing and License](#contributing-and-license)
5
+ [![Install in VS Code](https://img.shields.io/badge/VS_Code-Install-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)](https://vscode.dev/redirect/mcp/install?name=filesystem&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-24bfa5?style=flat-square&logo=visualstudiocode&logoColor=white)](https://insiders.vscode.dev/redirect/mcp/install?name=filesystem&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-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) [![Install in Cursor](https://img.shields.io/badge/Cursor-Install-000000?style=flat-square&logo=cursor&logoColor=white)](cursor://anysphere.cursor-deeplink/mcp/install?name=filesystem&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkBqMGhhbnovZmlsZXN5c3RlbS1tY3BAbGF0ZXN0Il19)
28
6
 
29
7
  ## Overview
30
8
 
31
- 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.
32
-
33
- Supports stdio (default) and Node Streamable HTTP transport. HTTP sessions are implemented with isolated per-session server state. The HTTP transport is stateful by default and currently non-resumable; it does not persist an event store for `Last-Event-ID` replay.
34
-
35
- ## Key Features
9
+ Filesystem-MCP is a [Model Context Protocol](https://modelcontextprotocol.io) server that lets AI assistants read and write files within explicitly allowed directories. Sensitive file patterns (`.env`, `*.pem`, `*id_rsa*`) are blocked by default. It exposes filesystem tools, resources, and prompts over stdio or Streamable HTTP transport.
36
10
 
37
- - **18 filesystem tools** — read, write, search, diff, patch, hash, and bulk operations with structured output schemas
38
- - **Security-first** path validation, symlink escape prevention, sensitive file denylist, localhost-only CORS, Host header validation for loopback HTTP binds, optional API key auth
39
- - **Dual transport** stdio for local use, Node Streamable HTTP for networked/multi-session deployments
40
- - **Structured output** all tools return typed `outputSchema` / `structuredContent` for reliable LLM parsing
41
- - **Self-documenting** — 6 built-in resources (`internal://instructions`, `internal://tool-catalog`, etc.) and 4 built-in prompts (`get-help`, `compare-files`, `analyze-path`, `get-tool-help`)
11
+ | Aspect | Details |
12
+ | :----------- | :--------------------------------------------- |
13
+ | **Status** | Active (see npm badge for the current version) |
14
+ | **Language** | TypeScript (strict) |
15
+ | **Runtime** | Node.js >= 24 |
16
+ | **Package** | npm |
17
+ | **License** | MIT |
42
18
 
43
- ## Requirements
19
+ ## Features
44
20
 
45
- - Node.js >= 24
21
+ | Feature | Description |
22
+ | :--------------------- | :--------------------------------------------------------------------------------------------------------- |
23
+ | **Path guarding** | Every path is validated against allowed roots; `.env`, `*.pem`, `*id_rsa*` and similar patterns are denied |
24
+ | **Filesystem tools** | Navigate, inspect, read, and write across all major file operations |
25
+ | **Batch operations** | Most tools accept `path`, `paths[]`, or `files[]` for parallel execution |
26
+ | **Dual transport** | stdio by default; `--port` enables Streamable HTTP |
27
+ | **File subscriptions** | Resource subscriptions push change notifications when watched files update |
28
+ | **Regex safety** | RE2 in all search tools: linear-time matching, so no pattern can ReDoS the server |
46
29
 
47
- ## Quick Start
30
+ ## Built with
48
31
 
49
- ```json
50
- {
51
- "mcpServers": {
52
- "filesystem": {
53
- "command": "npx",
54
- "args": ["-y", "@j0hanz/filesystem-mcp@latest"]
55
- }
56
- }
57
- }
58
- ```
32
+ [![Node.js](https://img.shields.io/badge/node-%3E%3D24-339933?style=for-the-badge&logo=node.js&logoColor=white)](https://nodejs.org) [![TypeScript](https://img.shields.io/badge/TypeScript-strict-3178C6?style=for-the-badge&logo=typescript&logoColor=white)](https://www.typescriptlang.org) [![Docker](https://img.shields.io/badge/Docker-ready-2496ED?style=for-the-badge&logo=docker&logoColor=white)](https://www.docker.com)
59
33
 
60
- ### Docker
34
+ | Layer | Technology |
35
+ | :-------- | :--------------------------------------------------------------------- |
36
+ | Protocol | MCP SDK v2 (`@modelcontextprotocol/server`) |
37
+ | Runtime | Node.js >= 24 · TypeScript 6 · ESM |
38
+ | Transport | stdio (default) · Streamable HTTP (`--port`) |
39
+ | Regex | RE2 (`re2-wasm`) — linear time, no lookahead/lookbehind/backreferences |
40
+ | Container | Docker alpine · multi-stage build · non-root user |
61
41
 
62
- ```bash
63
- docker run -i --rm -v /path/to/project:/workspace:ro ghcr.io/j0hanz/filesystem-mcp /workspace
64
- ```
42
+ ## Table of Contents
65
43
 
66
- Or using Docker Compose:
44
+ - [Quick start](#quick-start)
45
+ - [Usage](#usage)
46
+ - [Project structure](#project-structure)
47
+ - [Configuration](#configuration)
48
+ - [Scripts](#scripts)
49
+ - [Security](#security)
50
+ - [Contributing](#contributing)
51
+ - [License](#license)
67
52
 
68
- ```yaml
69
- services:
70
- filesystem-mcp:
71
- build: .
72
- stdin_open: true
73
- volumes:
74
- - ./:/projects/workspace:ro
75
- command: ['/projects/workspace']
76
- ```
53
+ ## Quick start
77
54
 
78
- ### CLI Usage
55
+ > [!NOTE]
56
+ > Requires Node.js ≥ 24.
79
57
 
80
- ```
81
- filesystem-mcp [options] [allowedDirs...]
58
+ ### Prerequisites
82
59
 
83
- Arguments:
84
- allowedDirs Directories the server can access
60
+ | Requirement | Version / Notes |
61
+ | :---------- | :--------------------------- |
62
+ | Node.js | ≥ 24 |
63
+ | npm | Bundled with Node.js |
64
+ | Docker | Optional — for container use |
85
65
 
86
- Options:
87
- --allow-cwd Allow the current working directory as an additional root
88
- --port <number> Enable HTTP transport on the given port
89
- -v, --version Display server version
90
- -h, --help Display help
66
+ ### Install via npx
91
67
 
92
- Examples:
93
- $ npx @j0hanz/filesystem-mcp@latest /path/to/project
94
- $ npx @j0hanz/filesystem-mcp@latest --allow-cwd
95
- $ npx @j0hanz/filesystem-mcp@latest --port 3000 /path/to/project
68
+ ```bash
69
+ npx -y @j0hanz/filesystem-mcp /path/to/allowed/dir
96
70
  ```
97
71
 
98
- ## Client Configuration
99
-
100
- <details>
101
- <summary><b>Install in VS Code</b></summary>
72
+ Or install globally:
102
73
 
103
- [![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&config=%7B%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40j0hanz%2Ffilesystem-mcp%40latest%22%5D%7D)
104
-
105
- Add to `.vscode/mcp.json`:
106
-
107
- ```json
108
- {
109
- "servers": {
110
- "filesystem": {
111
- "command": "npx",
112
- "args": ["-y", "@j0hanz/filesystem-mcp@latest"]
113
- }
114
- }
115
- }
74
+ ```bash
75
+ npm install -g @j0hanz/filesystem-mcp
76
+ filesystem-mcp /path/to/allowed/dir
116
77
  ```
117
78
 
118
- Or install via CLI:
79
+ ### Install via Docker
119
80
 
120
- ```sh
121
- code --add-mcp '{"name":"filesystem","command":"npx","args":["-y","@j0hanz/filesystem-mcp@latest"]}'
81
+ ```bash
82
+ docker run -i --rm \
83
+ -v /path/to/project:/workspace:ro \
84
+ ghcr.io/j0hanz/filesystem-mcp:latest \
85
+ --read-only /workspace
122
86
  ```
123
87
 
124
- </details>
125
-
126
- <details>
127
- <summary><b>Install in VS Code Insiders</b></summary>
128
-
129
- [![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&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)
88
+ ### Configure in VS Code
130
89
 
131
90
  Add to `.vscode/mcp.json`:
132
91
 
@@ -135,7 +94,7 @@ Add to `.vscode/mcp.json`:
135
94
  "servers": {
136
95
  "filesystem": {
137
96
  "command": "npx",
138
- "args": ["-y", "@j0hanz/filesystem-mcp@latest"]
97
+ "args": ["-y", "@j0hanz/filesystem-mcp@latest", "/path/to/project"]
139
98
  }
140
99
  }
141
100
  }
@@ -144,875 +103,411 @@ Add to `.vscode/mcp.json`:
144
103
  Or install via CLI:
145
104
 
146
105
  ```sh
147
- code-insiders --add-mcp '{"name":"filesystem","command":"npx","args":["-y","@j0hanz/filesystem-mcp@latest"]}'
106
+ code --add-mcp '{"name":"filesystem","command":"npx","args":["-y","@j0hanz/filesystem-mcp@latest","/path/to/project"]}'
148
107
  ```
149
108
 
150
- </details>
151
-
152
- <details>
153
- <summary><b>Install in Cursor</b></summary>
154
-
155
- [![Install in Cursor](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en/install-mcp?name=filesystem&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkBqMGhhbnovZmlsZXN5c3RlbS1tY3BAbGF0ZXN0Il19)
156
-
157
- Add to `~/.cursor/mcp.json`:
158
-
159
- ```json
160
- {
161
- "mcpServers": {
162
- "filesystem": {
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 Visual Studio</b></summary>
174
-
175
- [![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)
109
+ ### Configure in Visual Studio
176
110
 
177
- Add to `<SOLUTIONDIR>.mcp.json` or `%USERPROFILE%\.mcp.json`:
111
+ Add to `.vs\mcp.json` in your solution directory, or `%USERPROFILE%\.mcp.json` for a global configuration:
178
112
 
179
113
  ```json
180
114
  {
181
115
  "servers": {
182
116
  "filesystem": {
183
117
  "command": "npx",
184
- "args": ["-y", "@j0hanz/filesystem-mcp@latest"]
118
+ "args": ["-y", "@j0hanz/filesystem-mcp@latest", "/path/to/project"]
185
119
  }
186
120
  }
187
121
  }
188
122
  ```
189
123
 
190
- </details>
124
+ ### Configure in Claude Desktop
191
125
 
192
- <details>
193
- <summary><b>Install in Goose</b></summary>
194
-
195
- Add to `~/.config/goose/config.yaml`:
196
-
197
- ```yaml
198
- extensions:
199
- filesystem:
200
- name: Filesystem MCP
201
- cmd: npx
202
- args:
203
- - -y
204
- - '@j0hanz/filesystem-mcp@latest'
205
- enabled: true
206
- type: stdio
207
- ```
208
-
209
- </details>
210
-
211
- <details>
212
- <summary><b>Add to LM Studio</b></summary>
213
-
214
- [![Add to LM Studio](https://files.lmstudio.ai/deeplink/mcp-install-light.svg)](https://lmstudio.ai/install-mcp?name=filesystem&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkBqMGhhbnovZmlsZXN5c3RlbS1tY3BAbGF0ZXN0Il19)
126
+ Add to your `claude_desktop_config.json`:
215
127
 
216
128
  ```json
217
129
  {
218
130
  "mcpServers": {
219
131
  "filesystem": {
220
132
  "command": "npx",
221
- "args": ["-y", "@j0hanz/filesystem-mcp@latest"]
133
+ "args": ["-y", "@j0hanz/filesystem-mcp@latest", "/path/to/project"]
222
134
  }
223
135
  }
224
136
  }
225
137
  ```
226
138
 
227
- </details>
228
-
229
- <details>
230
- <summary><b>Install in Claude Desktop</b></summary>
139
+ ### Install in Cursor
231
140
 
232
- Add to `claude_desktop_config.json`:
141
+ Add to `.cursor/mcp.json` in your project root (project-scoped), or `~/.cursor/mcp.json` for a global configuration:
233
142
 
234
143
  ```json
235
144
  {
236
145
  "mcpServers": {
237
146
  "filesystem": {
238
147
  "command": "npx",
239
- "args": ["-y", "@j0hanz/filesystem-mcp@latest"]
148
+ "args": ["-y", "@j0hanz/filesystem-mcp@latest", "/path/to/project"]
240
149
  }
241
150
  }
242
151
  }
243
152
  ```
244
153
 
245
- </details>
246
-
247
- <details>
248
- <summary><b>Install in Claude Code</b></summary>
154
+ ### Docker configuration
249
155
 
250
- ```sh
251
- claude mcp add filesystem-mcp -- npx -y @j0hanz/filesystem-mcp@latest
252
- ```
253
-
254
- Or add a project-scoped `.mcp.json`:
156
+ VS Code (`.vscode/mcp.json`) and Visual Studio (`.vs\mcp.json`):
255
157
 
256
158
  ```json
257
159
  {
258
- "mcpServers": {
160
+ "servers": {
259
161
  "filesystem": {
260
- "command": "npx",
261
- "args": ["-y", "@j0hanz/filesystem-mcp@latest"]
162
+ "command": "docker",
163
+ "args": [
164
+ "run",
165
+ "-i",
166
+ "--rm",
167
+ "-v",
168
+ "/path/to/project:/workspace",
169
+ "ghcr.io/j0hanz/filesystem-mcp:latest",
170
+ "/workspace"
171
+ ]
262
172
  }
263
173
  }
264
174
  }
265
175
  ```
266
176
 
267
- </details>
268
-
269
- <details>
270
- <summary><b>Install in Windsurf</b></summary>
271
-
272
- Add to `~/.codeium/windsurf/mcp_config.json`:
177
+ Claude Desktop (`claude_desktop_config.json`) and Cursor (`mcp.json`):
273
178
 
274
179
  ```json
275
180
  {
276
181
  "mcpServers": {
277
182
  "filesystem": {
278
- "command": "npx",
279
- "args": ["-y", "@j0hanz/filesystem-mcp@latest"]
183
+ "command": "docker",
184
+ "args": [
185
+ "run",
186
+ "-i",
187
+ "--rm",
188
+ "-v",
189
+ "/path/to/project:/workspace",
190
+ "ghcr.io/j0hanz/filesystem-mcp:latest",
191
+ "/workspace"
192
+ ]
280
193
  }
281
194
  }
282
195
  }
283
196
  ```
284
197
 
285
- </details>
286
-
287
- <details>
288
- <summary><b>Install in Amp</b></summary>
289
-
290
- ```sh
291
- amp mcp add filesystem-mcp -- npx -y @j0hanz/filesystem-mcp@latest
292
- ```
198
+ > [!NOTE]
199
+ > For least privilege, use both controls: `:ro` makes the container mount
200
+ > read-only at the operating-system boundary, while the server's `--read-only`
201
+ > flag removes mutating tools (`create`, `edit`, `move`, `delete`, `patch`,
202
+ > `replace_text`) from `tools/list`.
293
203
 
294
- Or add to `settings.json`:
204
+ ## Usage
295
205
 
296
- ```json
297
- {
298
- "amp.mcpServers": {
299
- "filesystem": {
300
- "command": "npx",
301
- "args": ["-y", "@j0hanz/filesystem-mcp@latest"]
302
- }
303
- }
304
- }
305
- ```
206
+ ### Tools
306
207
 
307
- </details>
208
+ All tools are scoped to the configured roots. Call `list_roots` first to discover what is allowed.
308
209
 
309
- <details>
310
- <summary><b>Install in Cline</b></summary>
210
+ #### Navigate
311
211
 
312
- Add to `cline_mcp_settings.json`:
212
+ | Tool | Description |
213
+ | :----------- | :------------------------------------------------------------------------------------- |
214
+ | `list_roots` | List allowed workspace roots. Call this first — all other tools scope to these. |
215
+ | `list` | List directory contents. Returns entries (dirs-first, alphabetical) and an ASCII tree. |
216
+ | `find_files` | Find files by glob pattern (e.g. `**/*.ts`). Returns matching files with metadata. |
313
217
 
314
- ```json
315
- {
316
- "mcpServers": {
317
- "filesystem": {
318
- "command": "npx",
319
- "args": ["-y", "@j0hanz/filesystem-mcp@latest"]
320
- }
321
- }
322
- }
323
- ```
218
+ #### Inspect
324
219
 
325
- </details>
220
+ | Tool | Description |
221
+ | :------------ | :---------------------------------------------------------------------------------------- |
222
+ | `stat` | Get file/directory metadata: size, modified time, permissions, MIME type, token estimate. |
223
+ | `search_text` | Search file contents for text (grep-like). Returns matching lines with context. |
224
+ | `diff` | Compare two files and return a unified diff with added/removed line counts. |
326
225
 
327
- <details>
328
- <summary><b>Install in Codex</b></summary>
226
+ #### Read
329
227
 
330
- ```sh
331
- codex mcp add filesystem -- npx -y @j0hanz/filesystem-mcp@latest
332
- ```
228
+ | Tool | Description |
229
+ | :----- | :----------------------------------------------------------------------------------- |
230
+ | `read` | Read a text file. Supports head/tail and line ranges. Accepts `paths[]` for batches. |
333
231
 
334
- Or add to `~/.codex/config.toml` (or `.codex/config.toml` in a trusted project):
232
+ #### Write
335
233
 
336
- ```toml
337
- [mcp_servers.filesystem]
338
- command = "npx"
339
- args = ["-y", "@j0hanz/filesystem-mcp@latest"]
340
- ```
234
+ | Tool | Description |
235
+ | :------------- | :------------------------------------------------------------------------------------------------ |
236
+ | `create` | Create one or more files, overwriting existing content and creating parent directories as needed. |
237
+ | `edit` | Apply sequential literal string replacements to one or more files (max 5 per call). |
238
+ | `move` | Move, rename, or copy (`copy: true`) one or more files/directories to explicit destinations. |
239
+ | `delete` | Permanently delete one or more files or directories. This action is irreversible. |
240
+ | `replace_text` | Bulk search-and-replace across files matching a glob pattern. |
241
+ | `patch` | Apply a single-file unified diff and write the result. |
341
242
 
342
- </details>
243
+ ### Resources
343
244
 
344
- <details>
345
- <summary><b>Install in GitHub Copilot Coding Agent</b></summary>
245
+ | URI | Description |
246
+ | :------------------------------ | :------------------------------------------------------------------------------------ |
247
+ | `internal://instructions` | Server navigation guide — tools overview, constraints, and error recovery. |
248
+ | `filesystem-mcp://file/{+path}` | Read a workspace file. Subscribe to receive push notifications on change. |
249
+ | `filesystem-mcp://result/{id}` | Ephemeral cached tool output. Expires after ~60 seconds, eviction, or server restart. |
346
250
 
347
- Add this JSON in your repository's GitHub Copilot coding agent MCP configuration:
251
+ ### Prompts
348
252
 
349
- ```json
350
- {
351
- "mcpServers": {
352
- "filesystem": {
353
- "type": "local",
354
- "command": "npx",
355
- "args": ["-y", "@j0hanz/filesystem-mcp@latest"],
356
- "tools": ["*"]
357
- }
358
- }
359
- }
360
- ```
253
+ | Prompt | Description |
254
+ | :--------- | :-------------------------------------------------------------------- |
255
+ | `get-help` | Return usage instructions, optionally filtered to a specific section. |
361
256
 
362
- </details>
257
+ ## Project structure
363
258
 
364
- <details>
365
- <summary><b>Install in Warp</b></summary>
259
+ ```text
260
+ filesystem-mcp/
261
+ ├── __tests__/ Test suites
262
+ ├── scripts/ Build and task utilities
263
+ ├── src/
264
+ │ ├── core/ Path guarding, filesystem abstraction, concurrency, observability
265
+ │ ├── tools/ Tool definitions and registration
266
+ │ ├── index.ts Process entrypoint and transport selection
267
+ │ ├── server.ts Server factory and registrar composition
268
+ │ ├── transport/ stdio and Streamable HTTP transport setup
269
+ │ ├── prompts.ts Prompt definitions and registration
270
+ │ └── resources.ts Resource definitions and registration
271
+ └── Dockerfile Multi-stage alpine build, non-root user
272
+ ```
273
+
274
+ Runtime composition flows from `src/index.ts` to `src/transport.ts`, then to
275
+ `src/server.ts`, the registrars, and finally `src/core/`. Each registrar owns
276
+ the narrow dependency contract it consumes.
277
+
278
+ | Path | Purpose |
279
+ | :-------------------- | :------------------------------------------------------------- |
280
+ | `src/core/path.ts` | `PathGuard` — validates every path against allowed roots |
281
+ | `src/core/fs.ts` | `GuardedFileSystem` — guarded filesystem facade |
282
+ | `src/tools/define.ts` | Tool registration and execution framework |
283
+ | `src/tools/batch.ts` | Batch helpers (runOverPaths, normalizeBatchItems) |
284
+ | `src/server.ts` | Builds shared dependencies and invokes the three registrars |
285
+ | `src/transport.ts` | Owns stdio and Streamable HTTP setup around the server factory |
366
286
 
367
- ```json
368
- {
369
- "mcpServers": {
370
- "filesystem": {
371
- "command": "npx",
372
- "args": ["-y", "@j0hanz/filesystem-mcp@latest"]
373
- }
374
- }
375
- }
376
- ```
287
+ ## Configuration
377
288
 
378
- </details>
289
+ The server starts with allowed directories from explicit startup configuration:
379
290
 
380
- <details>
381
- <summary><b>Install in Kiro</b></summary>
291
+ 1. **Positional directories** passed to `filesystem-mcp`.
292
+ 2. **Environment variable** `FS_ALLOWED_DIRS` (separated by `:` on POSIX or `;` on Windows).
293
+ 3. **Current working directory** when `--allow-cwd` is enabled.
382
294
 
383
- Add to `.kiro/settings/mcp.json`:
295
+ Legacy MCP connections may additionally seed roots through the deprecated
296
+ `roots/list` flow. Modern 2026-07-28 connections do not automatically send
297
+ workspace roots. They can add access after startup by calling a tool with a
298
+ concrete path and approving the elicitation-backed grant. `list_roots` reports
299
+ the roots already configured or accepted; it cannot discover an unknown
300
+ workspace by itself.
384
301
 
385
- ```json
386
- {
387
- "mcpServers": {
388
- "filesystem": {
389
- "command": "npx",
390
- "args": ["-y", "@j0hanz/filesystem-mcp@latest"]
391
- }
392
- }
393
- }
394
- ```
302
+ ### Recommended global recipes
395
303
 
396
- </details>
304
+ #### VS Code / Cursor / Claude Code (primary recipe)
397
305
 
398
- <details>
399
- <summary><b>Install in Gemini CLI</b></summary>
306
+ Configure the project directory explicitly:
400
307
 
401
- Add to `~/.gemini/settings.json`:
308
+ Add to your global or project-scoped configuration:
402
309
 
403
310
  ```json
404
311
  {
405
312
  "mcpServers": {
406
313
  "filesystem": {
407
314
  "command": "npx",
408
- "args": ["-y", "@j0hanz/filesystem-mcp@latest"]
315
+ "args": ["-y", "@j0hanz/filesystem-mcp@latest", "/path/to/project"]
409
316
  }
410
317
  }
411
318
  }
412
319
  ```
413
320
 
414
- </details>
321
+ #### Claude Desktop (fallback recipe via environment variable)
415
322
 
416
- <details>
417
- <summary><b>Install in Zed</b></summary>
323
+ Claude Desktop and similar clients don't support the MCP Roots protocol. Use the `FS_ALLOWED_DIRS` environment variable to configure allowed folders.
418
324
 
419
- Add to `~/.config/zed/settings.json`:
325
+ Add to your `claude_desktop_config.json`:
420
326
 
421
327
  ```json
422
328
  {
423
- "context_servers": {
329
+ "mcpServers": {
424
330
  "filesystem": {
425
331
  "command": "npx",
426
332
  "args": ["-y", "@j0hanz/filesystem-mcp@latest"],
427
- "env": {}
333
+ "env": {
334
+ "FS_ALLOWED_DIRS": "/path/to/project1:/path/to/project2"
335
+ }
428
336
  }
429
337
  }
430
338
  }
431
339
  ```
432
340
 
433
- </details>
341
+ _(On Windows, separate directories with a semicolon `;` instead of a colon `:`)._
434
342
 
435
- <details>
436
- <summary><b>Install in Augment</b></summary>
343
+ ### Advanced / per-project positional arguments
437
344
 
438
- Add to VS Code `settings.json` under `augment.advanced`:
345
+ You can also restrict access to specific directories by passing positional arguments directly:
439
346
 
440
- ```json
441
- {
442
- "augment.advanced": {
443
- "mcpServers": [
444
- {
445
- "id": "filesystem",
446
- "command": "npx",
447
- "args": ["-y", "@j0hanz/filesystem-mcp@latest"]
448
- }
449
- ]
450
- }
451
- }
347
+ ```bash
348
+ # Start with explicit positional paths
349
+ filesystem-mcp /path/to/project1 /path/to/project2
452
350
  ```
453
351
 
454
- </details>
455
-
456
- <details>
457
- <summary><b>Install in Roo Code</b></summary>
352
+ ---
458
353
 
459
- ```json
460
- {
461
- "mcpServers": {
462
- "filesystem": {
463
- "command": "npx",
464
- "args": ["-y", "@j0hanz/filesystem-mcp@latest"]
465
- }
354
+ ### Configuration reference
355
+
356
+ #### CLI flags
357
+
358
+ | Flag | Default | Purpose |
359
+ | :------------------------ | :------ | :--------------------------------------------------------------------------------- |
360
+ | `[dirs...]` | — | One or more allowed root directories (positional) |
361
+ | `--allow-cwd` | `false` | Also allow the current working directory as a root |
362
+ | `--walk-cwd` | `false` | Walk up from CWD to find a project root; implies `--allow-cwd` |
363
+ | `--allow-missing-roots` | `false` | Start even if configured allowed directories do not exist |
364
+ | `--port <n>` | — | Enable Streamable HTTP transport on the given port (env: `FS_PORT`) |
365
+ | `--http-host <host>` | — | HTTP server bind address (env: `FS_HTTP_HOST`) |
366
+ | `--api-key <key>` | — | Require this API key on HTTP requests (env: `FS_API_KEY`) |
367
+ | `--read-only` | `false` | Disable write tools: `create`, `edit`, `delete`, `move`, `patch`, `replace_text` |
368
+ | `--safe` | `false` | Alias for `--read-only` |
369
+ | `--deny <pattern>` | — | Block paths matching this pattern; repeatable |
370
+ | `--allow-sensitive` | `false` | Allow access to sensitive system paths (env: `FS_ALLOW_SENSITIVE`) |
371
+ | `--root-boundary <path>` | — | Require all allowed roots to fall under this path (env: `FS_ROOT_BOUNDARY`) |
372
+ | `--max-file-size <bytes>` | — | Maximum file size for reads in bytes (env: `FS_MAX_FILE_SIZE`) |
373
+ | `--log-level <level>` | `info` | RFC 5424 log level, `debug` through `emergency` (env: `FS_LOG_LEVEL`) |
374
+ | `--print-config` | `false` | Print the active configuration and exit (use `--json` for machine-readable output) |
375
+ | `--json` | `false` | Output `--print-config` as JSON |
376
+
377
+ #### Environment variables
378
+
379
+ All boolean variables accept `true` or `1` to enable and `false`, `0`, or
380
+ unset to disable; any other value logs a warning and reads as disabled.
381
+ Flags take precedence when both are set.
382
+
383
+ | Variable | Purpose |
384
+ | :---------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
385
+ | `FS_ALLOWED_DIRS` | Colon-separated (POSIX) or semicolon-separated (Windows) list of directories to allow. |
386
+ | `FS_ROOT_BOUNDARY` | Path prefix all allowed roots must fall under (mirrors `--root-boundary`). |
387
+ | `FS_ALLOW_CWD_WALK` | Walk up from CWD to find a project root (mirrors `--walk-cwd`). |
388
+ | `FS_ALLOW_MISSING_ROOTS` | Start even if configured directories do not exist (mirrors `--allow-missing-roots`). |
389
+ | `FS_ALLOW_SENSITIVE` | Allow access to sensitive system paths (mirrors `--allow-sensitive`). |
390
+ | `FS_DENYLIST` | Comma-separated list of paths or patterns to block (mirrors `--deny`). |
391
+ | `FS_MAX_FILE_SIZE` | Maximum file size for reads in bytes (mirrors `--max-file-size`). |
392
+ | `FS_LOG_LEVEL` | RFC 5424 log level: `debug`, `info`, `notice`, `warn`/`warning`, `error`, `critical`, `alert`, or `emergency` (mirrors `--log-level`). |
393
+ | `FS_PORT` | Start the Streamable HTTP transport on this port; unset = stdio (mirrors `--port`). |
394
+ | `FS_HTTP_HOST` | HTTP server bind address (mirrors `--http-host`). |
395
+ | `FS_API_KEY` | API key required on HTTP requests (mirrors `--api-key`). |
396
+ | `FS_TRUST_PROXY` | Express `trust proxy` setting: hop count or expression. Unset = do not trust `X-Forwarded-*`. |
397
+ | `FS_ALLOWED_HOSTS` | Comma-separated Host header values to accept (HTTP transport). |
398
+ | `FS_ALLOWED_ORIGINS` | Comma-separated origin hostnames for CORS. |
399
+ | `FS_ALLOW_UNRESTRICTED_HOSTS` | Bind a wildcard host with no Host validation (accepts the risk). |
400
+ | `FS_PUBLIC_URL` | Resource identifier URL for RFC 9728 discovery. |
401
+ | `FS_RATE_LIMIT_RPM` | Per-client-IP requests/minute (default 120 with API-key authentication, 6,000 for keyless loopback; range 1–100000). |
402
+ | `FS_MAX_REQUEST_BYTES` | Max HTTP request body bytes (default 4194304, 1024–268435456). |
403
+ | `FS_KEEPALIVE_TIMEOUT_MS` | HTTP keep-alive timeout in ms; set above any fronting proxy's idle timeout (default 5000, 1000–600000). |
404
+ | `FS_MAX_WATCHERS` | Max concurrent file watchers (default 256, 1–4096). |
405
+ | `FS_MAX_INLINE_MATCHES` | Max inline content matches per search (default 50, 1–10000). |
406
+ | `FS_MAX_READ_MANY_BYTES` | Max total bytes across a batched `read` (default 524288, 10240–104857600). |
407
+ | `FS_SEARCH_TIMEOUT_MS` | Search timeout in ms (default 5000, 100–60000). |
408
+ | `NO_COLOR` | Any value disables ANSI color output. |
409
+ | `FS_REQUEST_STATE_KEY` | HMAC key sealing `input_required` requestState across retry rounds. Optional for stdio and single-instance HTTP (random per boot if unset); mandatory and shared across every fleet instance (UTF-8, >=32 bytes). |
410
+
411
+ #### Multi-instance HTTP deployments
412
+
413
+ Each instance delivers `subscriptions/listen` change events
414
+ (`resources/updated`, `tools/list_changed`, etc.) on an in-process bus by
415
+ default. Behind a load balancer with more than one instance, a listener on
416
+ instance A will not see an event published on instance B. Explicit fleet mode
417
+ therefore refuses to boot without a shared event bus.
418
+
419
+ To fan events out across instances, implement the SDK's `ServerEventBus`
420
+ interface (two methods: `publish`/`subscribe`) over whatever pub/sub you
421
+ already run, then pass it to filesystem-mcp's programmatic HTTP entry:
422
+
423
+ ```ts
424
+ import type { ServerEvent, ServerEventBus } from '@modelcontextprotocol/server';
425
+
426
+ import { startHttpServer } from '@j0hanz/filesystem-mcp/transport';
427
+ import Redis from 'ioredis';
428
+
429
+ // any pub/sub client works the same way
430
+
431
+ class RedisServerEventBus implements ServerEventBus {
432
+ private readonly listeners = new Set<(event: ServerEvent) => void>();
433
+ private readonly pub = new Redis(process.env['REDIS_URL']);
434
+ private readonly sub = new Redis(process.env['REDIS_URL']);
435
+
436
+ constructor() {
437
+ void this.sub.subscribe('fs-mcp-events');
438
+ this.sub.on('message', (_channel, message) => {
439
+ const event = JSON.parse(message) as ServerEvent;
440
+ for (const listener of this.listeners) listener(event);
441
+ });
466
442
  }
467
- }
468
- ```
469
443
 
470
- </details>
471
-
472
- <details>
473
- <summary><b>Install in Kilo Code</b></summary>
444
+ publish(event: ServerEvent): void {
445
+ void this.pub.publish('fs-mcp-events', JSON.stringify(event));
446
+ }
474
447
 
475
- ```json
476
- {
477
- "mcpServers": {
478
- "filesystem": {
479
- "command": "npx",
480
- "args": ["-y", "@j0hanz/filesystem-mcp@latest"]
481
- }
448
+ subscribe(listener: (event: ServerEvent) => void): () => void {
449
+ this.listeners.add(listener);
450
+ return () => this.listeners.delete(listener);
482
451
  }
483
452
  }
484
- ```
485
-
486
- </details>
487
-
488
- [↑ Back to top](#table-of-contents)
489
-
490
- ## Use Cases
491
-
492
- ### Explore and Understand a Codebase
493
-
494
- 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.
495
-
496
- **Relevant tools:** [`roots`](#roots), [`ls`](#ls), [`find`](#find), [`tree`](#tree), [`read`](#read), [`read_many`](#read_many), [`stat`](#stat)
497
-
498
- ### Search Across Files
499
-
500
- 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.
501
-
502
- **Relevant tools:** [`grep`](#grep), [`find`](#find)
503
-
504
- ### Edit and Refactor Code
505
-
506
- 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.
507
-
508
- **Relevant tools:** [`edit`](#edit), [`search_and_replace`](#search_and_replace), [`write`](#write)
509
-
510
- ### Diff and Patch Workflow
511
-
512
- Compare file versions and apply patches. Generate a unified diff with `diff_files`, preview with `apply_patch(dryRun: true)`, then apply. Supports both single-file and multi-file patches (best-effort per file with per-file `results[]`).
513
-
514
- **Relevant tools:** [`diff_files`](#diff_files), [`apply_patch`](#apply_patch)
515
453
 
516
- ### File Management
454
+ const eventBus = new RedisServerEventBus();
455
+ const apiKey = process.env['FS_API_KEY'];
456
+ if (!apiKey) throw new Error('FS_API_KEY is required for a multi-instance HTTP deployment');
517
457
 
518
- Create directories, move/rename files, delete files, and verify file integrity via SHA-256 hashing.
519
-
520
- **Relevant tools:** [`mkdir`](#mkdir), [`mv`](#mv), [`rm`](#rm), [`calculate_hash`](#calculate_hash), [`write`](#write)
521
-
522
- ## Architecture
523
-
524
- ```text
525
- [MCP Client]
526
- |
527
- | Transport: stdio (default) or Node Streamable HTTP (--port)
528
- v
529
- [MCP Server: filesystem-mcp]
530
- | Entry: src/index.ts -> src/server/bootstrap.ts
531
- |
532
- +-- initialize / initialized
533
- |
534
- +-- tools/call ──────────────────────────────────────────
535
- | +-- [roots] — List allowed workspace roots
536
- | +-- [ls] — List directory contents
537
- | +-- [find] — Find files by glob
538
- | +-- [tree] — Render directory tree
539
- | +-- [read] — Read file contents
540
- | +-- [read_many] — Read multiple files
541
- | +-- [stat] — Get file metadata
542
- | +-- [stat_many] — Get multiple file metadata
543
- | +-- [grep] — Search file contents
544
- | +-- [mkdir] — Create directory
545
- | +-- [write] — Write file
546
- | +-- [edit] — Edit file (string replacements)
547
- | +-- [mv] — Move/rename file
548
- | +-- [rm] — Delete file
549
- | +-- [calculate_hash] — SHA-256 hash
550
- | +-- [diff_files] — Unified diff
551
- | +-- [apply_patch] — Apply unified patch
552
- | +-- [search_and_replace]— Bulk search & replace
553
- |
554
- +-- resources/read ──────────────────────────────────────
555
- | +-- internal://instructions
556
- | +-- internal://tool-catalog
557
- | +-- internal://workflows
558
- | +-- internal://tool-info/{name}
559
- | +-- filesystem-mcp://result/{id}
560
- | +-- filesystem-mcp://metrics
561
- |
562
- +-- prompts/get ─────────────────────────────────────────
563
- | +-- get-help (optional topic argument)
564
- | +-- compare-files (original, modified)
565
- | +-- analyze-path (path)
566
- | +-- get-tool-help (name)
567
- |
568
- +-- Capabilities: logging, resources, tools, prompts, completions, tasks
569
- ```
570
-
571
- ### Request Lifecycle
572
-
573
- ```text
574
- [Client] -- initialize {protocolVersion, capabilities} --> [Server]
575
- [Server] -- {protocolVersion, capabilities, serverInfo} --> [Client]
576
- [Client] -- notifications/initialized --> [Server]
577
- [Client] -- tools/call {name, arguments} --> [Server]
578
- [Server] -- validate(inputSchema) --> [Handler]
579
- [Handler] -- {content: [{type, text}], structuredContent?, isError?} --> [Client]
458
+ await startHttpServer(
459
+ 3000,
460
+ { cliAllowedDirs: ['/workspace'] },
461
+ { apiKey, eventBus, deploymentMode: 'fleet' },
462
+ );
580
463
  ```
581
464
 
582
- ## MCP Surface
583
-
584
- ### Tools
585
-
586
- [`roots`](#roots) · [`ls`](#ls) · [`find`](#find) · [`tree`](#tree) · [`read`](#read) · [`read_many`](#read_many) · [`stat`](#stat) · [`stat_many`](#stat_many) · [`grep`](#grep) · [`mkdir`](#mkdir) · [`write`](#write) · [`edit`](#edit) · [`mv`](#mv) · [`rm`](#rm) · [`calculate_hash`](#calculate_hash) · [`diff_files`](#diff_files) · [`apply_patch`](#apply_patch) · [`search_and_replace`](#search_and_replace)
587
-
588
- #### `roots`
589
-
590
- List allowed workspace roots. Call first — all other tools are scoped to these directories.
591
-
592
- _No parameters._
593
-
594
- ---
595
-
596
- #### `ls`
597
-
598
- List immediate directory contents: name, path, type, size, modified date.
599
-
600
- | Parameter | Type | Required | Description |
601
- | ----------------------- | ------- | -------- | --------------------------------------------------------------------------- |
602
- | `path` | string | no | Base directory (default: root) |
603
- | `includeHidden` | boolean | no | Include dotfiles. Default: `false` |
604
- | `includeIgnored` | boolean | no | Include ignored items (node_modules, .git). Default: `false` |
605
- | `maxDepth` | integer | no | Max recursion depth (1-50) when pattern is provided |
606
- | `maxEntries` | integer | no | Max entries before truncation. Default: 20000, Max: 20000 |
607
- | `sortBy` | enum | no | `name` \| `size` \| `modified` \| `type`. Default: `name` |
608
- | `pattern` | string | no | Relative glob filter (e.g. `**/*.ts`). Absolute paths and `..` are rejected |
609
- | `includeSymlinkTargets` | boolean | no | Resolve symlink targets. Default: `false` |
610
- | `cursor` | string | no | Pagination cursor from a previous response |
611
-
612
- ---
613
-
614
- #### `find`
615
-
616
- Find files by glob pattern. Returns matching files with metadata.
617
-
618
- | Parameter | Type | Required | Description |
619
- | ---------------- | ------- | -------- | ---------------------------------------------------------------------------- |
620
- | `path` | string | no | Base directory (default: root) |
621
- | `pattern` | string | **yes** | Relative glob pattern (e.g. `**/*.ts`). Absolute paths and `..` are rejected |
622
- | `maxResults` | integer | no | Max results (1-10000). Default: 100 |
623
- | `includeIgnored` | boolean | no | Include ignored items. Default: `false` |
624
- | `includeHidden` | boolean | no | Include dotfiles. Default: `false` |
625
- | `sortBy` | enum | no | `path` \| `name` \| `size` \| `modified`. Default: `path` |
626
- | `maxDepth` | integer | no | Max directory depth (0-100) |
627
- | `cursor` | string | no | Pagination cursor |
628
-
629
- ---
630
-
631
- #### `tree`
632
-
633
- Render a directory tree with bounded recursion. Returns ASCII tree + structured JSON.
634
-
635
- | Parameter | Type | Required | Description |
636
- | ---------------- | ------- | -------- | ---------------------------------------------------- |
637
- | `path` | string | no | Base directory (default: root) |
638
- | `maxDepth` | integer | no | Depth (0 = root node only). Default: 5, Max: 50 |
639
- | `maxEntries` | integer | no | Max entries. Default: 1000, Max: 20000 |
640
- | `includeHidden` | boolean | no | Include dotfiles. Default: `false` |
641
- | `includeIgnored` | boolean | no | Include ignored items. Default: `false` |
642
- | `includeSizes` | boolean | no | Include file sizes in tree entries. Default: `false` |
643
-
644
- ---
645
-
646
- #### `read`
647
-
648
- Read text file contents. Use `head`/`tail` to preview first/last N lines of large files.
649
-
650
- | Parameter | Type | Required | Description |
651
- | ------------- | ------- | -------- | ----------------------------------------------------------- |
652
- | `path` | string | **yes** | Absolute path to file |
653
- | `head` | integer | no | Read first N lines (1-100000) |
654
- | `tail` | integer | no | Read last N lines (1-100000) |
655
- | `startLine` | integer | no | Start line (1-based, inclusive) |
656
- | `endLine` | integer | no | End line (1-based, inclusive). Requires `startLine` |
657
- | `includeHash` | boolean | no | Include SHA-256 hash of full file content. Default: `false` |
658
-
659
- ---
660
-
661
- #### `read_many`
662
-
663
- Read multiple text files in one request.
664
-
665
- | Parameter | Type | Required | Description |
666
- | ----------- | -------- | -------- | ------------------------------- |
667
- | `paths` | string[] | **yes** | Files to read (1-100 paths) |
668
- | `head` | integer | no | Read first N lines of each file |
669
- | `tail` | integer | no | Read last N lines of each file |
670
- | `startLine` | integer | no | Start line (1-based) per file |
671
- | `endLine` | integer | no | End line (1-based) per file |
672
-
673
- ---
674
-
675
- #### `stat`
676
-
677
- Get file/directory metadata: size, modified, permissions, mime, tokenEstimate.
678
-
679
- | Parameter | Type | Required | Description |
680
- | --------- | ------ | -------- | ---------------------------------- |
681
- | `path` | string | **yes** | Absolute path to file or directory |
682
-
683
- ---
684
-
685
- #### `stat_many`
686
-
687
- Get metadata for multiple files/directories in one request.
688
-
689
- | Parameter | Type | Required | Description |
690
- | --------- | -------- | -------- | ---------------------------- |
691
- | `paths` | string[] | **yes** | File/directory paths (1-100) |
692
-
693
- ---
694
-
695
- #### `grep`
696
-
697
- Search file contents (grep-like). Returns matching lines with optional context.
698
-
699
- | Parameter | Type | Required | Description |
700
- | ---------------- | ------- | -------- | ------------------------------------------------------------------- |
701
- | `path` | string | no | Base directory (default: root) |
702
- | `pattern` | string | **yes** | Search text or RE2 regex when `isRegex=true` |
703
- | `isRegex` | boolean | no | Treat pattern as RE2 regex. Default: `false` |
704
- | `caseSensitive` | boolean | no | Case-sensitive matching. Default: `false` |
705
- | `wholeWord` | boolean | no | Match whole words only. Default: `false` |
706
- | `contextLines` | integer | no | Lines of context before/after (0-50). Default: 0 |
707
- | `maxResults` | integer | no | Max match rows (0-10000). Default: 500 |
708
- | `filePattern` | string | no | Relative glob for candidate files (e.g. `**/*.ts`). Default: `**/*` |
709
- | `includeHidden` | boolean | no | Include dotfiles. Default: `false` |
710
- | `includeIgnored` | boolean | no | Include ignored items. Default: `false` |
711
-
712
- ---
713
-
714
- #### `mkdir`
465
+ This project ships no bus adapter and no pub/sub dependency. A single
466
+ in-process instance (the common case) needs nothing extra and is the CLI's
467
+ default. Load-balanced deployments must use the programmatic API with
468
+ `deploymentMode: 'fleet'`.
715
469
 
716
- Create a new directory (recursive). Idempotent.
470
+ ### Examples
717
471
 
718
- | Parameter | Type | Required | Description |
719
- | --------- | -------- | -------- | ----------------------------------------------------------------- |
720
- | `path` | string | no | Absolute path to directory to create |
721
- | `paths` | string[] | no | Multiple directories to create. Either `path` or `paths` required |
722
-
723
- ---
724
-
725
- #### `write`
726
-
727
- Write content to a file, **overwriting all existing content**. Creates parent directories if needed.
728
-
729
- | Parameter | Type | Required | Description |
730
- | --------- | ------ | -------- | --------------------- |
731
- | `path` | string | **yes** | Absolute path to file |
732
- | `content` | string | **yes** | Content to write |
733
-
734
- ---
735
-
736
- #### `edit`
737
-
738
- Apply sequential literal string replacements (first occurrence per edit). Use `dryRun` to preview.
739
-
740
- | Parameter | Type | Required | Description |
741
- | ------------------ | ------- | -------- | ---------------------------------------------------------- |
742
- | `path` | string | **yes** | Absolute path to file |
743
- | `edits` | array | **yes** | List of non-empty `{oldText, newText}` replacements |
744
- | `dryRun` | boolean | no | Preview edits without writing. Default: `false` |
745
- | `ignoreWhitespace` | boolean | no | Treat whitespace sequences as equivalent. Default: `false` |
746
-
747
- ---
748
-
749
- #### `mv`
750
-
751
- Move or rename a file or directory.
752
-
753
- | Parameter | Type | Required | Description |
754
- | ------------- | -------- | -------- | ---------------------------------------------------- |
755
- | `source` | string | no | Single path to move (deprecated: use `sources`) |
756
- | `sources` | string[] | no | Paths to move. Either `source` or `sources` required |
757
- | `destination` | string | **yes** | Destination path |
758
-
759
- ---
760
-
761
- #### `rm`
762
-
763
- Permanently delete a file or directory. **Irreversible.**
764
-
765
- | Parameter | Type | Required | Description |
766
- | ------------------- | ------- | -------- | ---------------------------------------------- |
767
- | `path` | string | **yes** | Absolute path to file or directory |
768
- | `recursive` | boolean | no | Delete non-empty directories. Default: `false` |
769
- | `ignoreIfNotExists` | boolean | no | No error if missing. Default: `false` |
770
-
771
- ---
772
-
773
- #### `calculate_hash`
774
-
775
- Calculate SHA-256 hash of a file or directory.
776
-
777
- | Parameter | Type | Required | Description |
778
- | --------- | ------ | -------- | ---------------------------------- |
779
- | `path` | string | **yes** | Absolute path to file or directory |
780
-
781
- ---
782
-
783
- #### `diff_files`
784
-
785
- Generate a unified diff between two files. Output feeds directly into `apply_patch`.
786
-
787
- | Parameter | Type | Required | Description |
788
- | ------------------ | ------- | -------- | ---------------------------------------------------- |
789
- | `original` | string | **yes** | Path to original file |
790
- | `modified` | string | **yes** | Path to modified file |
791
- | `context` | integer | no | Lines of context in diff output |
792
- | `ignoreWhitespace` | boolean | no | Ignore leading/trailing whitespace. Default: `false` |
793
- | `stripTrailingCr` | boolean | no | Strip trailing carriage returns. Default: `false` |
794
-
795
- ---
796
-
797
- #### `apply_patch`
798
-
799
- Apply a unified diff patch to one or more files. Single-file: throws on failure. Multi-file: best-effort per file with `results[]`. Workflow: `diff_files` -> `apply_patch(dryRun)` -> `apply_patch`.
800
-
801
- | Parameter | Type | Required | Description |
802
- | ------------------------ | ------- | -------- | ---------------------------------------------------------- |
803
- | `path` | string | **yes** | Path to file (single) or base directory (multi-file patch) |
804
- | `patch` | string | **yes** | Unified diff with `@@` hunk headers (single or multi-file) |
805
- | `fuzzFactor` | integer | no | Max fuzzy mismatches per hunk (0-20) |
806
- | `autoConvertLineEndings` | boolean | no | Auto-convert line endings. Default: `true` |
807
- | `dryRun` | boolean | no | Validate without writing. Default: `false` |
808
-
809
- ---
810
-
811
- #### `search_and_replace`
812
-
813
- Bulk search-and-replace across files matching a glob. Replaces **all** occurrences per file. Always `dryRun: true` first.
814
-
815
- | Parameter | Type | Required | Description |
816
- | ---------------- | ------- | -------- | ------------------------------------------------------- |
817
- | `path` | string | no | Base directory (default: root) |
818
- | `filePattern` | string | no | Relative glob pattern (e.g. `**/*.ts`). Default: `**/*` |
819
- | `searchPattern` | string | **yes** | Text to search. RE2 regex when `isRegex=true` |
820
- | `replacement` | string | **yes** | Replacement text. Supports `$1`, `$2` with regex |
821
- | `isRegex` | boolean | no | Treat as RE2 regex. Default: `false` |
822
- | `dryRun` | boolean | no | Preview matches with diff. Default: `false` |
823
- | `includeHidden` | boolean | no | Include dotfiles. Default: `false` |
824
- | `includeIgnored` | boolean | no | Include ignored items. Default: `false` |
825
- | `returnDiff` | boolean | no | Return diff even when not dry-run. Default: `false` |
826
- | `maxFiles` | integer | no | Max files to process before stopping (1-10000) |
827
- | `caseSensitive` | boolean | no | Case-sensitive matching. Default: `true` |
828
-
829
- ### Resources
830
-
831
- | Resource | URI | MIME Type | Description |
832
- | ------------ | ------------------------------ | ---------------- | ------------------------------------------------------------------ |
833
- | Instructions | `internal://instructions` | text/markdown | Comprehensive usage rules and guidelines |
834
- | Tool Catalog | `internal://tool-catalog` | text/markdown | Tool selection guide and data flow map |
835
- | Workflows | `internal://workflows` | text/markdown | Standard operating procedures for exploration, search, edit, patch |
836
- | Tool Info | `internal://tool-info/{name}` | text/markdown | Per-tool contract details, nuances, gotchas |
837
- | Result Cache | `filesystem-mcp://result/{id}` | text/plain | Ephemeral cached tool output (large results externalized here) |
838
- | Metrics | `filesystem-mcp://metrics` | application/json | Live per-tool call/error/avgDurationMs snapshot |
839
-
840
- ### Prompts
841
-
842
- | Prompt | Arguments | Description |
843
- | --------------- | ---------------------- | ---------------------------------------------------------------------- |
844
- | `get-help` | `topic` (optional) | Return usage instructions. Optionally filter by section heading prefix |
845
- | `compare-files` | `original`, `modified` | Generate a workflow for comparing two files using `diff_files` |
846
- | `analyze-path` | `path` | Generate a workflow for analyzing a file or directory |
847
- | `get-tool-help` | `name` | Return a prompt with the authoritative contract for a specific tool |
848
-
849
- ## MCP Capabilities
850
-
851
- | Capability | Status | Evidence |
852
- | ------------- | --------- | -------------------------------------------------------------------------- |
853
- | `logging` | confirmed | `src/server/bootstrap.ts` — registered in capabilities |
854
- | `resources` | confirmed | `src/server/bootstrap.ts` — 6 resources registered |
855
- | `tools` | confirmed | `src/server/bootstrap.ts` — 18 tools registered |
856
- | `prompts` | confirmed | `src/server/bootstrap.ts` — 4 prompts registered |
857
- | `completions` | confirmed | `src/completions.ts` — path, topic, and tool-name auto-completion |
858
- | `tasks` | confirmed | `src/server/bootstrap.ts` — optional task support (list, cancel, requests) |
859
-
860
- ### Tool Annotations
861
-
862
- | Annotation | Tools | Value |
863
- | ----------------------- | --------------------------------------------------------------------------------------------------------------- | -------------------------------------- |
864
- | `readOnlyHint: true` | `roots`, `ls`, `find`, `tree`, `read`, `read_many`, `stat`, `stat_many`, `grep`, `calculate_hash`, `diff_files` | Read-only, idempotent, non-destructive |
865
- | `destructiveHint: true` | `write`, `edit`, `rm`, `mv`, `search_and_replace`, `apply_patch` | Destructive writes, not idempotent |
866
- | `idempotentHint: true` | `mkdir` | Idempotent write, non-destructive |
867
-
868
- ### Structured Output
869
-
870
- 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).
871
-
872
- [↑ Back to top](#table-of-contents)
873
-
874
- ## Configuration
875
-
876
- ### HTTP & Auth
877
-
878
- | Variable | Default | Description |
879
- | ---------------------------------- | ---------------- | -------------------------------------------------------------- |
880
- | `FILESYSTEM_MCP_API_KEY` | _(none)_ | Bearer token required when binding HTTP to a non-loopback host |
881
- | `FILESYSTEM_MCP_MAX_HTTP_SESSIONS` | `100` | Max concurrent HTTP sessions (1-10,000) |
882
- | `FILESYSTEM_MCP_HTTP_HOST` | `127.0.0.1` | HTTP server bind address |
883
- | `FS_CONTEXT_MAX_REQUEST_BYTES` | `4194304` (4 MB) | Max HTTP request body size (1 KB - 256 MB) |
884
-
885
- ### File Size Limits
886
-
887
- | Variable | Default | Description |
888
- | -------------------------- | ------------------ | ------------------------------------------------------------- |
889
- | `MAX_FILE_SIZE` | `10485760` (10 MB) | Max file size for text read operations (1 MB - 100 MB) |
890
- | `MAX_SEARCH_SIZE` | `1048576` (1 MB) | Max file size for content search/grep (100 KB - 10 MB) |
891
- | `MAX_READ_MANY_TOTAL_SIZE` | `524288` (512 KB) | Max cumulative size for `read_many` requests (10 KB - 100 MB) |
892
- | `DEFAULT_SEARCH_TIMEOUT` | `5000` | Search operation timeout in ms (100 - 60,000) |
893
-
894
- ### Access Control
895
-
896
- | Variable | Default | Description |
897
- | ---------------------------- | -------- | ------------------------------------------------------------------------------- |
898
- | `FS_CONTEXT_ALLOW_SENSITIVE` | `false` | Allow reading sensitive files (.env, .key, credentials, tokens) |
899
- | `FS_CONTEXT_DENYLIST` | _(none)_ | CSV/newline-separated glob patterns to block (in addition to built-in denylist) |
900
- | `FS_CONTEXT_ALLOWLIST` | _(none)_ | CSV/newline-separated glob patterns to permit (overrides denylist) |
901
-
902
- ### Output & Inline Limits
903
-
904
- | Variable | Default | Description |
905
- | ------------------------------- | ------- | ------------------------------------------------------------------------------ |
906
- | `FS_CONTEXT_MAX_INLINE_CHARS` | `20000` | Max inline result chars before externalizing to `filesystem-mcp://result/{id}` |
907
- | `FS_CONTEXT_MAX_INLINE_MATCHES` | `50` | Max inline search matches before truncation |
908
- | `FS_CONTEXT_STRIP_STRUCTURED` | `false` | Strip `outputSchema` from tool definitions (reduces tokens) |
909
-
910
- ### Tasks
911
-
912
- | Variable | Default | Description |
913
- | ------------------------------------- | ---------------- | ----------------------------------------------- |
914
- | `FILESYSTEM_MCP_MAX_TASK_TTL_MS` | `3600000` (1 hr) | Max task TTL before auto-eviction (1 s - 24 hr) |
915
- | `FILESYSTEM_MCP_MAX_CONCURRENT_TASKS` | `100` | Max simultaneous task executions (1-10,000) |
916
-
917
- ### Logging & Diagnostics
918
-
919
- | Variable | Default | Description |
920
- | --------------------------------- | ------- | ------------------------------------------------------------------------------ |
921
- | `FILESYSTEM_MCP_LOG_LEVEL` | `info` | MCP log level: debug, info, notice, warning, error, critical, alert, emergency |
922
- | `FS_CONTEXT_DIAGNOSTICS` | `false` | Enable diagnostic logging |
923
- | `FS_CONTEXT_DIAGNOSTICS_DETAIL` | `false` | Enable detailed diagnostic output |
924
- | `FS_CONTEXT_TOOL_LOG_ERRORS` | `false` | Log tool errors to stderr |
925
- | `FS_CONTEXT_SEARCH_WORKERS_DEBUG` | `false` | Debug logging for search worker pool |
926
-
927
- ### Performance
928
-
929
- | Variable | Default | Description |
930
- | ------------------------------- | ---------------- | ---------------------------------------- |
931
- | `FS_CONTEXT_SEARCH_WORKERS` | CPU cores (≤ 8) | Concurrent search worker threads (1-16) |
932
- | `FS_CONTEXT_LIST_CURSOR_TTL_MS` | `300000` (5 min) | Cursor TTL for `ls` pagination snapshots |
933
-
934
- [↑ Back to top](#table-of-contents)
935
-
936
- ## HTTP Endpoints
472
+ ```bash
473
+ # Allow current working directory
474
+ filesystem-mcp --allow-cwd
937
475
 
938
- When started with `--port <number>`, the server exposes a single MCP endpoint:
476
+ # HTTP transport on port 3000
477
+ filesystem-mcp --port 3000
478
+ ```
939
479
 
940
- | Method | Path | Purpose |
941
- | -------- | ------ | ----------------------------------------------------- |
942
- | `POST` | `/mcp` | Initialize session or send requests (Streamable HTTP) |
943
- | `GET` | `/mcp` | HTTP streaming session endpoint |
944
- | `DELETE` | `/mcp` | Terminate a session |
480
+ ## Scripts
945
481
 
946
- **Required headers:**
482
+ | Mode | Command | Description |
483
+ | :--------------- | :------------------------------- | :--------------------------------------------------- |
484
+ | Full check | `node scripts/tasks.mjs` | Run build, type check, lint, format, knip, and tests |
485
+ | Auto-fix + check | `node scripts/tasks.mjs fix` | Auto-fix formatting/linting and run the full check |
486
+ | Static only | `node scripts/tasks.mjs --quick` | Run static analysis without tests |
487
+ | Tests only | `node scripts/tasks.mjs test` | Run tests; accepts native `node --test` options |
947
488
 
948
- - `mcp-protocol-version` — use the negotiated MCP protocol version on post-initialize HTTP requests
949
- - `mcp-session-id` — required for `GET`/`DELETE` (returned by `POST` on initialize)
489
+ ## Security
950
490
 
951
- **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.
491
+ > [!IMPORTANT]
492
+ > Report vulnerabilities privately via [GitHub Security Advisories](https://github.com/j0hanz/filesystem-mcp/security/advisories). Do not open public issues for security reports.
952
493
 
953
- **CORS:** Only localhost origins allowed (`127.0.0.1`, `::1`, `localhost`).
494
+ | Topic | Detail |
495
+ | :-------------- | :------------------------------------------------------------------------------ |
496
+ | Path traversal | Every path is resolved and validated against allowed roots before any operation |
497
+ | Sensitive files | `.env`, `*.pem`, `*id_rsa*`, and similar patterns are denied by default |
498
+ | Regex safety | RE2 cannot backtrack, so a hostile pattern cannot hang the server (ReDoS) |
499
+ | Container | Runs as non-root `mcp` user; bind mounts control what is exposed |
954
500
 
955
- **Host validation:** Loopback HTTP binds validate the `Host` header (`localhost`, `127.0.0.1`, `[::1]`) to reduce DNS rebinding risk. Non-loopback binds still require `FILESYSTEM_MCP_API_KEY`.
501
+ ## Contributing
956
502
 
957
- ## Security
503
+ 1. Fork the repository.
504
+ 2. Create a feature branch: `git checkout -b feat/your-feature`.
505
+ 3. Commit your changes with a clear message.
506
+ 4. Run `node scripts/tasks.mjs` to confirm tests, types, lint, formatting, and knip all pass.
507
+ 5. Open a pull request.
958
508
 
959
- | Control | Status | Evidence |
960
- | ------------------------- | --------- | -------------------------------------------------------------------------------------- |
961
- | Path sandboxing | confirmed | `src/lib/paths.ts` — all paths validated against allowed roots |
962
- | Traversal prevention | confirmed | `src/lib/paths.ts` — resolved paths checked after normalization |
963
- | Symlink escape prevention | confirmed | `src/__tests__/security.test.ts` — symlink boundary enforcement |
964
- | Sensitive file denylist | confirmed | `src/lib/constants.ts` — blocks `.git`, `.env*`, SSH keys, certs, secrets |
965
- | Origin validation | confirmed | `src/server/bootstrap.ts` — localhost-only Origin allowlist |
966
- | Bearer auth | confirmed | `src/server/bootstrap.ts` — optional `FILESYSTEM_MCP_API_KEY` with timing-safe compare |
967
- | Input validation | confirmed | `src/schemas.ts` — Zod strict schemas on all tool inputs |
968
- | Request body limit | confirmed | `src/server/bootstrap.ts` — configurable max request size (413 on overflow) |
969
- | Remote bind guard | confirmed | `src/server/bootstrap.ts` — refuses non-loopback bind without `FILESYSTEM_MCP_API_KEY` |
970
-
971
- [↑ Back to top](#table-of-contents)
972
-
973
- ## Development
974
-
975
- - `dev` — `tsc --watch --preserveWatchOutput` — Watch mode TypeScript compilation
976
- - `dev:run` — `node --env-file=.env --watch dist/index.js` — Run server with auto-reload
977
- - `start` — `node dist/index.js` — Run production server
978
- - `build` — `node scripts/tasks.mjs build` — Clean build
979
- - `test` — `node scripts/tasks.mjs test` — Build + run all tests
980
- - `test:fast` — `node --test --import tsx/esm src/__tests__/**/*.test.ts node-tests/**/*.test.ts` — Run tests without build
981
- - `lint` — `eslint .` — Lint source
982
- - `type-check` — `node scripts/tasks.mjs type-check` — Type-check src + tests
983
- - `format` — `prettier --write .` — Format code
984
- - `inspector` — `npm run build && npx -y @modelcontextprotocol/inspector node dist/index.js ${workspaceFolder}` — Launch MCP Inspector
985
-
986
- ## Build and Release
987
-
988
- - **CI:** `.github/workflows/release.yml` — runs lint, type-check, test, build before tagging/publishing.
989
- - **Docker:** Multi-stage build with `node:24-alpine`. Builder compiles TypeScript + native modules (re2); release stage runs as non-root `mcp` user.
990
- - **npm:** `npm run prepublishOnly` runs lint + type-check + build.
991
-
992
- ## Troubleshooting
993
-
994
- - **"No allowed directories"** — Pass at least one directory argument or use `--allow-cwd`.
995
- - **Sensitive file blocked** — Files matching the denylist (`.env*`, `.git`, SSH keys) are blocked by design. Check `src/lib/constants.ts` for the full list.
996
- - **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.
997
- - **Stdio: logs on stdout** — Keep logs on stderr only. The server uses `console.error` for diagnostics.
998
- - **HTTP 413** — Request body exceeds `FS_CONTEXT_MAX_REQUEST_BYTES`. Increase the limit or reduce payload size.
999
- - **HTTP 401** — `FILESYSTEM_MCP_API_KEY` is set but the request is missing or has an incorrect `Authorization: Bearer` header.
1000
-
1001
- ## Credits
1002
-
1003
- | Dependency | Description |
1004
- | ------------------------------------------------------------------------------------------ | --------------------------------------------- |
1005
- | [@modelcontextprotocol/server](https://www.npmjs.com/package/@modelcontextprotocol/server) | MCP server SDK package |
1006
- | [@modelcontextprotocol/client](https://www.npmjs.com/package/@modelcontextprotocol/client) | MCP client SDK package |
1007
- | [@modelcontextprotocol/node](https://www.npmjs.com/package/@modelcontextprotocol/node) | Node transport package for MCP runtime |
1008
- | [commander](https://www.npmjs.com/package/commander) | CLI argument parsing |
1009
- | [diff](https://www.npmjs.com/package/diff) | Unified diff generation and patch application |
1010
- | [ignore](https://www.npmjs.com/package/ignore) | `.gitignore` pattern matching |
1011
- | [re2](https://www.npmjs.com/package/re2) | Safe RE2 regex engine (no ReDoS) |
1012
- | [zod](https://www.npmjs.com/package/zod) | Schema validation and JSON Schema generation |
509
+ [![Contributors](https://contrib.rocks/image?repo=j0hanz/filesystem-mcp)](https://github.com/j0hanz/filesystem-mcp/graphs/contributors)
1013
510
 
1014
511
  ## License
1015
512
 
1016
- MIT License. See [LICENSE](LICENSE) for details.
1017
-
1018
- [↑ Back to top](#table-of-contents)
513
+ Released under the MIT License. See [LICENSE](LICENSE) for details.