@j0hanz/filesystem-context-mcp 1.1.0 → 1.2.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 (305) hide show
  1. package/README.md +106 -29
  2. package/dist/__tests__/lib/errors.test.js +3 -23
  3. package/dist/__tests__/lib/errors.test.js.map +1 -1
  4. package/dist/__tests__/lib/file-operations.test.js +34 -0
  5. package/dist/__tests__/lib/file-operations.test.js.map +1 -1
  6. package/dist/__tests__/lib/path-validation.test.js +8 -0
  7. package/dist/__tests__/lib/path-validation.test.js.map +1 -1
  8. package/dist/__tests__/schemas/validators.test.js +101 -122
  9. package/dist/__tests__/schemas/validators.test.js.map +1 -1
  10. package/dist/__tests__/security/filesystem-boundary.test.js +1 -1
  11. package/dist/__tests__/security/filesystem-boundary.test.js.map +1 -1
  12. package/dist/config/types.d.ts +1 -85
  13. package/dist/config/types.d.ts.map +1 -1
  14. package/dist/config/types.js +0 -2
  15. package/dist/config/types.js.map +1 -1
  16. package/dist/index.js +3 -3
  17. package/dist/index.js.map +1 -1
  18. package/dist/instructions.md +1 -2
  19. package/dist/lib/constants.d.ts +3 -1
  20. package/dist/lib/constants.d.ts.map +1 -1
  21. package/dist/lib/constants.js +73 -259
  22. package/dist/lib/constants.js.map +1 -1
  23. package/dist/lib/errors.d.ts +25 -3
  24. package/dist/lib/errors.d.ts.map +1 -1
  25. package/dist/lib/errors.js +4 -94
  26. package/dist/lib/errors.js.map +1 -1
  27. package/dist/lib/file-operations/analyze-directory.d.ts +8 -0
  28. package/dist/lib/file-operations/analyze-directory.d.ts.map +1 -0
  29. package/dist/lib/file-operations/analyze-directory.js +117 -0
  30. package/dist/lib/file-operations/analyze-directory.js.map +1 -0
  31. package/dist/lib/file-operations/directory-helpers.d.ts +35 -0
  32. package/dist/lib/file-operations/directory-helpers.d.ts.map +1 -0
  33. package/dist/lib/file-operations/directory-helpers.js +136 -0
  34. package/dist/lib/file-operations/directory-helpers.js.map +1 -0
  35. package/dist/lib/file-operations/directory-items.d.ts +20 -0
  36. package/dist/lib/file-operations/directory-items.d.ts.map +1 -0
  37. package/dist/lib/file-operations/directory-items.js +85 -0
  38. package/dist/lib/file-operations/directory-items.js.map +1 -0
  39. package/dist/lib/file-operations/directory-iteration.d.ts +17 -0
  40. package/dist/lib/file-operations/directory-iteration.d.ts.map +1 -0
  41. package/dist/lib/file-operations/directory-iteration.js +55 -0
  42. package/dist/lib/file-operations/directory-iteration.js.map +1 -0
  43. package/dist/lib/file-operations/directory-tree.d.ts +9 -0
  44. package/dist/lib/file-operations/directory-tree.d.ts.map +1 -0
  45. package/dist/lib/file-operations/directory-tree.js +175 -0
  46. package/dist/lib/file-operations/directory-tree.js.map +1 -0
  47. package/dist/lib/file-operations/file-info.d.ts +3 -0
  48. package/dist/lib/file-operations/file-info.d.ts.map +1 -0
  49. package/dist/lib/file-operations/file-info.js +56 -0
  50. package/dist/lib/file-operations/file-info.js.map +1 -0
  51. package/dist/lib/file-operations/list-directory.d.ts +10 -0
  52. package/dist/lib/file-operations/list-directory.d.ts.map +1 -0
  53. package/dist/lib/file-operations/list-directory.js +189 -0
  54. package/dist/lib/file-operations/list-directory.js.map +1 -0
  55. package/dist/lib/file-operations/pattern-complexity.d.ts +16 -0
  56. package/dist/lib/file-operations/pattern-complexity.d.ts.map +1 -0
  57. package/dist/lib/file-operations/pattern-complexity.js +86 -0
  58. package/dist/lib/file-operations/pattern-complexity.js.map +1 -0
  59. package/dist/lib/file-operations/pattern-validator.d.ts +15 -0
  60. package/dist/lib/file-operations/pattern-validator.d.ts.map +1 -0
  61. package/dist/lib/file-operations/pattern-validator.js +69 -0
  62. package/dist/lib/file-operations/pattern-validator.js.map +1 -0
  63. package/dist/lib/file-operations/read-media-file.d.ts +5 -0
  64. package/dist/lib/file-operations/read-media-file.d.ts.map +1 -0
  65. package/dist/lib/file-operations/read-media-file.js +31 -0
  66. package/dist/lib/file-operations/read-media-file.js.map +1 -0
  67. package/dist/lib/file-operations/read-multiple-files.d.ts +16 -0
  68. package/dist/lib/file-operations/read-multiple-files.d.ts.map +1 -0
  69. package/dist/lib/file-operations/read-multiple-files.js +100 -0
  70. package/dist/lib/file-operations/read-multiple-files.js.map +1 -0
  71. package/dist/lib/file-operations/search-content.d.ts +18 -0
  72. package/dist/lib/file-operations/search-content.d.ts.map +1 -0
  73. package/dist/lib/file-operations/search-content.js +436 -0
  74. package/dist/lib/file-operations/search-content.js.map +1 -0
  75. package/dist/lib/file-operations/search-files.d.ts +11 -0
  76. package/dist/lib/file-operations/search-files.d.ts.map +1 -0
  77. package/dist/lib/file-operations/search-files.js +143 -0
  78. package/dist/lib/file-operations/search-files.js.map +1 -0
  79. package/dist/lib/file-operations/sorting.d.ts +12 -0
  80. package/dist/lib/file-operations/sorting.d.ts.map +1 -0
  81. package/dist/lib/file-operations/sorting.js +24 -0
  82. package/dist/lib/file-operations/sorting.js.map +1 -0
  83. package/dist/lib/file-operations.d.ts +9 -57
  84. package/dist/lib/file-operations.d.ts.map +1 -1
  85. package/dist/lib/file-operations.js +9 -773
  86. package/dist/lib/file-operations.js.map +1 -1
  87. package/dist/lib/fs-helpers/binary-detect.d.ts +3 -0
  88. package/dist/lib/fs-helpers/binary-detect.d.ts.map +1 -0
  89. package/dist/lib/fs-helpers/binary-detect.js +54 -0
  90. package/dist/lib/fs-helpers/binary-detect.js.map +1 -0
  91. package/dist/lib/fs-helpers/concurrency.d.ts +11 -0
  92. package/dist/lib/fs-helpers/concurrency.d.ts.map +1 -0
  93. package/dist/lib/fs-helpers/concurrency.js +95 -0
  94. package/dist/lib/fs-helpers/concurrency.js.map +1 -0
  95. package/dist/lib/fs-helpers/fs-utils.d.ts +5 -0
  96. package/dist/lib/fs-helpers/fs-utils.d.ts.map +1 -0
  97. package/dist/lib/fs-helpers/fs-utils.js +13 -0
  98. package/dist/lib/fs-helpers/fs-utils.js.map +1 -0
  99. package/dist/lib/fs-helpers/readers/head-file.d.ts +2 -0
  100. package/dist/lib/fs-helpers/readers/head-file.d.ts.map +1 -0
  101. package/dist/lib/fs-helpers/readers/head-file.js +73 -0
  102. package/dist/lib/fs-helpers/readers/head-file.js.map +1 -0
  103. package/dist/lib/fs-helpers/readers/line-range.d.ts +7 -0
  104. package/dist/lib/fs-helpers/readers/line-range.d.ts.map +1 -0
  105. package/dist/lib/fs-helpers/readers/line-range.js +46 -0
  106. package/dist/lib/fs-helpers/readers/line-range.js.map +1 -0
  107. package/dist/lib/fs-helpers/readers/read-file.d.ts +16 -0
  108. package/dist/lib/fs-helpers/readers/read-file.d.ts.map +1 -0
  109. package/dist/lib/fs-helpers/readers/read-file.js +87 -0
  110. package/dist/lib/fs-helpers/readers/read-file.js.map +1 -0
  111. package/dist/lib/fs-helpers/readers/stream-lines.d.ts +7 -0
  112. package/dist/lib/fs-helpers/readers/stream-lines.d.ts.map +1 -0
  113. package/dist/lib/fs-helpers/readers/stream-lines.js +61 -0
  114. package/dist/lib/fs-helpers/readers/stream-lines.js.map +1 -0
  115. package/dist/lib/fs-helpers/readers/tail-file.d.ts +2 -0
  116. package/dist/lib/fs-helpers/readers/tail-file.d.ts.map +1 -0
  117. package/dist/lib/fs-helpers/readers/tail-file.js +98 -0
  118. package/dist/lib/fs-helpers/readers/tail-file.js.map +1 -0
  119. package/dist/lib/fs-helpers/readers/utf8.d.ts +3 -0
  120. package/dist/lib/fs-helpers/readers/utf8.d.ts.map +1 -0
  121. package/dist/lib/fs-helpers/readers/utf8.js +22 -0
  122. package/dist/lib/fs-helpers/readers/utf8.js.map +1 -0
  123. package/dist/lib/fs-helpers/readers.d.ts +4 -0
  124. package/dist/lib/fs-helpers/readers.d.ts.map +1 -0
  125. package/dist/lib/fs-helpers/readers.js +4 -0
  126. package/dist/lib/fs-helpers/readers.js.map +1 -0
  127. package/dist/lib/fs-helpers.d.ts +4 -25
  128. package/dist/lib/fs-helpers.d.ts.map +1 -1
  129. package/dist/lib/fs-helpers.js +4 -327
  130. package/dist/lib/fs-helpers.js.map +1 -1
  131. package/dist/lib/path-validation/allowed-directories.d.ts +9 -0
  132. package/dist/lib/path-validation/allowed-directories.d.ts.map +1 -0
  133. package/dist/lib/path-validation/allowed-directories.js +94 -0
  134. package/dist/lib/path-validation/allowed-directories.js.map +1 -0
  135. package/dist/lib/path-validation/errors.d.ts +5 -0
  136. package/dist/lib/path-validation/errors.d.ts.map +1 -0
  137. package/dist/lib/path-validation/errors.js +33 -0
  138. package/dist/lib/path-validation/errors.js.map +1 -0
  139. package/dist/lib/path-validation/roots.d.ts +3 -0
  140. package/dist/lib/path-validation/roots.d.ts.map +1 -0
  141. package/dist/lib/path-validation/roots.js +49 -0
  142. package/dist/lib/path-validation/roots.js.map +1 -0
  143. package/dist/lib/path-validation/validators.d.ts +9 -0
  144. package/dist/lib/path-validation/validators.d.ts.map +1 -0
  145. package/dist/lib/path-validation/validators.js +70 -0
  146. package/dist/lib/path-validation/validators.js.map +1 -0
  147. package/dist/lib/path-validation.d.ts +3 -7
  148. package/dist/lib/path-validation.d.ts.map +1 -1
  149. package/dist/lib/path-validation.js +3 -141
  150. package/dist/lib/path-validation.js.map +1 -1
  151. package/dist/lib/performance/monitor.d.ts +25 -0
  152. package/dist/lib/performance/monitor.d.ts.map +1 -0
  153. package/dist/lib/performance/monitor.js +84 -0
  154. package/dist/lib/performance/monitor.js.map +1 -0
  155. package/dist/schemas/input-helpers.d.ts +27 -0
  156. package/dist/schemas/input-helpers.d.ts.map +1 -0
  157. package/dist/schemas/input-helpers.js +176 -0
  158. package/dist/schemas/input-helpers.js.map +1 -0
  159. package/dist/schemas/inputs.d.ts +14 -7
  160. package/dist/schemas/inputs.d.ts.map +1 -1
  161. package/dist/schemas/inputs.js +56 -228
  162. package/dist/schemas/inputs.js.map +1 -1
  163. package/dist/schemas/output-helpers.d.ts +24 -0
  164. package/dist/schemas/output-helpers.d.ts.map +1 -0
  165. package/dist/schemas/output-helpers.js +13 -0
  166. package/dist/schemas/output-helpers.js.map +1 -0
  167. package/dist/schemas/outputs.d.ts +476 -42
  168. package/dist/schemas/outputs.d.ts.map +1 -1
  169. package/dist/schemas/outputs.js +26 -41
  170. package/dist/schemas/outputs.js.map +1 -1
  171. package/dist/server.d.ts +9 -1
  172. package/dist/server.d.ts.map +1 -1
  173. package/dist/server.js +29 -45
  174. package/dist/server.js.map +1 -1
  175. package/dist/tools/analyze-directory.d.ts.map +1 -1
  176. package/dist/tools/analyze-directory.js +115 -53
  177. package/dist/tools/analyze-directory.js.map +1 -1
  178. package/dist/tools/directory-tree.d.ts.map +1 -1
  179. package/dist/tools/directory-tree.js +86 -49
  180. package/dist/tools/directory-tree.js.map +1 -1
  181. package/dist/tools/get-file-info.d.ts.map +1 -1
  182. package/dist/tools/get-file-info.js +71 -37
  183. package/dist/tools/get-file-info.js.map +1 -1
  184. package/dist/tools/list-allowed-dirs.d.ts.map +1 -1
  185. package/dist/tools/list-allowed-dirs.js +48 -35
  186. package/dist/tools/list-allowed-dirs.js.map +1 -1
  187. package/dist/tools/list-directory.d.ts.map +1 -1
  188. package/dist/tools/list-directory.js +129 -58
  189. package/dist/tools/list-directory.js.map +1 -1
  190. package/dist/tools/read-file.d.ts.map +1 -1
  191. package/dist/tools/read-file.js +70 -56
  192. package/dist/tools/read-file.js.map +1 -1
  193. package/dist/tools/read-media-file.d.ts.map +1 -1
  194. package/dist/tools/read-media-file.js +39 -41
  195. package/dist/tools/read-media-file.js.map +1 -1
  196. package/dist/tools/read-multiple-files.d.ts.map +1 -1
  197. package/dist/tools/read-multiple-files.js +58 -50
  198. package/dist/tools/read-multiple-files.js.map +1 -1
  199. package/dist/tools/search-content.d.ts.map +1 -1
  200. package/dist/tools/search-content.js +148 -89
  201. package/dist/tools/search-content.js.map +1 -1
  202. package/dist/tools/search-files.d.ts.map +1 -1
  203. package/dist/tools/search-files.js +123 -50
  204. package/dist/tools/search-files.js.map +1 -1
  205. package/dist/tools/tool-response.d.ts +9 -0
  206. package/dist/tools/tool-response.d.ts.map +1 -0
  207. package/dist/tools/tool-response.js +7 -0
  208. package/dist/tools/tool-response.js.map +1 -0
  209. package/package.json +2 -1
  210. package/dist/__tests__/errors.test.d.ts +0 -2
  211. package/dist/__tests__/errors.test.d.ts.map +0 -1
  212. package/dist/__tests__/errors.test.js +0 -88
  213. package/dist/__tests__/errors.test.js.map +0 -1
  214. package/dist/__tests__/file-operations.test.d.ts +0 -2
  215. package/dist/__tests__/file-operations.test.d.ts.map +0 -1
  216. package/dist/__tests__/file-operations.test.js +0 -230
  217. package/dist/__tests__/file-operations.test.js.map +0 -1
  218. package/dist/__tests__/lib/formatters.test.d.ts +0 -2
  219. package/dist/__tests__/lib/formatters.test.d.ts.map +0 -1
  220. package/dist/__tests__/lib/formatters.test.js +0 -248
  221. package/dist/__tests__/lib/formatters.test.js.map +0 -1
  222. package/dist/__tests__/lib/image-parsing.test.d.ts +0 -2
  223. package/dist/__tests__/lib/image-parsing.test.d.ts.map +0 -1
  224. package/dist/__tests__/lib/image-parsing.test.js +0 -262
  225. package/dist/__tests__/lib/image-parsing.test.js.map +0 -1
  226. package/dist/__tests__/path-validation.test.d.ts +0 -2
  227. package/dist/__tests__/path-validation.test.d.ts.map +0 -1
  228. package/dist/__tests__/path-validation.test.js +0 -92
  229. package/dist/__tests__/path-validation.test.js.map +0 -1
  230. package/dist/lib/directory-helpers.d.ts +0 -4
  231. package/dist/lib/directory-helpers.d.ts.map +0 -1
  232. package/dist/lib/directory-helpers.js +0 -36
  233. package/dist/lib/directory-helpers.js.map +0 -1
  234. package/dist/lib/formatters.d.ts +0 -10
  235. package/dist/lib/formatters.d.ts.map +0 -1
  236. package/dist/lib/formatters.js +0 -202
  237. package/dist/lib/formatters.js.map +0 -1
  238. package/dist/lib/image-parsing.d.ts +0 -4
  239. package/dist/lib/image-parsing.d.ts.map +0 -1
  240. package/dist/lib/image-parsing.js +0 -124
  241. package/dist/lib/image-parsing.js.map +0 -1
  242. package/dist/lib/mcp-logger.d.ts +0 -11
  243. package/dist/lib/mcp-logger.d.ts.map +0 -1
  244. package/dist/lib/mcp-logger.js +0 -49
  245. package/dist/lib/mcp-logger.js.map +0 -1
  246. package/dist/lib/roots-utils.d.ts +0 -7
  247. package/dist/lib/roots-utils.d.ts.map +0 -1
  248. package/dist/lib/roots-utils.js +0 -39
  249. package/dist/lib/roots-utils.js.map +0 -1
  250. package/dist/lib/search-helpers.d.ts +0 -16
  251. package/dist/lib/search-helpers.d.ts.map +0 -1
  252. package/dist/lib/search-helpers.js +0 -169
  253. package/dist/lib/search-helpers.js.map +0 -1
  254. package/dist/lib/sorting.d.ts +0 -12
  255. package/dist/lib/sorting.d.ts.map +0 -1
  256. package/dist/lib/sorting.js +0 -41
  257. package/dist/lib/sorting.js.map +0 -1
  258. package/dist/lib/types.d.ts +0 -6
  259. package/dist/lib/types.d.ts.map +0 -1
  260. package/dist/lib/types.js +0 -2
  261. package/dist/lib/types.js.map +0 -1
  262. package/dist/prompts/analyze-codebase.d.ts +0 -3
  263. package/dist/prompts/analyze-codebase.d.ts.map +0 -1
  264. package/dist/prompts/analyze-codebase.js +0 -144
  265. package/dist/prompts/analyze-codebase.js.map +0 -1
  266. package/dist/prompts/filesystem-query.d.ts +0 -3
  267. package/dist/prompts/filesystem-query.d.ts.map +0 -1
  268. package/dist/prompts/filesystem-query.js +0 -168
  269. package/dist/prompts/filesystem-query.js.map +0 -1
  270. package/dist/prompts/find-duplicates.d.ts +0 -3
  271. package/dist/prompts/find-duplicates.d.ts.map +0 -1
  272. package/dist/prompts/find-duplicates.js +0 -77
  273. package/dist/prompts/find-duplicates.js.map +0 -1
  274. package/dist/prompts/index.d.ts +0 -3
  275. package/dist/prompts/index.d.ts.map +0 -1
  276. package/dist/prompts/index.js +0 -13
  277. package/dist/prompts/index.js.map +0 -1
  278. package/dist/prompts/project-overview.d.ts +0 -3
  279. package/dist/prompts/project-overview.d.ts.map +0 -1
  280. package/dist/prompts/project-overview.js +0 -122
  281. package/dist/prompts/project-overview.js.map +0 -1
  282. package/dist/prompts/search-and-replace.d.ts +0 -3
  283. package/dist/prompts/search-and-replace.d.ts.map +0 -1
  284. package/dist/prompts/search-and-replace.js +0 -130
  285. package/dist/prompts/search-and-replace.js.map +0 -1
  286. package/dist/prompts/shared.d.ts +0 -11
  287. package/dist/prompts/shared.d.ts.map +0 -1
  288. package/dist/prompts/shared.js +0 -32
  289. package/dist/prompts/shared.js.map +0 -1
  290. package/dist/resources/index.d.ts +0 -3
  291. package/dist/resources/index.d.ts.map +0 -1
  292. package/dist/resources/index.js +0 -54
  293. package/dist/resources/index.js.map +0 -1
  294. package/dist/schemas/validators.d.ts +0 -12
  295. package/dist/schemas/validators.d.ts.map +0 -1
  296. package/dist/schemas/validators.js +0 -35
  297. package/dist/schemas/validators.js.map +0 -1
  298. package/dist/utils/index.d.ts +0 -2
  299. package/dist/utils/index.d.ts.map +0 -1
  300. package/dist/utils/index.js +0 -2
  301. package/dist/utils/index.js.map +0 -1
  302. package/dist/utils/response-helpers.d.ts +0 -22
  303. package/dist/utils/response-helpers.d.ts.map +0 -1
  304. package/dist/utils/response-helpers.js +0 -24
  305. package/dist/utils/response-helpers.js.map +0 -1
