@j0hanz/filesystem-mcp 1.19.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (301) hide show
  1. package/README.md +333 -838
  2. package/dist/cli-help.d.ts +3 -0
  3. package/dist/cli-help.d.ts.map +1 -0
  4. package/dist/cli-help.js +169 -0
  5. package/dist/cli-help.js.map +1 -0
  6. package/dist/cli.d.ts +28 -0
  7. package/dist/cli.d.ts.map +1 -0
  8. package/dist/cli.js +168 -123
  9. package/dist/cli.js.map +1 -0
  10. package/dist/core/concurrency.d.ts +70 -0
  11. package/dist/core/concurrency.d.ts.map +1 -0
  12. package/dist/core/concurrency.js +173 -0
  13. package/dist/core/concurrency.js.map +1 -0
  14. package/dist/core/config.d.ts +19 -0
  15. package/dist/core/config.d.ts.map +1 -0
  16. package/dist/core/config.js +11 -0
  17. package/dist/core/config.js.map +1 -0
  18. package/dist/core/cursor.d.ts +23 -0
  19. package/dist/core/cursor.d.ts.map +1 -0
  20. package/dist/core/cursor.js +62 -0
  21. package/dist/core/cursor.js.map +1 -0
  22. package/dist/core/errors.d.ts +96 -0
  23. package/dist/core/errors.d.ts.map +1 -0
  24. package/dist/core/errors.js +356 -0
  25. package/dist/core/errors.js.map +1 -0
  26. package/dist/core/file-uri.d.ts +24 -0
  27. package/dist/core/file-uri.d.ts.map +1 -0
  28. package/dist/core/file-uri.js +52 -0
  29. package/dist/core/file-uri.js.map +1 -0
  30. package/dist/core/fmt.d.ts +38 -0
  31. package/dist/core/fmt.d.ts.map +1 -0
  32. package/dist/core/fmt.js +109 -0
  33. package/dist/core/fmt.js.map +1 -0
  34. package/dist/core/fs.d.ts +108 -0
  35. package/dist/core/fs.d.ts.map +1 -0
  36. package/dist/core/fs.js +243 -0
  37. package/dist/core/fs.js.map +1 -0
  38. package/dist/core/glob.d.ts +41 -0
  39. package/dist/core/glob.d.ts.map +1 -0
  40. package/dist/core/glob.js +399 -0
  41. package/dist/core/glob.js.map +1 -0
  42. package/dist/core/input-required.d.ts +147 -0
  43. package/dist/core/input-required.d.ts.map +1 -0
  44. package/dist/core/input-required.js +261 -0
  45. package/dist/core/input-required.js.map +1 -0
  46. package/dist/core/mime.d.ts +15 -0
  47. package/dist/core/mime.d.ts.map +1 -0
  48. package/dist/core/mime.js +188 -0
  49. package/dist/core/mime.js.map +1 -0
  50. package/dist/core/observability.d.ts +10 -0
  51. package/dist/core/observability.d.ts.map +1 -0
  52. package/dist/core/observability.js +76 -0
  53. package/dist/core/observability.js.map +1 -0
  54. package/dist/core/page-store.d.ts +41 -0
  55. package/dist/core/page-store.d.ts.map +1 -0
  56. package/dist/core/page-store.js +74 -0
  57. package/dist/core/page-store.js.map +1 -0
  58. package/dist/core/path-completer.d.ts +10 -0
  59. package/dist/core/path-completer.d.ts.map +1 -0
  60. package/dist/core/path-completer.js +227 -0
  61. package/dist/core/path-completer.js.map +1 -0
  62. package/dist/core/path-discovery.d.ts +8 -0
  63. package/dist/core/path-discovery.d.ts.map +1 -0
  64. package/dist/core/path-discovery.js +105 -0
  65. package/dist/core/path-discovery.js.map +1 -0
  66. package/dist/core/path-utils.d.ts +9 -0
  67. package/dist/core/path-utils.d.ts.map +1 -0
  68. package/dist/core/path-utils.js +121 -0
  69. package/dist/core/path-utils.js.map +1 -0
  70. package/dist/core/path.d.ts +148 -0
  71. package/dist/core/path.d.ts.map +1 -0
  72. package/dist/core/path.js +674 -0
  73. package/dist/core/path.js.map +1 -0
  74. package/dist/core/primitives.d.ts +23 -0
  75. package/dist/core/primitives.d.ts.map +1 -0
  76. package/dist/core/primitives.js +54 -0
  77. package/dist/core/primitives.js.map +1 -0
  78. package/dist/core/read.d.ts +74 -0
  79. package/dist/core/read.d.ts.map +1 -0
  80. package/dist/core/read.js +562 -0
  81. package/dist/core/read.js.map +1 -0
  82. package/dist/core/schema.d.ts +139 -0
  83. package/dist/core/schema.d.ts.map +1 -0
  84. package/dist/core/schema.js +345 -0
  85. package/dist/core/schema.js.map +1 -0
  86. package/dist/core/search.d.ts +100 -0
  87. package/dist/core/search.d.ts.map +1 -0
  88. package/dist/core/search.js +248 -0
  89. package/dist/core/search.js.map +1 -0
  90. package/dist/core/sensitive.d.ts +6 -0
  91. package/dist/core/sensitive.d.ts.map +1 -0
  92. package/dist/core/sensitive.js +142 -0
  93. package/dist/core/sensitive.js.map +1 -0
  94. package/dist/core/store.d.ts +57 -0
  95. package/dist/core/store.d.ts.map +1 -0
  96. package/dist/core/store.js +162 -0
  97. package/dist/core/store.js.map +1 -0
  98. package/dist/core/util.d.ts +26 -0
  99. package/dist/core/util.d.ts.map +1 -0
  100. package/dist/core/util.js +66 -0
  101. package/dist/core/util.js.map +1 -0
  102. package/dist/core/watcher-registry.d.ts +68 -0
  103. package/dist/core/watcher-registry.d.ts.map +1 -0
  104. package/dist/core/watcher-registry.js +312 -0
  105. package/dist/core/watcher-registry.js.map +1 -0
  106. package/dist/http-policy.d.ts +121 -0
  107. package/dist/http-policy.d.ts.map +1 -0
  108. package/dist/http-policy.js +340 -0
  109. package/dist/http-policy.js.map +1 -0
  110. package/dist/index.d.ts +1 -0
  111. package/dist/index.d.ts.map +1 -0
  112. package/dist/index.js +77 -41
  113. package/dist/index.js.map +1 -0
  114. package/dist/instructions.d.ts +12 -0
  115. package/dist/instructions.d.ts.map +1 -0
  116. package/dist/instructions.js +71 -0
  117. package/dist/instructions.js.map +1 -0
  118. package/dist/prompts.d.ts +8 -6
  119. package/dist/prompts.d.ts.map +1 -0
  120. package/dist/prompts.js +74 -168
  121. package/dist/prompts.js.map +1 -0
  122. package/dist/resources.d.ts +73 -9
  123. package/dist/resources.d.ts.map +1 -0
  124. package/dist/resources.js +392 -163
  125. package/dist/resources.js.map +1 -0
  126. package/dist/server.d.ts +62 -1
  127. package/dist/server.d.ts.map +1 -0
  128. package/dist/server.js +139 -1
  129. package/dist/server.js.map +1 -0
  130. package/dist/tools/batch.d.ts +89 -0
  131. package/dist/tools/batch.d.ts.map +1 -0
  132. package/dist/tools/batch.js +157 -0
  133. package/dist/tools/batch.js.map +1 -0
  134. package/dist/tools/create.d.ts +2 -0
  135. package/dist/tools/create.d.ts.map +1 -0
  136. package/dist/tools/create.js +142 -0
  137. package/dist/tools/create.js.map +1 -0
  138. package/dist/tools/define.d.ts +110 -0
  139. package/dist/tools/define.d.ts.map +1 -0
  140. package/dist/tools/define.js +394 -0
  141. package/dist/tools/define.js.map +1 -0
  142. package/dist/tools/delete-file.d.ts +2 -4
  143. package/dist/tools/delete-file.d.ts.map +1 -0
  144. package/dist/tools/delete-file.js +330 -87
  145. package/dist/tools/delete-file.js.map +1 -0
  146. package/dist/tools/diff.d.ts +2 -0
  147. package/dist/tools/diff.d.ts.map +1 -0
  148. package/dist/tools/diff.js +94 -0
  149. package/dist/tools/diff.js.map +1 -0
  150. package/dist/tools/edit.d.ts +2 -0
  151. package/dist/tools/edit.d.ts.map +1 -0
  152. package/dist/tools/edit.js +442 -0
  153. package/dist/tools/edit.js.map +1 -0
  154. package/dist/tools/index.d.ts +26 -0
  155. package/dist/tools/index.d.ts.map +1 -0
  156. package/dist/tools/index.js +52 -0
  157. package/dist/tools/index.js.map +1 -0
  158. package/dist/tools/list.d.ts +2 -0
  159. package/dist/tools/list.d.ts.map +1 -0
  160. package/dist/tools/list.js +291 -0
  161. package/dist/tools/list.js.map +1 -0
  162. package/dist/tools/move.d.ts +2 -0
  163. package/dist/tools/move.d.ts.map +1 -0
  164. package/dist/tools/move.js +321 -0
  165. package/dist/tools/move.js.map +1 -0
  166. package/dist/tools/patch.d.ts +2 -0
  167. package/dist/tools/patch.d.ts.map +1 -0
  168. package/dist/tools/patch.js +155 -0
  169. package/dist/tools/patch.js.map +1 -0
  170. package/dist/tools/progress.d.ts +52 -0
  171. package/dist/tools/progress.d.ts.map +1 -0
  172. package/dist/tools/progress.js +172 -0
  173. package/dist/tools/progress.js.map +1 -0
  174. package/dist/tools/read.d.ts +2 -4
  175. package/dist/tools/read.d.ts.map +1 -0
  176. package/dist/tools/read.js +398 -152
  177. package/dist/tools/read.js.map +1 -0
  178. package/dist/tools/replace-in-files.d.ts +2 -4
  179. package/dist/tools/replace-in-files.d.ts.map +1 -0
  180. package/dist/tools/replace-in-files.js +435 -264
  181. package/dist/tools/replace-in-files.js.map +1 -0
  182. package/dist/tools/roots.d.ts +2 -4
  183. package/dist/tools/roots.d.ts.map +1 -0
  184. package/dist/tools/roots.js +29 -52
  185. package/dist/tools/roots.js.map +1 -0
  186. package/dist/tools/search-content.d.ts +2 -4
  187. package/dist/tools/search-content.d.ts.map +1 -0
  188. package/dist/tools/search-content.js +262 -228
  189. package/dist/tools/search-content.js.map +1 -0
  190. package/dist/tools/search-files.d.ts +2 -4
  191. package/dist/tools/search-files.d.ts.map +1 -0
  192. package/dist/tools/search-files.js +162 -161
  193. package/dist/tools/search-files.js.map +1 -0
  194. package/dist/tools/stat.d.ts +2 -4
  195. package/dist/tools/stat.d.ts.map +1 -0
  196. package/dist/tools/stat.js +202 -62
  197. package/dist/tools/stat.js.map +1 -0
  198. package/dist/transport/http.d.ts +5 -0
  199. package/dist/transport/http.d.ts.map +1 -0
  200. package/dist/transport/http.js +276 -0
  201. package/dist/transport/http.js.map +1 -0
  202. package/dist/transport/shared.d.ts +45 -0
  203. package/dist/transport/shared.d.ts.map +1 -0
  204. package/dist/transport/shared.js +65 -0
  205. package/dist/transport/shared.js.map +1 -0
  206. package/dist/transport/stdio.d.ts +32 -0
  207. package/dist/transport/stdio.d.ts.map +1 -0
  208. package/dist/transport/stdio.js +279 -0
  209. package/dist/transport/stdio.js.map +1 -0
  210. package/dist/transport.d.ts +5 -0
  211. package/dist/transport.d.ts.map +1 -0
  212. package/dist/transport.js +4 -0
  213. package/dist/transport.js.map +1 -0
  214. package/package.json +37 -46
  215. package/dist/assets/logo.svg +0 -35
  216. package/dist/completions.d.ts +0 -2
  217. package/dist/completions.js +0 -572
  218. package/dist/config.d.ts +0 -119
  219. package/dist/config.js +0 -31
  220. package/dist/lib/abort.d.ts +0 -7
  221. package/dist/lib/abort.js +0 -81
  222. package/dist/lib/constants.d.ts +0 -42
  223. package/dist/lib/constants.js +0 -313
  224. package/dist/lib/errors.d.ts +0 -28
  225. package/dist/lib/errors.js +0 -301
  226. package/dist/lib/file-operations/core.d.ts +0 -53
  227. package/dist/lib/file-operations/core.js +0 -144
  228. package/dist/lib/file-operations/metadata.d.ts +0 -77
  229. package/dist/lib/file-operations/metadata.js +0 -878
  230. package/dist/lib/file-operations/search.d.ts +0 -46
  231. package/dist/lib/file-operations/search.js +0 -1194
  232. package/dist/lib/file-operations/traversal.d.ts +0 -40
  233. package/dist/lib/file-operations/traversal.js +0 -310
  234. package/dist/lib/fs-helpers.d.ts +0 -46
  235. package/dist/lib/fs-helpers.js +0 -606
  236. package/dist/lib/globs.d.ts +0 -2
  237. package/dist/lib/globs.js +0 -19
  238. package/dist/lib/logger.d.ts +0 -27
  239. package/dist/lib/logger.js +0 -91
  240. package/dist/lib/observability.d.ts +0 -33
  241. package/dist/lib/observability.js +0 -373
  242. package/dist/lib/paths.d.ts +0 -35
  243. package/dist/lib/paths.js +0 -634
  244. package/dist/lib/resource-store.d.ts +0 -28
  245. package/dist/lib/resource-store.js +0 -195
  246. package/dist/lib/utils.d.ts +0 -7
  247. package/dist/lib/utils.js +0 -37
  248. package/dist/lib/zod-codecs.d.ts +0 -2
  249. package/dist/lib/zod-codecs.js +0 -18
  250. package/dist/pkg-info.d.ts +0 -7
  251. package/dist/pkg-info.js +0 -9
  252. package/dist/resources/generated-instructions.d.ts +0 -1
  253. package/dist/resources/generated-instructions.js +0 -105
  254. package/dist/resources/tool-catalog.d.ts +0 -2
  255. package/dist/resources/tool-catalog.js +0 -78
  256. package/dist/resources/tool-info.d.ts +0 -9
  257. package/dist/resources/tool-info.js +0 -206
  258. package/dist/resources/workflows.d.ts +0 -1
  259. package/dist/resources/workflows.js +0 -72
  260. package/dist/schemas.d.ts +0 -505
  261. package/dist/schemas.js +0 -676
  262. package/dist/server/bootstrap.d.ts +0 -6
  263. package/dist/server/bootstrap.js +0 -563
  264. package/dist/server/event-store.d.ts +0 -18
  265. package/dist/server/event-store.js +0 -71
  266. package/dist/server/roots-manager.d.ts +0 -28
  267. package/dist/server/roots-manager.js +0 -227
  268. package/dist/server/task-store.d.ts +0 -10
  269. package/dist/server/task-store.js +0 -91
  270. package/dist/tools/apply-patch.d.ts +0 -4
  271. package/dist/tools/apply-patch.js +0 -235
  272. package/dist/tools/calculate-hash.d.ts +0 -4
  273. package/dist/tools/calculate-hash.js +0 -187
  274. package/dist/tools/contract.d.ts +0 -50
  275. package/dist/tools/contract.js +0 -1
  276. package/dist/tools/create-directory.d.ts +0 -4
  277. package/dist/tools/create-directory.js +0 -68
  278. package/dist/tools/diff-files.d.ts +0 -4
  279. package/dist/tools/diff-files.js +0 -136
  280. package/dist/tools/edit-file.d.ts +0 -4
  281. package/dist/tools/edit-file.js +0 -256
  282. package/dist/tools/icons.d.ts +0 -15
  283. package/dist/tools/icons.js +0 -24
  284. package/dist/tools/list-directory.d.ts +0 -4
  285. package/dist/tools/list-directory.js +0 -218
  286. package/dist/tools/move-file.d.ts +0 -4
  287. package/dist/tools/move-file.js +0 -178
  288. package/dist/tools/read-multiple.d.ts +0 -4
  289. package/dist/tools/read-multiple.js +0 -207
  290. package/dist/tools/shared.d.ts +0 -172
  291. package/dist/tools/shared.js +0 -599
  292. package/dist/tools/stat-many.d.ts +0 -4
  293. package/dist/tools/stat-many.js +0 -104
  294. package/dist/tools/task-support.d.ts +0 -29
  295. package/dist/tools/task-support.js +0 -472
  296. package/dist/tools/tree.d.ts +0 -4
  297. package/dist/tools/tree.js +0 -102
  298. package/dist/tools/write-file.d.ts +0 -4
  299. package/dist/tools/write-file.js +0 -60
  300. package/dist/tools.d.ts +0 -5
  301. package/dist/tools.js +0 -54
