@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
@@ -0,0 +1,94 @@
1
+ import * as fs from 'node:fs/promises';
2
+ import * as path from 'node:path';
3
+ import { normalizePath } from '../path-utils.js';
4
+ const PATH_SEPARATOR = process.platform === 'win32' ? '\\' : '/';
5
+ let allowedDirectories = [];
6
+ export const RESERVED_DEVICE_NAMES = new Set([
7
+ 'CON',
8
+ 'PRN',
9
+ 'AUX',
10
+ 'NUL',
11
+ 'COM1',
12
+ 'COM2',
13
+ 'COM3',
14
+ 'COM4',
15
+ 'COM5',
16
+ 'COM6',
17
+ 'COM7',
18
+ 'COM8',
19
+ 'COM9',
20
+ 'LPT1',
21
+ 'LPT2',
22
+ 'LPT3',
23
+ 'LPT4',
24
+ 'LPT5',
25
+ 'LPT6',
26
+ 'LPT7',
27
+ 'LPT8',
28
+ 'LPT9',
29
+ ]);
30
+ export function normalizeForComparison(p) {
31
+ return process.platform === 'win32' ? p.toLowerCase() : p;
32
+ }
33
+ function stripTrailingSeparator(normalized) {
34
+ return normalized.endsWith(PATH_SEPARATOR)
35
+ ? normalized.slice(0, -1)
36
+ : normalized;
37
+ }
38
+ export function normalizeAllowedDirectory(dir) {
39
+ const normalized = normalizePath(dir);
40
+ if (normalized.length === 0)
41
+ return '';
42
+ const { root } = path.parse(normalized);
43
+ const isRoot = normalizeForComparison(root) === normalizeForComparison(normalized);
44
+ if (isRoot)
45
+ return root;
46
+ return stripTrailingSeparator(normalized);
47
+ }
48
+ export function setAllowedDirectories(dirs) {
49
+ const normalized = dirs
50
+ .map(normalizeAllowedDirectory)
51
+ .filter((d) => d.length > 0);
52
+ allowedDirectories = [...new Set(normalized)];
53
+ }
54
+ export function getAllowedDirectories() {
55
+ return [...allowedDirectories];
56
+ }
57
+ export function isPathWithinAllowedDirectories(normalizedPath) {
58
+ const candidate = normalizeForComparison(normalizedPath);
59
+ return allowedDirectories.some((allowedDir) => {
60
+ const allowed = normalizeForComparison(allowedDir);
61
+ const root = normalizeForComparison(path.parse(allowedDir).root);
62
+ if (allowed === root) {
63
+ return candidate.startsWith(allowed);
64
+ }
65
+ return (candidate === allowed || candidate.startsWith(allowed + PATH_SEPARATOR));
66
+ });
67
+ }
68
+ export async function expandAllowedDirectories(dirs) {
69
+ const expanded = [];
70
+ for (const dir of dirs) {
71
+ const normalized = normalizeAllowedDirectory(dir);
72
+ if (!normalized)
73
+ continue;
74
+ expanded.push(normalized);
75
+ try {
76
+ const realPath = await fs.realpath(normalized);
77
+ const normalizedReal = normalizeAllowedDirectory(realPath);
78
+ if (normalizedReal &&
79
+ normalizeForComparison(normalizedReal) !==
80
+ normalizeForComparison(normalized)) {
81
+ expanded.push(normalizedReal);
82
+ }
83
+ }
84
+ catch {
85
+ // Keep normalized path if realpath fails
86
+ }
87
+ }
88
+ return [...new Set(expanded)];
89
+ }
90
+ export async function setAllowedDirectoriesResolved(dirs) {
91
+ const expanded = await expandAllowedDirectories(dirs);
92
+ setAllowedDirectories(expanded);
93
+ }
94
+ //# sourceMappingURL=allowed-directories.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"allowed-directories.js","sourceRoot":"","sources":["../../../src/lib/path-validation/allowed-directories.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import { McpError } from '../errors.js';
2
+ export declare function buildAllowedDirectoriesHint(): string;
3
+ export declare function toMcpError(requestedPath: string, error: unknown): McpError;
4
+ export declare function toAccessDeniedWithHint(requestedPath: string, resolvedPath: string, normalizedResolved: string): McpError;
5
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../../src/lib/path-validation/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,QAAQ,EAAE,MAAM,cAAc,CAAC;AAanD,wBAAgB,2BAA2B,IAAI,MAAM,CAKpD;AAED,wBAAgB,UAAU,CAAC,aAAa,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,QAAQ,CAmD1E;AAED,wBAAgB,sBAAsB,CACpC,aAAa,EAAE,MAAM,EACrB,YAAY,EAAE,MAAM,EACpB,kBAAkB,EAAE,MAAM,GACzB,QAAQ,CAQV"}
@@ -0,0 +1,33 @@
1
+ import { ErrorCode, McpError } from '../errors.js';
2
+ import { getAllowedDirectories } from './allowed-directories.js';
3
+ function createMcpError(code, message, requestedPath, details, cause) {
4
+ return new McpError(code, message, requestedPath, details, cause);
5
+ }
6
+ export function buildAllowedDirectoriesHint() {
7
+ const allowedDirs = getAllowedDirectories();
8
+ return allowedDirs.length > 0
9
+ ? `Allowed directories:\n${allowedDirs.map((d) => ` - ${d}`).join('\n')}`
10
+ : 'No allowed directories configured. Use CLI arguments or MCP roots protocol.';
11
+ }
12
+ export function toMcpError(requestedPath, error) {
13
+ const nodeError = error;
14
+ const { code } = nodeError;
15
+ if (code === 'ENOENT') {
16
+ return createMcpError(ErrorCode.E_NOT_FOUND, `Path does not exist: ${requestedPath}`, requestedPath, { originalCode: code }, error);
17
+ }
18
+ if (code === 'EACCES' || code === 'EPERM') {
19
+ return createMcpError(ErrorCode.E_PERMISSION_DENIED, `Permission denied accessing path: ${requestedPath}`, requestedPath, { originalCode: code }, error);
20
+ }
21
+ if (code === 'ELOOP') {
22
+ return createMcpError(ErrorCode.E_SYMLINK_NOT_ALLOWED, `Too many symbolic links in path (possible circular reference): ${requestedPath}`, requestedPath, { originalCode: code }, error);
23
+ }
24
+ if (code === 'ENAMETOOLONG') {
25
+ return createMcpError(ErrorCode.E_INVALID_INPUT, `Path name too long: ${requestedPath}`, requestedPath, { originalCode: code }, error);
26
+ }
27
+ return createMcpError(ErrorCode.E_NOT_FOUND, `Path is not accessible: ${requestedPath}`, requestedPath, { originalCode: code, originalMessage: nodeError.message }, error);
28
+ }
29
+ export function toAccessDeniedWithHint(requestedPath, resolvedPath, normalizedResolved) {
30
+ const suggestion = buildAllowedDirectoriesHint();
31
+ return new McpError(ErrorCode.E_ACCESS_DENIED, `Access denied: Path '${requestedPath}' is outside allowed directories.\n\n${suggestion}`, requestedPath, { resolvedPath, normalizedResolvedPath: normalizedResolved });
32
+ }
33
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../../src/lib/path-validation/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AAEjE,SAAS,cAAc,CACrB,IAAe,EACf,OAAe,EACf,aAAqB,EACrB,OAAgC,EAChC,KAAc;IAEd,OAAO,IAAI,QAAQ,CAAC,IAAI,EAAE,OAAO,EAAE,aAAa,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC;AACpE,CAAC;AAED,MAAM,UAAU,2BAA2B;IACzC,MAAM,WAAW,GAAG,qBAAqB,EAAE,CAAC;IAC5C,OAAO,WAAW,CAAC,MAAM,GAAG,CAAC;QAC3B,CAAC,CAAC,yBAAyB,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;QAC1E,CAAC,CAAC,6EAA6E,CAAC;AACpF,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,aAAqB,EAAE,KAAc;IAC9D,MAAM,SAAS,GAAG,KAA8B,CAAC;IACjD,MAAM,EAAE,IAAI,EAAE,GAAG,SAAS,CAAC;IAE3B,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;QACtB,OAAO,cAAc,CACnB,SAAS,CAAC,WAAW,EACrB,wBAAwB,aAAa,EAAE,EACvC,aAAa,EACb,EAAE,YAAY,EAAE,IAAI,EAAE,EACtB,KAAK,CACN,CAAC;IACJ,CAAC;IAED,IAAI,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;QAC1C,OAAO,cAAc,CACnB,SAAS,CAAC,mBAAmB,EAC7B,qCAAqC,aAAa,EAAE,EACpD,aAAa,EACb,EAAE,YAAY,EAAE,IAAI,EAAE,EACtB,KAAK,CACN,CAAC;IACJ,CAAC;IAED,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;QACrB,OAAO,cAAc,CACnB,SAAS,CAAC,qBAAqB,EAC/B,kEAAkE,aAAa,EAAE,EACjF,aAAa,EACb,EAAE,YAAY,EAAE,IAAI,EAAE,EACtB,KAAK,CACN,CAAC;IACJ,CAAC;IAED,IAAI,IAAI,KAAK,cAAc,EAAE,CAAC;QAC5B,OAAO,cAAc,CACnB,SAAS,CAAC,eAAe,EACzB,uBAAuB,aAAa,EAAE,EACtC,aAAa,EACb,EAAE,YAAY,EAAE,IAAI,EAAE,EACtB,KAAK,CACN,CAAC;IACJ,CAAC;IAED,OAAO,cAAc,CACnB,SAAS,CAAC,WAAW,EACrB,2BAA2B,aAAa,EAAE,EAC1C,aAAa,EACb,EAAE,YAAY,EAAE,IAAI,EAAE,eAAe,EAAE,SAAS,CAAC,OAAO,EAAE,EAC1D,KAAK,CACN,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,sBAAsB,CACpC,aAAqB,EACrB,YAAoB,EACpB,kBAA0B;IAE1B,MAAM,UAAU,GAAG,2BAA2B,EAAE,CAAC;IACjD,OAAO,IAAI,QAAQ,CACjB,SAAS,CAAC,eAAe,EACzB,wBAAwB,aAAa,wCAAwC,UAAU,EAAE,EACzF,aAAa,EACb,EAAE,YAAY,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,CAC7D,CAAC;AACJ,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { Root } from '@modelcontextprotocol/sdk/types.js';
2
+ export declare function getValidRootDirectories(roots: Root[]): Promise<string[]>;
3
+ //# sourceMappingURL=roots.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"roots.d.ts","sourceRoot":"","sources":["../../../src/lib/path-validation/roots.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,oCAAoC,CAAC;AA2C/D,wBAAsB,uBAAuB,CAC3C,KAAK,EAAE,IAAI,EAAE,GACZ,OAAO,CAAC,MAAM,EAAE,CAAC,CAcnB"}
@@ -0,0 +1,49 @@
1
+ import * as fs from 'node:fs/promises';
2
+ import { fileURLToPath } from 'node:url';
3
+ import { normalizePath } from '../path-utils.js';
4
+ import { normalizeForComparison } from './allowed-directories.js';
5
+ function isFileRoot(root) {
6
+ return root.uri.startsWith('file://');
7
+ }
8
+ async function maybeAddRealPath(normalizedPath, validDirs) {
9
+ try {
10
+ const realPath = await fs.realpath(normalizedPath);
11
+ const normalizedReal = normalizePath(realPath);
12
+ if (normalizeForComparison(normalizedReal) !==
13
+ normalizeForComparison(normalizedPath)) {
14
+ validDirs.push(normalizedReal);
15
+ }
16
+ }
17
+ catch {
18
+ // If realpath fails, use the normalized path only
19
+ }
20
+ }
21
+ async function resolveRootDirectory(root) {
22
+ try {
23
+ const dirPath = fileURLToPath(root.uri);
24
+ const normalizedPath = normalizePath(dirPath);
25
+ const stats = await fs.stat(normalizedPath);
26
+ if (!stats.isDirectory()) {
27
+ console.error(`Skipping root (not a directory): ${normalizedPath}`);
28
+ return null;
29
+ }
30
+ return normalizedPath;
31
+ }
32
+ catch {
33
+ return null;
34
+ }
35
+ }
36
+ export async function getValidRootDirectories(roots) {
37
+ const validDirs = [];
38
+ for (const root of roots) {
39
+ if (!isFileRoot(root))
40
+ continue;
41
+ const normalizedPath = await resolveRootDirectory(root);
42
+ if (!normalizedPath)
43
+ continue;
44
+ validDirs.push(normalizedPath);
45
+ await maybeAddRealPath(normalizedPath, validDirs);
46
+ }
47
+ return validDirs;
48
+ }
49
+ //# sourceMappingURL=roots.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"roots.js","sourceRoot":"","sources":["../../../src/lib/path-validation/roots.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAIzC,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAElE,SAAS,UAAU,CAAC,IAAU;IAC5B,OAAO,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;AACxC,CAAC;AAED,KAAK,UAAU,gBAAgB,CAC7B,cAAsB,EACtB,SAAmB;IAEnB,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC;QACnD,MAAM,cAAc,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC;QAC/C,IACE,sBAAsB,CAAC,cAAc,CAAC;YACtC,sBAAsB,CAAC,cAAc,CAAC,EACtC,CAAC;YACD,SAAS,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QACjC,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,kDAAkD;IACpD,CAAC;AACH,CAAC;AAED,KAAK,UAAU,oBAAoB,CAAC,IAAU;IAC5C,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,aAAa,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACxC,MAAM,cAAc,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC;QAC9C,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QAC5C,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;YACzB,OAAO,CAAC,KAAK,CAAC,oCAAoC,cAAc,EAAE,CAAC,CAAC;YACpE,OAAO,IAAI,CAAC;QACd,CAAC;QAED,OAAO,cAAc,CAAC;IACxB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,KAAa;IAEb,MAAM,SAAS,GAAa,EAAE,CAAC;IAE/B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;YAAE,SAAS;QAEhC,MAAM,cAAc,GAAG,MAAM,oBAAoB,CAAC,IAAI,CAAC,CAAC;QACxD,IAAI,CAAC,cAAc;YAAE,SAAS;QAE9B,SAAS,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QAC/B,MAAM,gBAAgB,CAAC,cAAc,EAAE,SAAS,CAAC,CAAC;IACpD,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC"}
@@ -0,0 +1,9 @@
1
+ interface ValidatedPathDetails {
2
+ requestedPath: string;
3
+ resolvedPath: string;
4
+ isSymlink: boolean;
5
+ }
6
+ export declare function validateExistingPathDetailed(requestedPath: string): Promise<ValidatedPathDetails>;
7
+ export declare function validateExistingPath(requestedPath: string): Promise<string>;
8
+ export {};
9
+ //# sourceMappingURL=validators.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validators.d.ts","sourceRoot":"","sources":["../../../src/lib/path-validation/validators.ts"],"names":[],"mappings":"AAWA,UAAU,oBAAoB;IAC5B,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,OAAO,CAAC;CACpB;AAgGD,wBAAsB,4BAA4B,CAChD,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC,oBAAoB,CAAC,CAE/B;AAED,wBAAsB,oBAAoB,CACxC,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC,MAAM,CAAC,CAGjB"}
@@ -0,0 +1,70 @@
1
+ import * as fs from 'node:fs/promises';
2
+ import { ErrorCode, McpError } from '../errors.js';
3
+ import { normalizePath } from '../path-utils.js';
4
+ import { isPathWithinAllowedDirectories, normalizeForComparison, RESERVED_DEVICE_NAMES, } from './allowed-directories.js';
5
+ import { toAccessDeniedWithHint, toMcpError } from './errors.js';
6
+ function ensureNonEmptyPath(requestedPath) {
7
+ if (!requestedPath || requestedPath.trim().length === 0) {
8
+ throw new McpError(ErrorCode.E_INVALID_INPUT, 'Path cannot be empty or whitespace', requestedPath);
9
+ }
10
+ }
11
+ function ensureNoNullBytes(requestedPath) {
12
+ if (requestedPath.includes('\0')) {
13
+ throw new McpError(ErrorCode.E_INVALID_INPUT, 'Path contains null bytes', requestedPath);
14
+ }
15
+ }
16
+ function ensureNoReservedWindowsNames(requestedPath) {
17
+ if (process.platform !== 'win32')
18
+ return;
19
+ const segments = requestedPath.split(/[\\/]/);
20
+ for (const segment of segments) {
21
+ const baseName = segment.split('.')[0]?.toUpperCase();
22
+ if (baseName && RESERVED_DEVICE_NAMES.has(baseName)) {
23
+ throw new McpError(ErrorCode.E_INVALID_INPUT, `Windows reserved device name not allowed: ${baseName}`, requestedPath);
24
+ }
25
+ }
26
+ }
27
+ function ensureWithinAllowedDirectories(normalizedPath, requestedPath, details) {
28
+ if (isPathWithinAllowedDirectories(normalizedPath))
29
+ return;
30
+ throw new McpError(ErrorCode.E_ACCESS_DENIED, `Access denied: Path '${requestedPath}' is outside allowed directories`, requestedPath, details);
31
+ }
32
+ function validateRequestedPath(requestedPath) {
33
+ ensureNonEmptyPath(requestedPath);
34
+ ensureNoNullBytes(requestedPath);
35
+ ensureNoReservedWindowsNames(requestedPath);
36
+ return normalizePath(requestedPath);
37
+ }
38
+ async function resolveRealPath(requestedPath, normalizedRequested) {
39
+ try {
40
+ return await fs.realpath(normalizedRequested);
41
+ }
42
+ catch (error) {
43
+ throw toMcpError(requestedPath, error);
44
+ }
45
+ }
46
+ async function validateExistingPathDetailsInternal(requestedPath) {
47
+ const normalizedRequested = validateRequestedPath(requestedPath);
48
+ ensureWithinAllowedDirectories(normalizedRequested, requestedPath, {
49
+ normalizedPath: normalizedRequested,
50
+ });
51
+ const realPath = await resolveRealPath(requestedPath, normalizedRequested);
52
+ const normalizedReal = normalizePath(realPath);
53
+ if (!isPathWithinAllowedDirectories(normalizedReal)) {
54
+ throw toAccessDeniedWithHint(requestedPath, realPath, normalizedReal);
55
+ }
56
+ return {
57
+ requestedPath: normalizedRequested,
58
+ resolvedPath: normalizedReal,
59
+ isSymlink: normalizeForComparison(normalizedRequested) !==
60
+ normalizeForComparison(normalizedReal),
61
+ };
62
+ }
63
+ export async function validateExistingPathDetailed(requestedPath) {
64
+ return validateExistingPathDetailsInternal(requestedPath);
65
+ }
66
+ export async function validateExistingPath(requestedPath) {
67
+ const details = await validateExistingPathDetailsInternal(requestedPath);
68
+ return details.resolvedPath;
69
+ }
70
+ //# sourceMappingURL=validators.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validators.js","sourceRoot":"","sources":["../../../src/lib/path-validation/validators.ts"],"names":[],"mappings":"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"}
@@ -1,8 +1,4 @@
1
- import type { Root } from '@modelcontextprotocol/sdk/types.js';
2
- import type { ValidatedPathDetails } from '../config/types.js';
3
- export declare function setAllowedDirectories(dirs: string[]): void;
4
- export declare function getAllowedDirectories(): string[];
5
- export declare function validateExistingPathDetailed(requestedPath: string): Promise<ValidatedPathDetails>;
6
- export declare function validateExistingPath(requestedPath: string): Promise<string>;
7
- export declare function getValidRootDirectories(roots: Root[]): Promise<string[]>;
1
+ export { getAllowedDirectories, setAllowedDirectories, setAllowedDirectoriesResolved, expandAllowedDirectories, RESERVED_DEVICE_NAMES, } from './path-validation/allowed-directories.js';
2
+ export { validateExistingPath, validateExistingPathDetailed, } from './path-validation/validators.js';
3
+ export { getValidRootDirectories } from './path-validation/roots.js';
8
4
  //# sourceMappingURL=path-validation.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"path-validation.d.ts","sourceRoot":"","sources":["../../src/lib/path-validation.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,oCAAoC,CAAC;AAE/D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAM/D,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAG1D;AAED,wBAAgB,qBAAqB,IAAI,MAAM,EAAE,CAEhD;AAoKD,wBAAsB,4BAA4B,CAChD,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC,oBAAoB,CAAC,CAE/B;AAED,wBAAsB,oBAAoB,CACxC,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC,MAAM,CAAC,CAGjB;AAED,wBAAsB,uBAAuB,CAC3C,KAAK,EAAE,IAAI,EAAE,GACZ,OAAO,CAAC,MAAM,EAAE,CAAC,CA8BnB"}