@@ -1,59 +1,96 @@
1
1
  import { createErrorResponse, ErrorCode } from '../lib/errors.js';
2
2
  import { getDirectoryTree } from '../lib/file-operations.js';
3
- import { formatOperationSummary, formatTreeEntry } from '../lib/formatters.js';
4
3
  import { DirectoryTreeInputSchema, DirectoryTreeOutputSchema, } from '../schemas/index.js';
4
+ import { buildToolResponse } from './tool-response.js';
5
+ const BYTE_UNIT_LABELS = ['B', 'KB', 'MB', 'GB', 'TB'];
6
+ function formatBytes(bytes) {
7
+ if (bytes === 0)
8
+ return '0 B';
9
+ const unitIndex = Math.floor(Math.log(bytes) / Math.log(1024));
10
+ const unit = BYTE_UNIT_LABELS[unitIndex] ?? 'B';
11
+ const value = bytes / Math.pow(1024, unitIndex);
12
+ return `${parseFloat(value.toFixed(2))} ${unit}`;
13
+ }
14
+ function formatTreeEntry(entry, indent = '') {
15
+ const lines = [];
16
+ const icon = entry.type === 'directory' ? '[DIR]' : '[FILE]';
17
+ const size = entry.size !== undefined ? ` (${formatBytes(entry.size)})` : '';
18
+ lines.push(`${indent}${icon} ${entry.name}${size}`);
19
+ for (const child of entry.children ?? []) {
20
+ lines.push(formatTreeEntry(child, `${indent} `));
21
+ }
22
+ return lines.join('\n');
23
+ }
24
+ function formatOperationSummary(summary) {
25
+ const lines = [];
26
+ if (summary.truncated) {
27
+ lines.push(`\n\n!! PARTIAL RESULTS: ${summary.truncatedReason ?? 'results truncated'}`);
28
+ if (summary.tip)
29
+ lines.push(`Tip: ${summary.tip}`);
30
+ }
31
+ const note = (count, msg) => {
32
+ if (count && count > 0)
33
+ lines.push(`Note: ${count} ${msg}`);
34
+ };
35
+ note(summary.skippedTooLarge, 'file(s) skipped (too large).');
36
+ note(summary.skippedBinary, 'file(s) skipped (binary).');
37
+ note(summary.skippedInaccessible, 'item(s) were inaccessible and skipped.');
38
+ note(summary.symlinksNotFollowed, 'symlink(s) were not followed (security).');
39
+ note(summary.linesSkippedDueToRegexTimeout, 'line(s) skipped (regex timeout).');
40
+ return lines.join('\n');
41
+ }
42
+ function buildStructuredResult(result) {
43
+ return {
44
+ ok: true,
45
+ tree: result.tree,
46
+ summary: result.summary,
47
+ };
48
+ }
49
+ function buildTextResult(result) {
50
+ let textOutput = formatTreeEntry(result.tree);
51
+ textOutput += formatOperationSummary({
52
+ truncated: result.summary.truncated,
53
+ truncatedReason: 'tree was truncated',
54
+ tip: 'Increase maxDepth or maxFiles, or add excludePatterns to narrow scope.',
55
+ skippedInaccessible: result.summary.skippedInaccessible,
56
+ symlinksNotFollowed: result.summary.symlinksNotFollowed,
57
+ });
58
+ return textOutput;
59
+ }
60
+ async function handleDirectoryTree({ path, maxDepth, excludePatterns, includeHidden, includeSize, maxFiles, }) {
61
+ const result = await getDirectoryTree(path, {
62
+ maxDepth,
63
+ excludePatterns,
64
+ includeHidden,
65
+ includeSize,
66
+ maxFiles,
67
+ });
68
+ const structured = buildStructuredResult(result);
69
+ const textOutput = buildTextResult(result);
70
+ return buildToolResponse(textOutput, structured);
71
+ }
72
+ const DIRECTORY_TREE_TOOL = {
73
+ title: 'Directory Tree',
74
+ description: 'Generate a hierarchical JSON tree structure of a directory. ' +
75
+ 'More efficient for AI parsing than flat file lists. ' +
76
+ 'Ideal for understanding project layout and structure at a glance. ' +
77
+ 'Use maxDepth to limit traversal depth and excludePatterns to skip folders like node_modules. ' +
78
+ 'Optionally include file sizes with includeSize=true.',
79
+ inputSchema: DirectoryTreeInputSchema,
80
+ outputSchema: DirectoryTreeOutputSchema,
81
+ annotations: {
82
+ readOnlyHint: true,
83
+ idempotentHint: true,
84
+ openWorldHint: true,
85
+ },
86
+ };
5
87
  export function registerDirectoryTreeTool(server) {
6
- server.registerTool('directory_tree', {
7
- title: 'Directory Tree',
8
- description: 'Generate a hierarchical JSON tree structure of a directory. ' +
9
- 'More efficient for AI parsing than flat file lists. ' +
10
- 'Ideal for understanding project layout and structure at a glance. ' +
11
- 'Use maxDepth to limit traversal depth and excludePatterns to skip folders like node_modules. ' +
12
- 'Optionally include file sizes with includeSize=true.',
13
- inputSchema: DirectoryTreeInputSchema,
14
- outputSchema: DirectoryTreeOutputSchema,
15
- annotations: {
16
- readOnlyHint: true,
17
- idempotentHint: true,
18
- openWorldHint: true,
19
- },
20
- }, async ({ path, maxDepth, excludePatterns, includeHidden, includeSize, maxFiles, }) => {
88
+ server.registerTool('directory_tree', DIRECTORY_TREE_TOOL, async (args) => {
21
89
  try {
22
- const result = await getDirectoryTree(path, {
23
- maxDepth,
24
- excludePatterns,
25
- includeHidden,
26
- includeSize,
27
- maxFiles,
28
- });
29
- let textOutput = formatTreeEntry(result.tree);
30
- const structured = {
31
- ok: true,
32
- tree: result.tree,
33
- summary: {
34
- totalFiles: result.summary.totalFiles,
35
- totalDirectories: result.summary.totalDirectories,
36
- maxDepthReached: result.summary.maxDepthReached,
37
- truncated: result.summary.truncated,
38
- skippedInaccessible: result.summary.skippedInaccessible,
39
- symlinksNotFollowed: result.summary.symlinksNotFollowed,
40
- },
41
- };
42
- // Add truncation notice for better error recovery feedback
43
- textOutput += formatOperationSummary({
44
- truncated: result.summary.truncated,
45
- truncatedReason: 'tree was truncated',
46
- tip: 'Increase maxDepth or maxFiles, or add excludePatterns to narrow scope.',
47
- skippedInaccessible: result.summary.skippedInaccessible,
48
- symlinksNotFollowed: result.summary.symlinksNotFollowed,
49
- });
50
- return {
51
- content: [{ type: 'text', text: textOutput }],
52
- structuredContent: structured,
53
- };
90
+ return await handleDirectoryTree(args);
54
91
  }
55
92
  catch (error) {
56
- return createErrorResponse(error, ErrorCode.E_NOT_DIRECTORY, path);
93
+ return createErrorResponse(error, ErrorCode.E_NOT_DIRECTORY, args.path);
57
94
  }
58
95
  });
59
96
  }
@@ -1 +1 @@
1
- {"version":3,"file":"directory-tree.js","sourceRoot":"","sources":["../../src/tools/directory-tree.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,mBAAmB,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAClE,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAC7D,OAAO,EAAE,sBAAsB,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAC/E,OAAO,EACL,wBAAwB,EACxB,yBAAyB,GAC1B,MAAM,qBAAqB,CAAC;AAE7B,MAAM,UAAU,yBAAyB,CAAC,MAAiB;IACzD,MAAM,CAAC,YAAY,CACjB,gBAAgB,EAChB;QACE,KAAK,EAAE,gBAAgB;QACvB,WAAW,EACT,8DAA8D;YAC9D,sDAAsD;YACtD,oEAAoE;YACpE,+FAA+F;YAC/F,sDAAsD;QACxD,WAAW,EAAE,wBAAwB;QACrC,YAAY,EAAE,yBAAyB;QACvC,WAAW,EAAE;YACX,YAAY,EAAE,IAAI;YAClB,cAAc,EAAE,IAAI;YACpB,aAAa,EAAE,IAAI;SACpB;KACF,EACD,KAAK,EAAE,EACL,IAAI,EACJ,QAAQ,EACR,eAAe,EACf,aAAa,EACb,WAAW,EACX,QAAQ,GACT,EAAE,EAAE;QACH,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC,IAAI,EAAE;gBAC1C,QAAQ;gBACR,eAAe;gBACf,aAAa;gBACb,WAAW;gBACX,QAAQ;aACT,CAAC,CAAC;YAEH,IAAI,UAAU,GAAG,eAAe,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAE9C,MAAM,UAAU,GAAG;gBACjB,EAAE,EAAE,IAAI;gBACR,IAAI,EAAE,MAAM,CAAC,IAAI;gBACjB,OAAO,EAAE;oBACP,UAAU,EAAE,MAAM,CAAC,OAAO,CAAC,UAAU;oBACrC,gBAAgB,EAAE,MAAM,CAAC,OAAO,CAAC,gBAAgB;oBACjD,eAAe,EAAE,MAAM,CAAC,OAAO,CAAC,eAAe;oBAC/C,SAAS,EAAE,MAAM,CAAC,OAAO,CAAC,SAAS;oBACnC,mBAAmB,EAAE,MAAM,CAAC,OAAO,CAAC,mBAAmB;oBACvD,mBAAmB,EAAE,MAAM,CAAC,OAAO,CAAC,mBAAmB;iBACxD;aACF,CAAC;YAEF,2DAA2D;YAC3D,UAAU,IAAI,sBAAsB,CAAC;gBACnC,SAAS,EAAE,MAAM,CAAC,OAAO,CAAC,SAAS;gBACnC,eAAe,EAAE,oBAAoB;gBACrC,GAAG,EAAE,wEAAwE;gBAC7E,mBAAmB,EAAE,MAAM,CAAC,OAAO,CAAC,mBAAmB;gBACvD,mBAAmB,EAAE,MAAM,CAAC,OAAO,CAAC,mBAAmB;aACxD,CAAC,CAAC;YAEH,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC;gBAC7C,iBAAiB,EAAE,UAAU;aAC9B,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,mBAAmB,CAAC,KAAK,EAAE,SAAS,CAAC,eAAe,EAAE,IAAI,CAAC,CAAC;QACrE,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"directory-tree.js","sourceRoot":"","sources":["../../src/tools/directory-tree.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"get-file-info.d.ts","sourceRoot":"","sources":["../../src/tools/get-file-info.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAUzE,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA8C/D"}
1
+ {"version":3,"file":"get-file-info.d.ts","sourceRoot":"","sources":["../../src/tools/get-file-info.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AA8FzE,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAQ/D"}
@@ -1,47 +1,81 @@
1
1
  import { createErrorResponse, ErrorCode } from '../lib/errors.js';
2
2
  import { getFileInfo } from '../lib/file-operations.js';
3
- import { formatFileInfo } from '../lib/formatters.js';
4
3
  import { GetFileInfoInputSchema, GetFileInfoOutputSchema, } from '../schemas/index.js';
5
- export function registerGetFileInfoTool(server) {
6
- server.registerTool('get_file_info', {
7
- title: 'Get File Info',
8
- description: 'Retrieve detailed metadata about a file or directory without reading its contents. ' +
9
- 'Returns: name, path, type, size, timestamps (created/modified/accessed), permissions, ' +
10
- 'MIME type (for files), hidden status, and symlink target (if applicable). ' +
11
- 'Use this to check file properties before reading large files.',
12
- inputSchema: GetFileInfoInputSchema,
13
- outputSchema: GetFileInfoOutputSchema,
14
- annotations: {
15
- readOnlyHint: true,
16
- idempotentHint: true,
17
- openWorldHint: true,
4
+ import { buildToolResponse } from './tool-response.js';
5
+ const BYTE_UNIT_LABELS = ['B', 'KB', 'MB', 'GB', 'TB'];
6
+ function formatBytes(bytes) {
7
+ if (bytes === 0)
8
+ return '0 B';
9
+ const unitIndex = Math.floor(Math.log(bytes) / Math.log(1024));
10
+ const unit = BYTE_UNIT_LABELS[unitIndex] ?? 'B';
11
+ const value = bytes / Math.pow(1024, unitIndex);
12
+ return `${parseFloat(value.toFixed(2))} ${unit}`;
13
+ }
14
+ function formatDate(date) {
15
+ return date.toISOString();
16
+ }
17
+ function formatFileInfo(info) {
18
+ const lines = [
19
+ `Name: ${info.name}`,
20
+ `Path: ${info.path}`,
21
+ `Type: ${info.type}`,
22
+ `Size: ${formatBytes(info.size)}`,
23
+ `Created: ${formatDate(info.created)}`,
24
+ `Modified: ${formatDate(info.modified)}`,
25
+ `Accessed: ${formatDate(info.accessed)}`,
26
+ `Permissions: ${info.permissions}`,
27
+ `Hidden: ${info.isHidden ? 'Yes' : 'No'}`,
28
+ ];
29
+ if (info.mimeType)
30
+ lines.push(`MIME Type: ${info.mimeType}`);
31
+ if (info.symlinkTarget)
32
+ lines.push(`Symlink Target: ${info.symlinkTarget}`);
33
+ return lines.join('\n');
34
+ }
35
+ function buildStructuredResult(info) {
36
+ return {
37
+ ok: true,
38
+ info: {
39
+ name: info.name,
40
+ path: info.path,
41
+ type: info.type,
42
+ size: info.size,
43
+ created: info.created.toISOString(),
44
+ modified: info.modified.toISOString(),
45
+ accessed: info.accessed.toISOString(),
46
+ permissions: info.permissions,
47
+ isHidden: info.isHidden,
48
+ mimeType: info.mimeType,
49
+ symlinkTarget: info.symlinkTarget,
18
50
  },
19
- }, async ({ path }) => {
51
+ };
52
+ }
53
+ async function handleGetFileInfo({ path, }) {
54
+ const info = await getFileInfo(path);
55
+ const structured = buildStructuredResult(info);
56
+ return buildToolResponse(formatFileInfo(info), structured);
57
+ }
58
+ const GET_FILE_INFO_TOOL = {
59
+ title: 'Get File Info',
60
+ description: 'Retrieve detailed metadata about a file or directory without reading its contents. ' +
61
+ 'Returns: name, path, type, size, timestamps (created/modified/accessed), permissions, ' +
62
+ 'MIME type (for files), hidden status, and symlink target (if applicable). ' +
63
+ 'Use this to check file properties before reading large files.',
64
+ inputSchema: GetFileInfoInputSchema,
65
+ outputSchema: GetFileInfoOutputSchema,
66
+ annotations: {
67
+ readOnlyHint: true,
68
+ idempotentHint: true,
69
+ openWorldHint: true,
70
+ },
71
+ };
72
+ export function registerGetFileInfoTool(server) {
73
+ server.registerTool('get_file_info', GET_FILE_INFO_TOOL, async (args) => {
20
74
  try {
21
- const info = await getFileInfo(path);
22
- const structured = {
23
- ok: true,
24
- info: {
25
- name: info.name,
26
- path: info.path,
27
- type: info.type,
28
- size: info.size,
29
- created: info.created.toISOString(),
30
- modified: info.modified.toISOString(),
31
- accessed: info.accessed.toISOString(),
32
- permissions: info.permissions,
33
- isHidden: info.isHidden,
34
- mimeType: info.mimeType,
35
- symlinkTarget: info.symlinkTarget,
36
- },
37
- };
38
- return {
39
- content: [{ type: 'text', text: formatFileInfo(info) }],
40
- structuredContent: structured,
41
- };
75
+ return await handleGetFileInfo(args);
42
76
  }
43
77
  catch (error) {
44
- return createErrorResponse(error, ErrorCode.E_NOT_FOUND, path);
78
+ return createErrorResponse(error, ErrorCode.E_NOT_FOUND, args.path);
45
79
  }
46
80
  });
47
81
  }
@@ -1 +1 @@
1
- {"version":3,"file":"get-file-info.js","sourceRoot":"","sources":["../../src/tools/get-file-info.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,mBAAmB,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAClE,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACxD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EACL,sBAAsB,EACtB,uBAAuB,GACxB,MAAM,qBAAqB,CAAC;AAE7B,MAAM,UAAU,uBAAuB,CAAC,MAAiB;IACvD,MAAM,CAAC,YAAY,CACjB,eAAe,EACf;QACE,KAAK,EAAE,eAAe;QACtB,WAAW,EACT,qFAAqF;YACrF,wFAAwF;YACxF,4EAA4E;YAC5E,+DAA+D;QACjE,WAAW,EAAE,sBAAsB;QACnC,YAAY,EAAE,uBAAuB;QACrC,WAAW,EAAE;YACX,YAAY,EAAE,IAAI;YAClB,cAAc,EAAE,IAAI;YACpB,aAAa,EAAE,IAAI;SACpB;KACF,EACD,KAAK,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE;QACjB,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,WAAW,CAAC,IAAI,CAAC,CAAC;YACrC,MAAM,UAAU,GAAG;gBACjB,EAAE,EAAE,IAAI;gBACR,IAAI,EAAE;oBACJ,IAAI,EAAE,IAAI,CAAC,IAAI;oBACf,IAAI,EAAE,IAAI,CAAC,IAAI;oBACf,IAAI,EAAE,IAAI,CAAC,IAAI;oBACf,IAAI,EAAE,IAAI,CAAC,IAAI;oBACf,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE;oBACnC,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,WAAW,EAAE;oBACrC,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,WAAW,EAAE;oBACrC,WAAW,EAAE,IAAI,CAAC,WAAW;oBAC7B,QAAQ,EAAE,IAAI,CAAC,QAAQ;oBACvB,QAAQ,EAAE,IAAI,CAAC,QAAQ;oBACvB,aAAa,EAAE,IAAI,CAAC,aAAa;iBAClC;aACF,CAAC;YACF,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,cAAc,CAAC,IAAI,CAAC,EAAE,CAAC;gBACvD,iBAAiB,EAAE,UAAU;aAC9B,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,mBAAmB,CAAC,KAAK,EAAE,SAAS,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;QACjE,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"get-file-info.js","sourceRoot":"","sources":["../../src/tools/get-file-info.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"list-allowed-dirs.d.ts","sourceRoot":"","sources":["../../src/tools/list-allowed-dirs.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAqBzE,wBAAgB,kCAAkC,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA2C1E"}
1
+ {"version":3,"file":"list-allowed-dirs.d.ts","sourceRoot":"","sources":["../../src/tools/list-allowed-dirs.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAyFzE,wBAAgB,kCAAkC,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAM1E"}
@@ -1,7 +1,17 @@
1
1
  import * as fs from 'node:fs/promises';
2
- import { formatAllowedDirectories } from '../lib/formatters.js';
3
2
  import { getAllowedDirectories } from '../lib/path-validation.js';
4
3
  import { ListAllowedDirectoriesOutputSchema } from '../schemas/index.js';
4
+ import { buildToolResponse } from './tool-response.js';
5
+ function formatAllowedDirectories(dirs) {
6
+ if (dirs.length === 0) {
7
+ return 'No directories are currently allowed.';
8
+ }
9
+ const lines = ['Allowed Directories:', ''];
10
+ for (const dir of dirs) {
11
+ lines.push(` - ${dir}`);
12
+ }
13
+ return lines.join('\n');
14
+ }
5
15
  async function checkDirectoryAccess(dirPath) {
6
16
  try {
7
17
  await fs.access(dirPath, fs.constants.R_OK);
@@ -17,40 +27,43 @@ async function checkDirectoryAccess(dirPath) {
17
27
  }
18
28
  }
19
29
  }
30
+ function buildHint(count) {
31
+ if (count === 0) {
32
+ return 'No directories configured. Server cannot access any files.';
33
+ }
34
+ if (count === 1) {
35
+ return 'Single directory configured. All operations are sandboxed here.';
36
+ }
37
+ return `${count} directories configured. Operations work across all of them.`;
38
+ }
39
+ async function handleListAllowedDirectories() {
40
+ const dirs = getAllowedDirectories();
41
+ const count = dirs.length;
42
+ const hint = buildHint(count);
43
+ const accessStatus = await Promise.all(dirs.map(checkDirectoryAccess));
44
+ const structured = {
45
+ ok: true,
46
+ allowedDirectories: dirs,
47
+ count,
48
+ accessStatus,
49
+ hint,
50
+ };
51
+ return buildToolResponse(formatAllowedDirectories(dirs), structured);
52
+ }
53
+ const LIST_ALLOWED_DIRECTORIES_TOOL = {
54
+ title: 'List Allowed Directories',
55
+ description: 'Returns the list of directories this server is permitted to access. ' +
56
+ 'Call this FIRST to understand the scope of available file operations. ' +
57
+ 'All other tools will only work within these directories for security.',
58
+ inputSchema: {},
59
+ outputSchema: ListAllowedDirectoriesOutputSchema,
60
+ annotations: {
61
+ readOnlyHint: true,
62
+ idempotentHint: true,
63
+ openWorldHint: false,
64
+ },
65
+ };
20
66
  export function registerListAllowedDirectoriesTool(server) {
21
- server.registerTool('list_allowed_directories', {
22
- title: 'List Allowed Directories',
23
- description: 'Returns the list of directories this server is permitted to access. ' +
24
- 'Call this FIRST to understand the scope of available file operations. ' +
25
- 'All other tools will only work within these directories for security.',
26
- inputSchema: {},
27
- outputSchema: ListAllowedDirectoriesOutputSchema,
28
- annotations: {
29
- readOnlyHint: true,
30
- idempotentHint: true,
31
- openWorldHint: false,
32
- },
33
- }, async () => {
34
- const dirs = getAllowedDirectories();
35
- const count = dirs.length;
36
- const hint = count === 0
37
- ? 'No directories configured. Server cannot access any files.'
38
- : count === 1
39
- ? 'Single directory configured. All operations are sandboxed here.'
40
- : `${count} directories configured. Operations work across all of them.`;
41
- // Check access status for each directory
42
- const accessStatus = await Promise.all(dirs.map(checkDirectoryAccess));
43
- const structured = {
44
- ok: true,
45
- allowedDirectories: dirs,
46
- count,
47
- accessStatus,
48
- hint,
49
- };
50
- return {
51
- content: [{ type: 'text', text: formatAllowedDirectories(dirs) }],
52
- structuredContent: structured,
53
- };
54
- });
67
+ server.registerTool('list_allowed_directories', LIST_ALLOWED_DIRECTORIES_TOOL, async () => await handleListAllowedDirectories());
55
68
  }
56
69
  //# sourceMappingURL=list-allowed-dirs.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"list-allowed-dirs.js","sourceRoot":"","sources":["../../src/tools/list-allowed-dirs.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAKvC,OAAO,EAAE,wBAAwB,EAAE,MAAM,sBAAsB,CAAC;AAChE,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,EAAE,kCAAkC,EAAE,MAAM,qBAAqB,CAAC;AAEzE,KAAK,UAAU,oBAAoB,CAAC,OAAe;IACjD,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,MAAM,CAAC,OAAO,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QAC5C,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IAC7D,CAAC;IAAC,MAAM,CAAC;QACP,IAAI,CAAC;YACH,MAAM,EAAE,CAAC,MAAM,CAAC,OAAO,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;YAC5C,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;QAC9D,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;QAC/D,CAAC;IACH,CAAC;AACH,CAAC;AAED,MAAM,UAAU,kCAAkC,CAAC,MAAiB;IAClE,MAAM,CAAC,YAAY,CACjB,0BAA0B,EAC1B;QACE,KAAK,EAAE,0BAA0B;QACjC,WAAW,EACT,sEAAsE;YACtE,wEAAwE;YACxE,uEAAuE;QACzE,WAAW,EAAE,EAAE;QACf,YAAY,EAAE,kCAAkC;QAChD,WAAW,EAAE;YACX,YAAY,EAAE,IAAI;YAClB,cAAc,EAAE,IAAI;YACpB,aAAa,EAAE,KAAK;SACrB;KACF,EACD,KAAK,IAAI,EAAE;QACT,MAAM,IAAI,GAAG,qBAAqB,EAAE,CAAC;QACrC,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC;QAC1B,MAAM,IAAI,GACR,KAAK,KAAK,CAAC;YACT,CAAC,CAAC,4DAA4D;YAC9D,CAAC,CAAC,KAAK,KAAK,CAAC;gBACX,CAAC,CAAC,iEAAiE;gBACnE,CAAC,CAAC,GAAG,KAAK,8DAA8D,CAAC;QAE/E,yCAAyC;QACzC,MAAM,YAAY,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC,CAAC;QAEvE,MAAM,UAAU,GAAG;YACjB,EAAE,EAAE,IAAI;YACR,kBAAkB,EAAE,IAAI;YACxB,KAAK;YACL,YAAY;YACZ,IAAI;SACL,CAAC;QACF,OAAO;YACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,wBAAwB,CAAC,IAAI,CAAC,EAAE,CAAC;YACjE,iBAAiB,EAAE,UAAU;SAC9B,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"list-allowed-dirs.js","sourceRoot":"","sources":["../../src/tools/list-allowed-dirs.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"list-directory.d.ts","sourceRoot":"","sources":["../../src/tools/list-directory.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAmBzE,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA6EjE"}
1
+ {"version":3,"file":"list-directory.d.ts","sourceRoot":"","sources":["../../src/tools/list-directory.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAmMzE,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAQjE"}
@@ -1,75 +1,146 @@
1
1
  import * as pathModule from 'node:path';
2
2
  import { createErrorResponse, ErrorCode } from '../lib/errors.js';
3
3
  import { listDirectory } from '../lib/file-operations.js';
4
- import { formatDirectoryListing, formatOperationSummary, } from '../lib/formatters.js';
5
4
  import { ListDirectoryInputSchema, ListDirectoryOutputSchema, } from '../schemas/index.js';
5
+ import { buildToolResponse } from './tool-response.js';
6
6
  function getExtension(name, isFile) {
7
7
  if (!isFile)
8
8
  return undefined;
9
9
  const ext = pathModule.extname(name);
10
10
  return ext ? ext.slice(1) : undefined;
11
11
  }
12
- export function registerListDirectoryTool(server) {
13
- server.registerTool('list_directory', {
14
- title: 'List Directory',
15
- description: 'List files and subdirectories in a specified path with optional recursive traversal. ' +
16
- 'Returns names, types (file/directory/symlink), sizes, and modification dates. ' +
17
- 'Use recursive=true with maxDepth to explore nested structures. ' +
18
- 'For a visual tree structure, use directory_tree instead.',
19
- inputSchema: ListDirectoryInputSchema,
20
- outputSchema: ListDirectoryOutputSchema,
21
- annotations: {
22
- readOnlyHint: true,
23
- idempotentHint: true,
24
- openWorldHint: true,
12
+ const BYTE_UNIT_LABELS = ['B', 'KB', 'MB', 'GB', 'TB'];
13
+ function formatBytes(bytes) {
14
+ if (bytes === 0)
15
+ return '0 B';
16
+ const unitIndex = Math.floor(Math.log(bytes) / Math.log(1024));
17
+ const unit = BYTE_UNIT_LABELS[unitIndex] ?? 'B';
18
+ const value = bytes / Math.pow(1024, unitIndex);
19
+ return `${parseFloat(value.toFixed(2))} ${unit}`;
20
+ }
21
+ function formatDirectoryListing(entries, basePath) {
22
+ if (entries.length === 0)
23
+ return 'Directory is empty';
24
+ const dirs = entries.filter((e) => e.type === 'directory');
25
+ const files = entries.filter((e) => e.type !== 'directory');
26
+ const lines = [
27
+ `Contents of ${basePath}:`,
28
+ '',
29
+ ...(dirs.length
30
+ ? [
31
+ 'Directories:',
32
+ ...dirs.map((dir) => {
33
+ const symlink = dir.symlinkTarget ? ` -> ${dir.symlinkTarget}` : '';
34
+ return ` [DIR] ${dir.relativePath}${symlink}`;
35
+ }),
36
+ '',
37
+ ]
38
+ : []),
39
+ ...(files.length
40
+ ? [
41
+ 'Files:',
42
+ ...files.map((file) => {
43
+ const size = file.size !== undefined ? ` (${formatBytes(file.size)})` : '';
44
+ const tag = file.type === 'symlink' ? '[LINK]' : '[FILE]';
45
+ const symlink = file.symlinkTarget
46
+ ? ` -> ${file.symlinkTarget}`
47
+ : '';
48
+ return ` ${tag} ${file.relativePath}${size}${symlink}`;
49
+ }),
50
+ ]
51
+ : []),
52
+ '',
53
+ `Total: ${dirs.length} directories, ${files.length} files`,
54
+ ];
55
+ return lines.join('\n');
56
+ }
57
+ function formatOperationSummary(summary) {
58
+ const lines = [];
59
+ if (summary.truncated) {
60
+ lines.push(`\n\n!! PARTIAL RESULTS: ${summary.truncatedReason ?? 'results truncated'}`);
61
+ if (summary.tip) {
62
+ lines.push(`Tip: ${summary.tip}`);
63
+ }
64
+ }
65
+ const note = (count, msg) => {
66
+ if (count && count > 0)
67
+ lines.push(`Note: ${count} ${msg}`);
68
+ };
69
+ note(summary.skippedTooLarge, 'file(s) skipped (too large).');
70
+ note(summary.skippedBinary, 'file(s) skipped (binary).');
71
+ note(summary.skippedInaccessible, 'item(s) were inaccessible and skipped.');
72
+ note(summary.symlinksNotFollowed, 'symlink(s) were not followed (security).');
73
+ note(summary.linesSkippedDueToRegexTimeout, 'line(s) skipped (regex timeout).');
74
+ return lines.join('\n');
75
+ }
76
+ const LIST_DIRECTORY_TOOL = {
77
+ title: 'List Directory',
78
+ description: 'List files and subdirectories in a specified path with optional recursive traversal. ' +
79
+ 'Returns names, types (file/directory/symlink), sizes, and modification dates. ' +
80
+ 'Use recursive=true with maxDepth to explore nested structures. ' +
81
+ 'For a visual tree structure, use directory_tree instead.',
82
+ inputSchema: ListDirectoryInputSchema,
83
+ outputSchema: ListDirectoryOutputSchema,
84
+ annotations: {
85
+ readOnlyHint: true,
86
+ idempotentHint: true,
87
+ openWorldHint: true,
88
+ },
89
+ };
90
+ function buildStructuredResult(result) {
91
+ return {
92
+ ok: true,
93
+ path: result.path,
94
+ entries: result.entries.map((e) => ({
95
+ name: e.relativePath,
96
+ type: e.type,
97
+ extension: getExtension(e.relativePath, e.type === 'file'),
98
+ size: e.size,
99
+ modified: e.modified?.toISOString(),
100
+ symlinkTarget: e.symlinkTarget,
101
+ })),
102
+ summary: {
103
+ totalEntries: result.summary.totalEntries,
104
+ totalFiles: result.summary.totalFiles,
105
+ totalDirectories: result.summary.totalDirectories,
106
+ maxDepthReached: result.summary.maxDepthReached,
107
+ truncated: result.summary.truncated,
108
+ skippedInaccessible: result.summary.skippedInaccessible,
109
+ symlinksNotFollowed: result.summary.symlinksNotFollowed,
25
110
  },
26
- }, async ({ path: dirPath, recursive, includeHidden, maxDepth, maxEntries, sortBy, includeSymlinkTargets, }) => {
111
+ };
112
+ }
113
+ function buildTextResult(result) {
114
+ let textOutput = formatDirectoryListing(result.entries, result.path);
115
+ textOutput += formatOperationSummary({
116
+ truncated: result.summary.truncated,
117
+ truncatedReason: `reached max entries limit (${result.summary.totalEntries} returned)`,
118
+ tip: 'Increase maxEntries or reduce maxDepth to see more results.',
119
+ skippedInaccessible: result.summary.skippedInaccessible,
120
+ symlinksNotFollowed: result.summary.symlinksNotFollowed,
121
+ });
122
+ return textOutput;
123
+ }
124
+ async function handleListDirectory({ path: dirPath, recursive, includeHidden, maxDepth, maxEntries, sortBy, includeSymlinkTargets, }) {
125
+ const result = await listDirectory(dirPath, {
126
+ recursive,
127
+ includeHidden,
128
+ maxDepth,
129
+ maxEntries,
130
+ sortBy,
131
+ includeSymlinkTargets,
132
+ });
133
+ const structured = buildStructuredResult(result);
134
+ const textOutput = buildTextResult(result);
135
+ return buildToolResponse(textOutput, structured);
136
+ }
137
+ export function registerListDirectoryTool(server) {
138
+ server.registerTool('list_directory', LIST_DIRECTORY_TOOL, async (args) => {
27
139
  try {
28
- const result = await listDirectory(dirPath, {
29
- recursive,
30
- includeHidden,
31
- maxDepth,
32
- maxEntries,
33
- sortBy,
34
- includeSymlinkTargets,
35
- });
36
- const structured = {
37
- ok: true,
38
- path: result.path,
39
- entries: result.entries.map((e) => ({
40
- name: e.relativePath,
41
- type: e.type,
42
- extension: getExtension(e.relativePath, e.type === 'file'),
43
- size: e.size,
44
- modified: e.modified?.toISOString(),
45
- symlinkTarget: e.symlinkTarget,
46
- })),
47
- summary: {
48
- totalEntries: result.summary.totalEntries,
49
- totalFiles: result.summary.totalFiles,
50
- totalDirectories: result.summary.totalDirectories,
51
- maxDepthReached: result.summary.maxDepthReached,
52
- truncated: result.summary.truncated,
53
- skippedInaccessible: result.summary.skippedInaccessible,
54
- symlinksNotFollowed: result.summary.symlinksNotFollowed,
55
- },
56
- };
57
- // Build text output with truncation notice for better error recovery feedback
58
- let textOutput = formatDirectoryListing(result.entries, result.path);
59
- textOutput += formatOperationSummary({
60
- truncated: result.summary.truncated,
61
- truncatedReason: `reached max entries limit (${result.summary.totalEntries} returned)`,
62
- tip: 'Increase maxEntries or reduce maxDepth to see more results.',
63
- skippedInaccessible: result.summary.skippedInaccessible,
64
- symlinksNotFollowed: result.summary.symlinksNotFollowed,
65
- });
66
- return {
67
- content: [{ type: 'text', text: textOutput }],
68
- structuredContent: structured,
69
- };
140
+ return await handleListDirectory(args);
70
141
  }
71
142
  catch (error) {
72
- return createErrorResponse(error, ErrorCode.E_NOT_DIRECTORY, dirPath);
143
+ return createErrorResponse(error, ErrorCode.E_NOT_DIRECTORY, args.path);
73
144
  }
74
145
  });
75
146
  }