@@ -0,0 +1,71 @@
1
+ import { DEFAULT_SEARCH_CONTENT_RESULTS, getMaxTextFileSize, MAX_SEARCH_RESULTS, } from './core/util.js';
2
+ import { GET_FILE_INFO, LIST, LIST_ALLOWED_DIRECTORIES, MUTATING_TOOL_NAMES, READ_FILE, SEARCH_CONTENT, SEARCH_FILES, } from './tools/index.js';
3
+ function buildToolsOverview(readOnly) {
4
+ const rows = [
5
+ ['Navigate', [LIST_ALLOWED_DIRECTORIES.name, LIST.name, SEARCH_FILES.name]],
6
+ ['Inspect', [GET_FILE_INFO.name, SEARCH_CONTENT.name]],
7
+ ['Read', [READ_FILE.name]],
8
+ ];
9
+ // Under --read-only the mutating tools are never registered, so advertising
10
+ // them here would point the model at tools that are not there. Drop the row
11
+ // rather than emit an empty one.
12
+ if (!readOnly) {
13
+ rows.push(['Write', [...MUTATING_TOOL_NAMES]]);
14
+ }
15
+ const rowLines = rows.map(([cat, names]) => `${cat}: ${names.join(', ')}`);
16
+ return `\`\`\`\n${rowLines.join('\n')}\n\`\`\``;
17
+ }
18
+ export const INSTRUCTIONS_URI = 'internal://instructions';
19
+ export const NO_POSITIONAL_ROOTS_GUIDANCE = 'No positional directories specified. Configure roots with directory arguments, FS_ALLOWED_DIRS, or --allow-cwd. Modern clients with elicitation can also call a tool with a concrete path and approve the requested grant.';
20
+ /**
21
+ * The one statement of what this server is and how to approach it. The server's
22
+ * `instructions`, the `get-help` prompt, and the instructions resource all
23
+ * describe the same document, and three hand-maintained paraphrases of it drift
24
+ * against each other and cost the client the same sentence three times.
25
+ */
26
+ export const INSTRUCTIONS_SUMMARY = 'Navigation guide for filesystem-mcp tools and constraints. ' +
27
+ 'Use list_roots to inspect configured or accepted roots, then list/find_files -> stat -> read. Never guess paths.';
28
+ export function buildSectionsRecord(readOnly) {
29
+ const maxFileMb = Math.floor(getMaxTextFileSize() / 1024 / 1024);
30
+ return {
31
+ guidelines: [
32
+ 'Guidelines:',
33
+ '```',
34
+ `root_access: ${LIST_ALLOWED_DIRECTORIES.name} lists configured or accepted roots; every other tool is scoped to them.`,
35
+ 'modern_root_grants: Modern clients do not automatically send workspace roots. Call a tool with a concrete path and approve its grant when elicitation is available.',
36
+ `path_resolution: Confirm a path with ${LIST.name} or ${SEARCH_FILES.name} before acting on it.`,
37
+ '```',
38
+ ].join('\n'),
39
+ tools_overview: [
40
+ 'Tools Overview:',
41
+ buildToolsOverview(readOnly),
42
+ '',
43
+ 'Full schemas, descriptions, and annotations are in `tools/list`.',
44
+ ].join('\n'),
45
+ constraints: [
46
+ 'Constraints:',
47
+ '```',
48
+ `allowed_roots: Startup roots come from CLI paths, FS_ALLOWED_DIRS, or --allow-cwd; accepted modern grants are additive. Call ${LIST_ALLOWED_DIRECTORIES.name} to read the current set.`,
49
+ 'legacy_roots: Legacy clients may additionally seed roots through the deprecated roots/list flow.',
50
+ 'sensitive_paths: Sensitive file paths (.env, *.pem, *id_rsa*) are denied by default.',
51
+ `enforced_limits: max file size ${maxFileMb} MB, file search cap ${MAX_SEARCH_RESULTS} results, content search cap ${DEFAULT_SEARCH_CONTENT_RESULTS} matches.`,
52
+ 'ephemeral_results: When a tool returns resourceUri, call resources/read immediately — cached results are ephemeral and expire after ~60 seconds, eviction, or restart.',
53
+ 'pagination: nextCursor is backed by a snapshot on the same ~60s clock. Page through promptly; if a cursor is rejected, start again without one. resourceUri appears on the first page only.',
54
+ '```',
55
+ ].join('\n'),
56
+ error_recovery: [
57
+ 'Error Recovery:',
58
+ '```',
59
+ `ACCESS_DENIED: Run ${LIST_ALLOWED_DIRECTORIES.name}; configure a missing startup root or retry a concrete path and approve the grant.`,
60
+ `NOT_FOUND: Run ${LIST.name} or ${SEARCH_FILES.name} to verify the path.`,
61
+ `TOO_LARGE: Use ${READ_FILE.name} with head/tail or startLine/endLine, or split across several calls.`,
62
+ 'TIMEOUT: Reduce scope, depth, or maxResults.',
63
+ 'INVALID_INPUT: Re-read the tool schema in tools/list.',
64
+ '```',
65
+ ].join('\n'),
66
+ };
67
+ }
68
+ export function renderSections(sections) {
69
+ return `\n${Object.values(sections).join('\n\n')}\n`;
70
+ }
71
+ //# sourceMappingURL=instructions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"instructions.js","sourceRoot":"","sources":["../src/instructions.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,8BAA8B,EAC9B,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,aAAa,EACb,IAAI,EACJ,wBAAwB,EACxB,mBAAmB,EACnB,SAAS,EACT,cAAc,EACd,YAAY,GACb,MAAM,kBAAkB,CAAC;AAE1B,SAAS,kBAAkB,CAAC,QAAiB;IAC3C,MAAM,IAAI,GAAyB;QACjC,CAAC,UAAU,EAAE,CAAC,wBAAwB,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,YAAY,CAAC,IAAI,CAAC,CAAC;QAC3E,CAAC,SAAS,EAAE,CAAC,aAAa,CAAC,IAAI,EAAE,cAAc,CAAC,IAAI,CAAC,CAAC;QACtD,CAAC,MAAM,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;KAC3B,CAAC;IAEF,4EAA4E;IAC5E,4EAA4E;IAC5E,iCAAiC;IACjC,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,IAAI,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC,GAAG,mBAAmB,CAAC,CAAC,CAAC,CAAC;IACjD,CAAC;IAED,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,KAAK,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC3E,OAAO,WAAW,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC;AAClD,CAAC;AAED,MAAM,CAAC,MAAM,gBAAgB,GAAG,yBAAyB,CAAC;AAC1D,MAAM,CAAC,MAAM,4BAA4B,GACvC,4NAA4N,CAAC;AAE/N;;;;;GAKG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAC/B,6DAA6D;IAC7D,kHAAkH,CAAC;AAErH,MAAM,UAAU,mBAAmB,CAAC,QAAiB;IACnD,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,kBAAkB,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC;IACjE,OAAO;QACL,UAAU,EAAE;YACV,aAAa;YACb,KAAK;YACL,gBAAgB,wBAAwB,CAAC,IAAI,0EAA0E;YACvH,qKAAqK;YACrK,wCAAwC,IAAI,CAAC,IAAI,OAAO,YAAY,CAAC,IAAI,uBAAuB;YAChG,KAAK;SACN,CAAC,IAAI,CAAC,IAAI,CAAC;QACZ,cAAc,EAAE;YACd,iBAAiB;YACjB,kBAAkB,CAAC,QAAQ,CAAC;YAC5B,EAAE;YACF,kEAAkE;SACnE,CAAC,IAAI,CAAC,IAAI,CAAC;QACZ,WAAW,EAAE;YACX,cAAc;YACd,KAAK;YACL,gIAAgI,wBAAwB,CAAC,IAAI,2BAA2B;YACxL,kGAAkG;YAClG,sFAAsF;YACtF,kCAAkC,SAAS,wBAAwB,kBAAkB,gCAAgC,8BAA8B,WAAW;YAC9J,wKAAwK;YACxK,6LAA6L;YAC7L,KAAK;SACN,CAAC,IAAI,CAAC,IAAI,CAAC;QACZ,cAAc,EAAE;YACd,iBAAiB;YACjB,KAAK;YACL,sBAAsB,wBAAwB,CAAC,IAAI,oFAAoF;YACvI,kBAAkB,IAAI,CAAC,IAAI,OAAO,YAAY,CAAC,IAAI,sBAAsB;YACzE,kBAAkB,SAAS,CAAC,IAAI,sEAAsE;YACtG,8CAA8C;YAC9C,uDAAuD;YACvD,KAAK;SACN,CAAC,IAAI,CAAC,IAAI,CAAC;KACb,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,QAAgC;IAC7D,OAAO,KAAK,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC;AACvD,CAAC","sourcesContent":["import {\n DEFAULT_SEARCH_CONTENT_RESULTS,\n getMaxTextFileSize,\n MAX_SEARCH_RESULTS,\n} from './core/util.js';\nimport {\n GET_FILE_INFO,\n LIST,\n LIST_ALLOWED_DIRECTORIES,\n MUTATING_TOOL_NAMES,\n READ_FILE,\n SEARCH_CONTENT,\n SEARCH_FILES,\n} from './tools/index.js';\n\nfunction buildToolsOverview(readOnly: boolean): string {\n const rows: [string, string[]][] = [\n ['Navigate', [LIST_ALLOWED_DIRECTORIES.name, LIST.name, SEARCH_FILES.name]],\n ['Inspect', [GET_FILE_INFO.name, SEARCH_CONTENT.name]],\n ['Read', [READ_FILE.name]],\n ];\n\n // Under --read-only the mutating tools are never registered, so advertising\n // them here would point the model at tools that are not there. Drop the row\n // rather than emit an empty one.\n if (!readOnly) {\n rows.push(['Write', [...MUTATING_TOOL_NAMES]]);\n }\n\n const rowLines = rows.map(([cat, names]) => `${cat}: ${names.join(', ')}`);\n return `\\`\\`\\`\\n${rowLines.join('\\n')}\\n\\`\\`\\``;\n}\n\nexport const INSTRUCTIONS_URI = 'internal://instructions';\nexport const NO_POSITIONAL_ROOTS_GUIDANCE =\n 'No positional directories specified. Configure roots with directory arguments, FS_ALLOWED_DIRS, or --allow-cwd. Modern clients with elicitation can also call a tool with a concrete path and approve the requested grant.';\n\n/**\n * The one statement of what this server is and how to approach it. The server's\n * `instructions`, the `get-help` prompt, and the instructions resource all\n * describe the same document, and three hand-maintained paraphrases of it drift\n * against each other and cost the client the same sentence three times.\n */\nexport const INSTRUCTIONS_SUMMARY =\n 'Navigation guide for filesystem-mcp tools and constraints. ' +\n 'Use list_roots to inspect configured or accepted roots, then list/find_files -> stat -> read. Never guess paths.';\n\nexport function buildSectionsRecord(readOnly: boolean): Record<string, string> {\n const maxFileMb = Math.floor(getMaxTextFileSize() / 1024 / 1024);\n return {\n guidelines: [\n 'Guidelines:',\n '```',\n `root_access: ${LIST_ALLOWED_DIRECTORIES.name} lists configured or accepted roots; every other tool is scoped to them.`,\n 'modern_root_grants: Modern clients do not automatically send workspace roots. Call a tool with a concrete path and approve its grant when elicitation is available.',\n `path_resolution: Confirm a path with ${LIST.name} or ${SEARCH_FILES.name} before acting on it.`,\n '```',\n ].join('\\n'),\n tools_overview: [\n 'Tools Overview:',\n buildToolsOverview(readOnly),\n '',\n 'Full schemas, descriptions, and annotations are in `tools/list`.',\n ].join('\\n'),\n constraints: [\n 'Constraints:',\n '```',\n `allowed_roots: Startup roots come from CLI paths, FS_ALLOWED_DIRS, or --allow-cwd; accepted modern grants are additive. Call ${LIST_ALLOWED_DIRECTORIES.name} to read the current set.`,\n 'legacy_roots: Legacy clients may additionally seed roots through the deprecated roots/list flow.',\n 'sensitive_paths: Sensitive file paths (.env, *.pem, *id_rsa*) are denied by default.',\n `enforced_limits: max file size ${maxFileMb} MB, file search cap ${MAX_SEARCH_RESULTS} results, content search cap ${DEFAULT_SEARCH_CONTENT_RESULTS} matches.`,\n 'ephemeral_results: When a tool returns resourceUri, call resources/read immediately — cached results are ephemeral and expire after ~60 seconds, eviction, or restart.',\n 'pagination: nextCursor is backed by a snapshot on the same ~60s clock. Page through promptly; if a cursor is rejected, start again without one. resourceUri appears on the first page only.',\n '```',\n ].join('\\n'),\n error_recovery: [\n 'Error Recovery:',\n '```',\n `ACCESS_DENIED: Run ${LIST_ALLOWED_DIRECTORIES.name}; configure a missing startup root or retry a concrete path and approve the grant.`,\n `NOT_FOUND: Run ${LIST.name} or ${SEARCH_FILES.name} to verify the path.`,\n `TOO_LARGE: Use ${READ_FILE.name} with head/tail or startLine/endLine, or split across several calls.`,\n 'TIMEOUT: Reduce scope, depth, or maxResults.',\n 'INVALID_INPUT: Re-read the tool schema in tools/list.',\n '```',\n ].join('\\n'),\n };\n}\n\nexport function renderSections(sections: Record<string, string>): string {\n return `\\n${Object.values(sections).join('\\n\\n')}\\n`;\n}\n"]}
package/dist/prompts.d.ts CHANGED
@@ -1,6 +1,8 @@
1
- import { type McpServer } from '@modelcontextprotocol/server';
2
- import { type IconInfo } from './tools/shared.js';
3
- export declare function registerGetHelpPrompt(server: McpServer, instructions: string, iconInfo?: IconInfo): void;
4
- export declare function registerCompareFilesPrompt(server: McpServer, iconInfo?: IconInfo): void;
5
- export declare function registerAnalyzePathPrompt(server: McpServer, iconInfo?: IconInfo): void;
6
- export declare function registerGetToolHelpPrompt(server: McpServer, iconInfo?: IconInfo): void;
1
+ import type { McpServer } from '@modelcontextprotocol/server';
2
+ interface PromptRegistrarDeps {
3
+ readonly server: McpServer;
4
+ readonly readOnly?: boolean;
5
+ }
6
+ export declare function registerPrompts(deps: PromptRegistrarDeps): void;
7
+ export {};
8
+ //# sourceMappingURL=prompts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../src/prompts.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,SAAS,EAGV,MAAM,8BAA8B,CAAC;AAkBtC,UAAU,mBAAmB;IAC3B,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAC3B,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;CAC7B;AA+DD,wBAAgB,eAAe,CAAC,IAAI,EAAE,mBAAmB,GAAG,IAAI,CAoC/D"}
package/dist/prompts.js CHANGED
@@ -1,177 +1,83 @@
1
- import { ProtocolError, ProtocolErrorCode, } from '@modelcontextprotocol/server';
2
- import { z } from 'zod';
3
- import { buildToolInfo, getSortedToolContracts, } from './resources/tool-info.js';
4
- import { withDefaultIcons } from './tools/shared.js';
5
- const HELP_PROMPT_NAME = 'get-help';
6
- const HELP_PROMPT_TITLE = 'Get Help';
7
- const HELP_PROMPT_DESCRIPTION = 'Return filesystem-mcp usage instructions.';
8
- const COMPARE_FILES_PROMPT_NAME = 'compare-files';
9
- const COMPARE_FILES_PROMPT_TITLE = 'Compare Files';
10
- const COMPARE_FILES_PROMPT_DESCRIPTION = 'Generate a workflow for comparing two files using diff_files.';
11
- const ANALYZE_PATH_PROMPT_NAME = 'analyze-path';
12
- const ANALYZE_PATH_PROMPT_TITLE = 'Analyze Path';
13
- const ANALYZE_PATH_PROMPT_DESCRIPTION = 'Generate a workflow for analyzing a file or directory using stat, read, and tree.';
14
- const GET_TOOL_HELP_PROMPT_NAME = 'get-tool-help';
15
- const GET_TOOL_HELP_PROMPT_TITLE = 'Get Tool Help';
16
- const GET_TOOL_HELP_PROMPT_DESCRIPTION = 'Return a prompt with the authoritative contract for a specific filesystem-mcp tool.';
17
- function filterInstructionsByTopic(instructions, topic) {
18
- const normalized = topic.trim().toLowerCase();
19
- if (!normalized)
20
- return instructions;
21
- const sections = instructions.split(/\n(?=## )/u);
22
- const match = sections.find((sec) => sec.toLowerCase().startsWith(`## ${normalized}`));
23
- if (match !== undefined)
24
- return match;
25
- const available = sections
26
- .filter((sec) => sec.startsWith('## '))
27
- .map((sec) => sec.split('\n')[0]?.replace(/^##\s*/u, '') ?? '')
28
- .filter(Boolean)
29
- .join(', ');
30
- return `Section '${topic}' not found. Available: ${available}\n\n${instructions}`;
31
- }
32
- function findKnownToolName(rawName) {
33
- const normalized = rawName.trim().toLowerCase();
34
- if (!normalized)
35
- return undefined;
36
- return getSortedToolContracts().find((contract) => contract.name.toLowerCase() === normalized)?.name;
37
- }
38
- export function registerGetHelpPrompt(server, instructions, iconInfo) {
39
- const baseConfig = withDefaultIcons({ title: HELP_PROMPT_TITLE, description: HELP_PROMPT_DESCRIPTION }, iconInfo);
40
- server.registerPrompt(HELP_PROMPT_NAME, {
41
- ...baseConfig,
42
- argsSchema: z.object({
43
- topic: z
44
- .string()
45
- .optional()
46
- .describe('Optional section heading prefix (example: "error handling"). Omit to return full instructions.'),
47
- }),
48
- }, ({ topic }) => {
49
- const text = topic
50
- ? filterInstructionsByTopic(instructions, topic)
51
- : instructions;
52
- return {
53
- description: HELP_PROMPT_DESCRIPTION,
54
- messages: [
55
- {
56
- role: 'user',
57
- content: {
58
- type: 'text',
59
- text,
60
- annotations: {
61
- audience: ['assistant'],
62
- priority: 1,
63
- },
64
- },
65
- },
66
- ],
67
- };
1
+ import { completable, getDisplayName, ProtocolError } from '@modelcontextprotocol/server';
2
+ import * as z from 'zod/v4';
3
+ import { formatUnknownErrorMessage, fsErrorCode, hasErrorShape } from './core/errors.js';
4
+ import { Logger } from './core/observability.js';
5
+ import { isBlank, SHELL_METACHAR_RE } from './core/schema.js';
6
+ import { buildSectionsRecord, INSTRUCTIONS_SUMMARY, renderSections } from './instructions.js';
7
+ // --- Helpers ---
8
+ function topicArg(topics, description) {
9
+ return completable(z
10
+ .string()
11
+ .min(1, { message: 'Topic required' })
12
+ .refine((val) => !isBlank(val), {
13
+ message: 'Topic cannot be empty or whitespace-only',
14
+ })
15
+ .refine((val) => !SHELL_METACHAR_RE.test(val), {
16
+ message: 'Topic contains prohibited characters (newlines or shell metacharacters)',
17
+ })
18
+ .describe(description), (value) => {
19
+ const lower = value.toLowerCase();
20
+ return lower ? topics.filter((t) => t.startsWith(lower)) : [...topics];
68
21
  });
69
22
  }
70
- export function registerCompareFilesPrompt(server, iconInfo) {
71
- server.registerPrompt(COMPARE_FILES_PROMPT_NAME, {
72
- ...withDefaultIcons({
73
- title: COMPARE_FILES_PROMPT_TITLE,
74
- description: COMPARE_FILES_PROMPT_DESCRIPTION,
75
- }, iconInfo),
76
- argsSchema: z.object({
77
- original: z.string().describe('Path to the original file.'),
78
- modified: z.string().describe('Path to the modified file.'),
79
- }),
80
- }, ({ original, modified }) => ({
81
- description: COMPARE_FILES_PROMPT_DESCRIPTION,
82
- messages: [
83
- {
84
- role: 'user',
85
- content: {
86
- type: 'text',
87
- text: `Compare files and explain differences.\n\n1. Call \`diff_files\` with:\n - original: ${original}\n - modified: ${modified}\n2. Summarize: additions, deletions, and semantic changes.\n3. Flag any potential issues (conflicts, regressions, breaking changes).`,
88
- annotations: {
89
- audience: ['assistant'],
90
- priority: 1,
91
- },
92
- },
93
- },
94
- ],
95
- }));
23
+ function userText(text) {
24
+ const content = {
25
+ type: 'text',
26
+ text,
27
+ annotations: { audience: ['assistant'], priority: 1 },
28
+ };
29
+ return { role: 'user', content };
96
30
  }
97
- export function registerAnalyzePathPrompt(server, iconInfo) {
98
- server.registerPrompt(ANALYZE_PATH_PROMPT_NAME, {
99
- ...withDefaultIcons({
100
- title: ANALYZE_PATH_PROMPT_TITLE,
101
- description: ANALYZE_PATH_PROMPT_DESCRIPTION,
102
- }, iconInfo),
103
- argsSchema: z.object({
104
- path: z.string().describe('Absolute path to analyze.'),
105
- }),
106
- }, ({ path: targetPath }) => ({
107
- description: ANALYZE_PATH_PROMPT_DESCRIPTION,
108
- messages: [
109
- {
110
- role: 'user',
111
- content: {
112
- type: 'text',
113
- text: `Analyze the path: ${targetPath}\n\n1. Call \`stat\` to determine if it is a file or directory.\n2. If file: call \`read\` with \`includeHash: true\` and summarize contents.\n3. If directory: call \`tree\` (maxDepth: 3) and \`ls\` to summarize structure.\n4. Report: type, size, permissions, key observations.`,
114
- annotations: {
115
- audience: ['assistant'],
116
- priority: 1,
117
- },
118
- },
119
- },
120
- ],
121
- }));
31
+ async function wrapHandler(contract, fn) {
32
+ const displayName = getDisplayName(contract);
33
+ try {
34
+ const result = await fn();
35
+ Logger.debug(`prompt resolved`, { name: contract.name, displayName });
36
+ return result;
37
+ }
38
+ catch (error) {
39
+ if (hasErrorShape(error, 'ProtocolError'))
40
+ throw error;
41
+ const message = formatUnknownErrorMessage(error);
42
+ Logger.error(`Prompt handler failed: ${message}`, {
43
+ promptName: contract.name,
44
+ error,
45
+ });
46
+ const protocolError = new ProtocolError(fsErrorCode(error), message);
47
+ protocolError.cause = error;
48
+ throw protocolError;
49
+ }
122
50
  }
123
- export function registerGetToolHelpPrompt(server, iconInfo) {
124
- server.registerPrompt(GET_TOOL_HELP_PROMPT_NAME, {
125
- ...withDefaultIcons({
126
- title: GET_TOOL_HELP_PROMPT_TITLE,
127
- description: GET_TOOL_HELP_PROMPT_DESCRIPTION,
128
- }, iconInfo),
129
- argsSchema: z.object({
130
- name: z
131
- .string()
132
- .min(1)
133
- .describe('Tool name from tools/list or internal://tool-info/{name}.'),
51
+ // --- Prompt entries ---
52
+ const GET_HELP = {
53
+ name: 'get-help',
54
+ title: 'Get Help',
55
+ description: INSTRUCTIONS_SUMMARY,
56
+ };
57
+ export function registerPrompts(deps) {
58
+ const sections = buildSectionsRecord(deps.readOnly ?? false);
59
+ const instructions = renderSections(sections);
60
+ const topics = Object.keys(sections);
61
+ deps.server.registerPrompt(GET_HELP.name, {
62
+ title: GET_HELP.title,
63
+ description: GET_HELP.description,
64
+ argsSchema: z.strictObject({
65
+ topic: topicArg(topics, `Section key to filter instructions (one of: ${topics.join(', ')}); omit to return all instructions.`).optional(),
134
66
  }),
135
- }, ({ name }) => {
136
- const toolName = findKnownToolName(name);
137
- if (!toolName) {
138
- throw new ProtocolError(ProtocolErrorCode.InvalidParams, `Unknown tool: ${name}`);
139
- }
140
- const toolInfo = buildToolInfo(toolName);
141
- if (!toolInfo) {
142
- throw new ProtocolError(ProtocolErrorCode.InvalidParams, `Unknown tool: ${toolName}`);
67
+ }, ({ topic }) => wrapHandler(GET_HELP, () => {
68
+ const lowerTopic = topic?.toLowerCase();
69
+ const section = lowerTopic && Object.hasOwn(sections, lowerTopic) ? sections[lowerTopic] : undefined;
70
+ if (topic && !section) {
71
+ Logger.debug('get-help: unknown topic requested', { topic });
143
72
  }
73
+ const text = section ??
74
+ (topic
75
+ ? `Section '${topic}' not found. Available: ${topics.join(', ')}\n\n${instructions}`
76
+ : instructions);
144
77
  return {
145
- description: GET_TOOL_HELP_PROMPT_DESCRIPTION,
146
- messages: [
147
- {
148
- role: 'user',
149
- content: {
150
- type: 'text',
151
- text: `Use the embedded contract for \`${toolName}\` as the authoritative reference. ` +
152
- 'Summarize when to use it, its key constraints, and the safest next action.',
153
- annotations: {
154
- audience: ['assistant'],
155
- priority: 1,
156
- },
157
- },
158
- },
159
- {
160
- role: 'user',
161
- content: {
162
- type: 'resource',
163
- resource: {
164
- uri: `internal://tool-info/${toolName}`,
165
- mimeType: 'text/markdown',
166
- text: toolInfo,
167
- },
168
- annotations: {
169
- audience: ['assistant'],
170
- priority: 1,
171
- },
172
- },
173
- },
174
- ],
78
+ description: GET_HELP.description,
79
+ messages: [userText(text)],
175
80
  };
176
- });
81
+ }));
177
82
  }
83
+ //# sourceMappingURL=prompts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompts.js","sourceRoot":"","sources":["../src/prompts.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n GetPromptResult,\n McpServer,\n PromptMessage,\n TextContent,\n} from '@modelcontextprotocol/server';\nimport { completable, getDisplayName, ProtocolError } from '@modelcontextprotocol/server';\n\nimport * as z from 'zod/v4';\n\nimport { formatUnknownErrorMessage, fsErrorCode, hasErrorShape } from './core/errors.js';\nimport { Logger } from './core/observability.js';\nimport { isBlank, SHELL_METACHAR_RE } from './core/schema.js';\nimport { buildSectionsRecord, INSTRUCTIONS_SUMMARY, renderSections } from './instructions.js';\n\n// --- Types ---\n\ninterface PromptContract {\n readonly name: string;\n readonly title: string;\n readonly description: string;\n}\n\ninterface PromptRegistrarDeps {\n readonly server: McpServer;\n readonly readOnly?: boolean;\n}\n\n// --- Helpers ---\n\nfunction topicArg(\n topics: readonly string[],\n description: string,\n): ReturnType<typeof completable<z.ZodString>> {\n return completable(\n z\n .string()\n .min(1, { message: 'Topic required' })\n .refine((val) => !isBlank(val), {\n message: 'Topic cannot be empty or whitespace-only',\n })\n .refine((val) => !SHELL_METACHAR_RE.test(val), {\n message: 'Topic contains prohibited characters (newlines or shell metacharacters)',\n })\n .describe(description),\n (value) => {\n const lower = value.toLowerCase();\n return lower ? topics.filter((t) => t.startsWith(lower)) : [...topics];\n },\n );\n}\n\nfunction userText(text: string): PromptMessage {\n const content: TextContent = {\n type: 'text',\n text,\n annotations: { audience: ['assistant'], priority: 1 },\n };\n return { role: 'user', content };\n}\n\nasync function wrapHandler<T>(contract: PromptContract, fn: () => Promise<T> | T): Promise<T> {\n const displayName = getDisplayName(contract);\n\n try {\n const result = await fn();\n Logger.debug(`prompt resolved`, { name: contract.name, displayName });\n return result;\n } catch (error) {\n if (hasErrorShape(error, 'ProtocolError')) throw error;\n const message = formatUnknownErrorMessage(error);\n Logger.error(`Prompt handler failed: ${message}`, {\n promptName: contract.name,\n error,\n });\n const protocolError = new ProtocolError(fsErrorCode(error), message);\n protocolError.cause = error;\n throw protocolError;\n }\n}\n\n// --- Prompt entries ---\n\nconst GET_HELP: PromptContract = {\n name: 'get-help',\n title: 'Get Help',\n description: INSTRUCTIONS_SUMMARY,\n};\n\nexport function registerPrompts(deps: PromptRegistrarDeps): void {\n const sections = buildSectionsRecord(deps.readOnly ?? false);\n const instructions = renderSections(sections);\n const topics = Object.keys(sections);\n\n deps.server.registerPrompt(\n GET_HELP.name,\n {\n title: GET_HELP.title,\n description: GET_HELP.description,\n argsSchema: z.strictObject({\n topic: topicArg(\n topics,\n `Section key to filter instructions (one of: ${topics.join(', ')}); omit to return all instructions.`,\n ).optional(),\n }),\n },\n ({ topic }: { topic?: string | undefined }): GetPromptResult | Promise<GetPromptResult> =>\n wrapHandler(GET_HELP, () => {\n const lowerTopic = topic?.toLowerCase();\n const section =\n lowerTopic && Object.hasOwn(sections, lowerTopic) ? sections[lowerTopic] : undefined;\n if (topic && !section) {\n Logger.debug('get-help: unknown topic requested', { topic });\n }\n const text =\n section ??\n (topic\n ? `Section '${topic}' not found. Available: ${topics.join(', ')}\\n\\n${instructions}`\n : instructions);\n return {\n description: GET_HELP.description,\n messages: [userText(text)],\n };\n }),\n );\n}\n"]}
@@ -1,9 +1,73 @@
1
- import { type McpServer } from '@modelcontextprotocol/server';
2
- import type { ResourceStore } from './lib/resource-store.js';
3
- import { type IconInfo } from './tools/shared.js';
4
- export declare function registerInstructionResource(server: McpServer, instructions: string, iconInfo?: IconInfo): void;
5
- export declare function registerToolCatalogResource(server: McpServer, iconInfo?: IconInfo): void;
6
- export declare function registerWorkflowGuideResource(server: McpServer, iconInfo?: IconInfo): void;
7
- export declare function registerResultResources(server: McpServer, store: ResourceStore, iconInfo?: IconInfo): void;
8
- export declare function registerToolInfoResource(server: McpServer, iconInfo?: IconInfo): void;
9
- export declare function registerMetricsResource(server: McpServer, iconInfo?: IconInfo): void;
1
+ import type { CacheHint, McpServer, ReadResourceResult, Resource, Role, ServerContext, ServerNotifier } from '@modelcontextprotocol/server';
2
+ import type { PathGuard } from './core/path.js';
3
+ import type { ResourceStore } from './core/store.js';
4
+ import { type WatcherRegistry } from './core/watcher-registry.js';
5
+ export interface ResourceRegistrationOptions {
6
+ resourceStore: ResourceStore;
7
+ pathGuard?: PathGuard;
8
+ /** Mirrors the `--read-only` gate so the instructions match the tools actually registered. */
9
+ readOnly: boolean;
10
+ /**
11
+ * Shared file-watcher registry for the modern (per-request) HTTP leg. When set,
12
+ * the resource uses this handler-scoped registry instead of creating its own
13
+ * per-server one, so file-change watchers persist across requests and publish
14
+ * to the shared ServerEventBus. Omitted (per-server registry) on legacy/stdio.
15
+ */
16
+ watcherRegistry?: WatcherRegistry;
17
+ /** Modern-leg typed notification publisher. */
18
+ notifier?: ServerNotifier;
19
+ /** The protocol era this instance serves; omitted where the caller does not know. */
20
+ era?: 'legacy' | 'modern';
21
+ /**
22
+ * Scope for shared-content cache hints. 'private' when the endpoint is
23
+ * API-key gated, mirroring the list hints in server.ts — a shared cache must
24
+ * not store an authenticated response body. Defaults to 'public'.
25
+ */
26
+ cacheScope?: 'public' | 'private';
27
+ }
28
+ type ResourceRegistrarDeps = Omit<ResourceRegistrationOptions, 'pathGuard' | 'readOnly'> & {
29
+ readonly server: McpServer;
30
+ readonly pathGuard: PathGuard;
31
+ readonly readOnly?: boolean;
32
+ };
33
+ interface BaseResourceContract {
34
+ name: string;
35
+ title?: string;
36
+ description?: string;
37
+ mimeType?: string;
38
+ cacheHint?: CacheHint;
39
+ annotations?: {
40
+ audience?: Role[];
41
+ priority?: number;
42
+ };
43
+ readonly read: (uri: URL, variables: Record<string, string | string[]>, ctx: ServerContext) => Promise<ReadResourceResult> | ReadResourceResult;
44
+ readonly subscribe?: (uri: string, notify: (uri: string) => void) => Promise<boolean | undefined> | boolean | undefined;
45
+ readonly unsubscribe?: (uri: string) => void;
46
+ readonly destroy?: () => void;
47
+ readonly list?: (ctx: ServerContext) => Promise<{
48
+ resources: Resource[];
49
+ }> | {
50
+ resources: Resource[];
51
+ };
52
+ }
53
+ /** A resource with a fixed, enumerable URI (e.g. internal://instructions). */
54
+ interface StaticResourceContract extends BaseResourceContract {
55
+ uri: string;
56
+ uriTemplate?: never;
57
+ complete?: never;
58
+ }
59
+ /** A resource identified by a URI template (FILESYSTEM_FILE_URI_TEMPLATE). */
60
+ interface TemplateResourceContract extends BaseResourceContract {
61
+ uriTemplate: string;
62
+ uri?: never;
63
+ complete?: (variable: string, value: string, ctx?: {
64
+ arguments?: Record<string, string>;
65
+ }) => Promise<string[]> | string[];
66
+ }
67
+ type ResourceContract = StaticResourceContract | TemplateResourceContract;
68
+ export declare function getResourceContracts(options: ResourceRegistrationOptions): ResourceContract[];
69
+ export declare function registerResources(deps: ResourceRegistrarDeps): {
70
+ dispose(): void;
71
+ };
72
+ export {};
73
+ //# sourceMappingURL=resources.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resources.d.ts","sourceRoot":"","sources":["../src/resources.ts"],"names":[],"mappings":"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"}