1
+ {"version":3,"file":"path-validation.d.ts","sourceRoot":"","sources":["../../src/lib/path-validation.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,qBAAqB,EACrB,qBAAqB,EACrB,6BAA6B,EAC7B,wBAAwB,EACxB,qBAAqB,GACtB,MAAM,0CAA0C,CAAC;AAClD,OAAO,EACL,oBAAoB,EACpB,4BAA4B,GAC7B,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,uBAAuB,EAAE,MAAM,4BAA4B,CAAC"}
@@ -1,142 +1,4 @@
1
- import * as fs from 'node:fs/promises';
2
- import { fileURLToPath } from 'node:url';
3
- import { ErrorCode, McpError } from './errors.js';
4
- import { normalizePath } from './path-utils.js';
5
- let allowedDirectories = [];
6
- export function setAllowedDirectories(dirs) {
7
- const normalized = dirs.map(normalizePath).filter((d) => d.length > 0);
8
- allowedDirectories = [...new Set(normalized)];
9
- }
10
- export function getAllowedDirectories() {
11
- return [...allowedDirectories];
12
- }
13
- const PATH_SEPARATOR = process.platform === 'win32' ? '\\' : '/';
14
- function normalizeForComparison(p) {
15
- return process.platform === 'win32' ? p.toLowerCase() : p;
16
- }
17
- function isPathWithinAllowedDirectories(normalizedPath) {
18
- const candidate = normalizeForComparison(normalizedPath);
19
- return allowedDirectories.some((allowedDir) => {
20
- const allowed = normalizeForComparison(allowedDir);
21
- return (candidate === allowed || candidate.startsWith(allowed + PATH_SEPARATOR));
22
- });
23
- }
24
- const RESERVED_DEVICE_NAMES = new Set([
25
- 'CON',
26
- 'PRN',
27
- 'AUX',
28
- 'NUL',
29
- 'COM1',
30
- 'COM2',
31
- 'COM3',
32
- 'COM4',
33
- 'COM5',
34
- 'COM6',
35
- 'COM7',
36
- 'COM8',
37
- 'COM9',
38
- 'LPT1',
39
- 'LPT2',
40
- 'LPT3',
41
- 'LPT4',
42
- 'LPT5',
43
- 'LPT6',
44
- 'LPT7',
45
- 'LPT8',
46
- 'LPT9',
47
- ]);
48
- async function validateExistingPathDetailsInternal(requestedPath) {
49
- if (!requestedPath || requestedPath.trim().length === 0) {
50
- throw new McpError(ErrorCode.E_INVALID_INPUT, 'Path cannot be empty or whitespace', requestedPath);
51
- }
52
- // Check for null bytes (path truncation attack prevention)
53
- if (requestedPath.includes('\0')) {
54
- throw new McpError(ErrorCode.E_INVALID_INPUT, 'Path contains null bytes', requestedPath);
55
- }
56
- // Check for Windows reserved device names
57
- if (process.platform === 'win32') {
58
- const segments = requestedPath.split(/[\\/]/);
59
- for (const segment of segments) {
60
- const baseName = segment.split('.')[0]?.toUpperCase();
61
- if (baseName && RESERVED_DEVICE_NAMES.has(baseName)) {
62
- throw new McpError(ErrorCode.E_INVALID_INPUT, `Windows reserved device name not allowed: ${baseName}`, requestedPath);
63
- }
64
- }
65
- }
66
- const normalizedRequested = normalizePath(requestedPath);
67
- if (!isPathWithinAllowedDirectories(normalizedRequested)) {
68
- throw new McpError(ErrorCode.E_ACCESS_DENIED, `Access denied: Path '${requestedPath}' is outside allowed directories`, requestedPath, { normalizedPath: normalizedRequested });
69
- }
70
- let realPath;
71
- try {
72
- realPath = await fs.realpath(normalizedRequested);
73
- }
74
- catch (error) {
75
- const nodeError = error;
76
- if (nodeError.code === 'ENOENT') {
77
- throw new McpError(ErrorCode.E_NOT_FOUND, `Path does not exist: ${requestedPath}`, requestedPath, { originalCode: nodeError.code }, error);
78
- }
79
- if (nodeError.code === 'EACCES' || nodeError.code === 'EPERM') {
80
- throw new McpError(ErrorCode.E_PERMISSION_DENIED, `Permission denied accessing path: ${requestedPath}`, requestedPath, { originalCode: nodeError.code }, error);
81
- }
82
- if (nodeError.code === 'ELOOP') {
83
- throw new McpError(ErrorCode.E_SYMLINK_NOT_ALLOWED, `Too many symbolic links in path (possible circular reference): ${requestedPath}`, requestedPath, { originalCode: nodeError.code }, error);
84
- }
85
- if (nodeError.code === 'ENAMETOOLONG') {
86
- throw new McpError(ErrorCode.E_INVALID_INPUT, `Path name too long: ${requestedPath}`, requestedPath, { originalCode: nodeError.code }, error);
87
- }
88
- throw new McpError(ErrorCode.E_NOT_FOUND, `Path is not accessible: ${requestedPath}`, requestedPath, { originalCode: nodeError.code, originalMessage: nodeError.message }, error);
89
- }
90
- const normalizedReal = normalizePath(realPath);
91
- if (!isPathWithinAllowedDirectories(normalizedReal)) {
92
- const allowedDirs = getAllowedDirectories();
93
- const suggestion = allowedDirs.length > 0
94
- ? `Allowed directories:\n${allowedDirs.map((d) => ` - ${d}`).join('\n')}`
95
- : 'No allowed directories configured. Use CLI arguments or MCP roots protocol.';
96
- throw new McpError(ErrorCode.E_ACCESS_DENIED, `Access denied: Path '${requestedPath}' is outside allowed directories.\n\n${suggestion}`, requestedPath, { resolvedPath: realPath, normalizedResolvedPath: normalizedReal });
97
- }
98
- const isSymlink = normalizedRequested !== normalizedReal;
99
- return {
100
- requestedPath: normalizedRequested,
101
- resolvedPath: normalizedReal,
102
- isSymlink,
103
- };
104
- }
105
- export async function validateExistingPathDetailed(requestedPath) {
106
- return validateExistingPathDetailsInternal(requestedPath);
107
- }
108
- export async function validateExistingPath(requestedPath) {
109
- const details = await validateExistingPathDetailsInternal(requestedPath);
110
- return details.resolvedPath;
111
- }
112
- export async function getValidRootDirectories(roots) {
113
- const validDirs = [];
114
- for (const root of roots) {
115
- if (!root.uri.startsWith('file://')) {
116
- continue;
117
- }
118
- try {
119
- const dirPath = fileURLToPath(root.uri);
120
- const normalizedPath = normalizePath(dirPath);
121
- const stats = await fs.stat(normalizedPath);
122
- if (stats.isDirectory()) {
123
- try {
124
- const realPath = await fs.realpath(normalizedPath);
125
- validDirs.push(normalizePath(realPath));
126
- }
127
- catch {
128
- // If realpath fails, use the normalized path
129
- validDirs.push(normalizedPath);
130
- }
131
- }
132
- else {
133
- console.error(`Skipping root (not a directory): ${normalizedPath}`);
134
- }
135
- }
136
- catch {
137
- continue;
138
- }
139
- }
140
- return validDirs;
141
- }
1
+ export { getAllowedDirectories, setAllowedDirectories, setAllowedDirectoriesResolved, expandAllowedDirectories, RESERVED_DEVICE_NAMES, } from './path-validation/allowed-directories.js';
2
+ export { validateExistingPath, validateExistingPathDetailed, } from './path-validation/validators.js';
3
+ export { getValidRootDirectories } from './path-validation/roots.js';
142
4
  //# sourceMappingURL=path-validation.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"path-validation.js","sourceRoot":"","sources":["../../src/lib/path-validation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAKzC,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD,IAAI,kBAAkB,GAAa,EAAE,CAAC;AAEtC,MAAM,UAAU,qBAAqB,CAAC,IAAc;IAClD,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACvE,kBAAkB,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC;AAChD,CAAC;AAED,MAAM,UAAU,qBAAqB;IACnC,OAAO,CAAC,GAAG,kBAAkB,CAAC,CAAC;AACjC,CAAC;AAED,MAAM,cAAc,GAAG,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC;AAEjE,SAAS,sBAAsB,CAAC,CAAS;IACvC,OAAO,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;AAC5D,CAAC;AAED,SAAS,8BAA8B,CAAC,cAAsB;IAC5D,MAAM,SAAS,GAAG,sBAAsB,CAAC,cAAc,CAAC,CAAC;IACzD,OAAO,kBAAkB,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,EAAE;QAC5C,MAAM,OAAO,GAAG,sBAAsB,CAAC,UAAU,CAAC,CAAC;QACnD,OAAO,CACL,SAAS,KAAK,OAAO,IAAI,SAAS,CAAC,UAAU,CAAC,OAAO,GAAG,cAAc,CAAC,CACxE,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,qBAAqB,GAAG,IAAI,GAAG,CAAC;IACpC,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;CACP,CAAC,CAAC;AAEH,KAAK,UAAU,mCAAmC,CAChD,aAAqB;IAErB,IAAI,CAAC,aAAa,IAAI,aAAa,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxD,MAAM,IAAI,QAAQ,CAChB,SAAS,CAAC,eAAe,EACzB,oCAAoC,EACpC,aAAa,CACd,CAAC;IACJ,CAAC;IAED,2DAA2D;IAC3D,IAAI,aAAa,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACjC,MAAM,IAAI,QAAQ,CAChB,SAAS,CAAC,eAAe,EACzB,0BAA0B,EAC1B,aAAa,CACd,CAAC;IACJ,CAAC;IAED,0CAA0C;IAC1C,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;QACjC,MAAM,QAAQ,GAAG,aAAa,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAC9C,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YAC/B,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC;YACtD,IAAI,QAAQ,IAAI,qBAAqB,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACpD,MAAM,IAAI,QAAQ,CAChB,SAAS,CAAC,eAAe,EACzB,6CAA6C,QAAQ,EAAE,EACvD,aAAa,CACd,CAAC;YACJ,CAAC;QACH,CAAC;IACH,CAAC;IAED,MAAM,mBAAmB,GAAG,aAAa,CAAC,aAAa,CAAC,CAAC;IAEzD,IAAI,CAAC,8BAA8B,CAAC,mBAAmB,CAAC,EAAE,CAAC;QACzD,MAAM,IAAI,QAAQ,CAChB,SAAS,CAAC,eAAe,EACzB,wBAAwB,aAAa,kCAAkC,EACvE,aAAa,EACb,EAAE,cAAc,EAAE,mBAAmB,EAAE,CACxC,CAAC;IACJ,CAAC;IAED,IAAI,QAAgB,CAAC;IACrB,IAAI,CAAC;QACH,QAAQ,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,mBAAmB,CAAC,CAAC;IACpD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,SAAS,GAAG,KAA8B,CAAC;QACjD,IAAI,SAAS,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAChC,MAAM,IAAI,QAAQ,CAChB,SAAS,CAAC,WAAW,EACrB,wBAAwB,aAAa,EAAE,EACvC,aAAa,EACb,EAAE,YAAY,EAAE,SAAS,CAAC,IAAI,EAAE,EAChC,KAAK,CACN,CAAC;QACJ,CAAC;QACD,IAAI,SAAS,CAAC,IAAI,KAAK,QAAQ,IAAI,SAAS,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;YAC9D,MAAM,IAAI,QAAQ,CAChB,SAAS,CAAC,mBAAmB,EAC7B,qCAAqC,aAAa,EAAE,EACpD,aAAa,EACb,EAAE,YAAY,EAAE,SAAS,CAAC,IAAI,EAAE,EAChC,KAAK,CACN,CAAC;QACJ,CAAC;QACD,IAAI,SAAS,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;YAC/B,MAAM,IAAI,QAAQ,CAChB,SAAS,CAAC,qBAAqB,EAC/B,kEAAkE,aAAa,EAAE,EACjF,aAAa,EACb,EAAE,YAAY,EAAE,SAAS,CAAC,IAAI,EAAE,EAChC,KAAK,CACN,CAAC;QACJ,CAAC;QACD,IAAI,SAAS,CAAC,IAAI,KAAK,cAAc,EAAE,CAAC;YACtC,MAAM,IAAI,QAAQ,CAChB,SAAS,CAAC,eAAe,EACzB,uBAAuB,aAAa,EAAE,EACtC,aAAa,EACb,EAAE,YAAY,EAAE,SAAS,CAAC,IAAI,EAAE,EAChC,KAAK,CACN,CAAC;QACJ,CAAC;QACD,MAAM,IAAI,QAAQ,CAChB,SAAS,CAAC,WAAW,EACrB,2BAA2B,aAAa,EAAE,EAC1C,aAAa,EACb,EAAE,YAAY,EAAE,SAAS,CAAC,IAAI,EAAE,eAAe,EAAE,SAAS,CAAC,OAAO,EAAE,EACpE,KAAK,CACN,CAAC;IACJ,CAAC;IACD,MAAM,cAAc,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC;IAE/C,IAAI,CAAC,8BAA8B,CAAC,cAAc,CAAC,EAAE,CAAC;QACpD,MAAM,WAAW,GAAG,qBAAqB,EAAE,CAAC;QAC5C,MAAM,UAAU,GACd,WAAW,CAAC,MAAM,GAAG,CAAC;YACpB,CAAC,CAAC,yBAAyB,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;YAC1E,CAAC,CAAC,6EAA6E,CAAC;QAEpF,MAAM,IAAI,QAAQ,CAChB,SAAS,CAAC,eAAe,EACzB,wBAAwB,aAAa,wCAAwC,UAAU,EAAE,EACzF,aAAa,EACb,EAAE,YAAY,EAAE,QAAQ,EAAE,sBAAsB,EAAE,cAAc,EAAE,CACnE,CAAC;IACJ,CAAC;IAED,MAAM,SAAS,GAAG,mBAAmB,KAAK,cAAc,CAAC;IAEzD,OAAO;QACL,aAAa,EAAE,mBAAmB;QAClC,YAAY,EAAE,cAAc;QAC5B,SAAS;KACV,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,4BAA4B,CAChD,aAAqB;IAErB,OAAO,mCAAmC,CAAC,aAAa,CAAC,CAAC;AAC5D,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,aAAqB;IAErB,MAAM,OAAO,GAAG,MAAM,mCAAmC,CAAC,aAAa,CAAC,CAAC;IACzE,OAAO,OAAO,CAAC,YAAY,CAAC;AAC9B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,KAAa;IAEb,MAAM,SAAS,GAAa,EAAE,CAAC;IAE/B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YACpC,SAAS;QACX,CAAC;QAED,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,aAAa,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACxC,MAAM,cAAc,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC;YAE9C,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;YAC5C,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;gBACxB,IAAI,CAAC;oBACH,MAAM,QAAQ,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC;oBACnD,SAAS,CAAC,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC,CAAC;gBAC1C,CAAC;gBAAC,MAAM,CAAC;oBACP,6CAA6C;oBAC7C,SAAS,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;gBACjC,CAAC;YACH,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,KAAK,CAAC,oCAAoC,cAAc,EAAE,CAAC,CAAC;YACtE,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,SAAS;QACX,CAAC;IACH,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC"}
1
+ {"version":3,"file":"path-validation.js","sourceRoot":"","sources":["../../src/lib/path-validation.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,qBAAqB,EACrB,qBAAqB,EACrB,6BAA6B,EAC7B,wBAAwB,EACxB,qBAAqB,GACtB,MAAM,0CAA0C,CAAC;AAClD,OAAO,EACL,oBAAoB,EACpB,4BAA4B,GAC7B,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,uBAAuB,EAAE,MAAM,4BAA4B,CAAC"}
@@ -0,0 +1,25 @@
1
+ interface OperationMetrics {
2
+ operation: string;
3
+ duration: number;
4
+ timestamp: number;
5
+ }
6
+ declare class PerformanceMonitor {
7
+ private observer?;
8
+ private metrics;
9
+ private readonly enabled;
10
+ constructor(enabled?: boolean);
11
+ private initObserver;
12
+ startOperation(name: string): void;
13
+ endOperation(name: string): void;
14
+ getMetrics(): OperationMetrics[];
15
+ getSummary(): Record<string, {
16
+ count: number;
17
+ avgDuration: number;
18
+ totalDuration: number;
19
+ }>;
20
+ clear(): void;
21
+ dispose(): void;
22
+ }
23
+ export declare const perfMonitor: PerformanceMonitor;
24
+ export {};
25
+ //# sourceMappingURL=monitor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"monitor.d.ts","sourceRoot":"","sources":["../../../src/lib/performance/monitor.ts"],"names":[],"mappings":"AAEA,UAAU,gBAAgB;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,cAAM,kBAAkB;IACtB,OAAO,CAAC,QAAQ,CAAC,CAAsB;IACvC,OAAO,CAAC,OAAO,CAA0B;IACzC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAU;gBAEtB,OAAO,UAAQ;IAO3B,OAAO,CAAC,YAAY;IAoBpB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAKlC,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAOhC,UAAU,IAAI,gBAAgB,EAAE;IAIhC,UAAU,IAAI,MAAM,CAClB,MAAM,EACN;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,CAAA;KAAE,CAC9D;IA6BD,KAAK,IAAI,IAAI;IAMb,OAAO,IAAI,IAAI;CAGhB;AAID,eAAO,MAAM,WAAW,oBAAoC,CAAC"}
@@ -0,0 +1,84 @@
1
+ import { performance, PerformanceObserver } from 'node:perf_hooks';
2
+ class PerformanceMonitor {
3
+ observer;
4
+ metrics = [];
5
+ enabled;
6
+ constructor(enabled = false) {
7
+ this.enabled = enabled;
8
+ if (this.enabled) {
9
+ this.initObserver();
10
+ }
11
+ }
12
+ initObserver() {
13
+ this.observer = new PerformanceObserver((list) => {
14
+ for (const entry of list.getEntries()) {
15
+ this.metrics.push({
16
+ operation: entry.name,
17
+ duration: entry.duration,
18
+ timestamp: entry.startTime,
19
+ });
20
+ // Log slow operations (>1s) to console
21
+ if (entry.duration > 1000) {
22
+ console.warn(`[PERF] Slow operation: ${entry.name} took ${entry.duration.toFixed(2)}ms`);
23
+ }
24
+ }
25
+ });
26
+ this.observer.observe({ entryTypes: ['measure'] });
27
+ }
28
+ startOperation(name) {
29
+ if (!this.enabled)
30
+ return;
31
+ performance.mark(`${name}-start`);
32
+ }
33
+ endOperation(name) {
34
+ if (!this.enabled)
35
+ return;
36
+ const endMark = `${name}-end`;
37
+ performance.mark(endMark);
38
+ performance.measure(name, `${name}-start`, endMark);
39
+ }
40
+ getMetrics() {
41
+ return [...this.metrics];
42
+ }
43
+ getSummary() {
44
+ const summary = {};
45
+ for (const metric of this.metrics) {
46
+ summary[metric.operation] ??= {
47
+ count: 0,
48
+ avgDuration: 0,
49
+ totalDuration: 0,
50
+ };
51
+ const entry = summary[metric.operation];
52
+ if (entry) {
53
+ entry.count++;
54
+ entry.totalDuration += metric.duration;
55
+ }
56
+ }
57
+ for (const op of Object.keys(summary)) {
58
+ const stats = summary[op];
59
+ if (stats) {
60
+ stats.avgDuration = stats.totalDuration / stats.count;
61
+ }
62
+ }
63
+ return summary;
64
+ }
65
+ clear() {
66
+ this.metrics = [];
67
+ performance.clearMarks();
68
+ performance.clearMeasures();
69
+ }
70
+ dispose() {
71
+ this.observer?.disconnect();
72
+ }
73
+ }
74
+ // Enable via environment variable
75
+ const isEnabled = process.env.ENABLE_PERF_MONITORING === 'true';
76
+ export const perfMonitor = new PerformanceMonitor(isEnabled);
77
+ // Cleanup on process exit
78
+ process.on('beforeExit', () => {
79
+ if (isEnabled) {
80
+ console.error('[PERF] Summary:', perfMonitor.getSummary());
81
+ }
82
+ perfMonitor.dispose();
83
+ });
84
+ //# sourceMappingURL=monitor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"monitor.js","sourceRoot":"","sources":["../../../src/lib/performance/monitor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ import { z } from 'zod';
2
+ export declare function isSafeGlobPattern(value: string): boolean;
3
+ export declare const EncodingSchema: z.ZodDefault<z.ZodOptional<z.ZodEnum<["utf-8", "utf8", "ascii", "base64", "hex", "latin1"]>>>;
4
+ export declare const ReadFileMaxSizeSchema: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
5
+ export declare const ReadMultipleFilesMaxSizeSchema: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
6
+ export declare const ExcludePatternsSchema: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodEffects<z.ZodString, string, string>, "many">>>;
7
+ export declare const BasicExcludePatternsSchema: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString, "many">>>;
8
+ export declare const MaxDepthSchema: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
9
+ export declare const MaxResultsSchema: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
10
+ export declare const MaxFilesScannedSchema: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
11
+ export declare const TimeoutMsSchema: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
12
+ export declare const TopNSchema: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
13
+ export declare const TreeMaxDepthSchema: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
14
+ export declare const IncludeHiddenSchema: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
15
+ export declare const SortByFileSchema: z.ZodDefault<z.ZodOptional<z.ZodEnum<["name", "size", "modified", "path"]>>>;
16
+ export declare const SortByDirectorySchema: z.ZodDefault<z.ZodOptional<z.ZodEnum<["name", "size", "modified", "type"]>>>;
17
+ export declare const MaxEntriesSchema: z.ZodOptional<z.ZodNumber>;
18
+ export declare const CaseSensitiveSchema: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
19
+ export declare const SkipBinarySchema: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
20
+ export declare const BaseNameMatchSchema: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
21
+ export declare const MaxFileSizeSearchSchema: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
22
+ export declare const ContextLinesSchema: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
23
+ export declare const HeadLinesSchema: z.ZodOptional<z.ZodNumber>;
24
+ export declare const TailLinesSchema: z.ZodOptional<z.ZodNumber>;
25
+ export declare const LineStartSchema: z.ZodOptional<z.ZodNumber>;
26
+ export declare const LineEndSchema: z.ZodOptional<z.ZodNumber>;
27
+ //# sourceMappingURL=input-helpers.d.ts.map