@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
@@ -1,91 +0,0 @@
1
- import { AsyncLocalStorage } from 'node:async_hooks';
2
- import { channel } from 'node:diagnostics_channel';
3
- export const SessionContext = new AsyncLocalStorage();
4
- const LOG_CHANNEL = channel('filesystem-mcp:log');
5
- const MCP_LOGGER_NAME = 'filesystem-mcp';
6
- const LOG_LEVEL_ORDER = {
7
- debug: 0,
8
- info: 1,
9
- notice: 2,
10
- warning: 3,
11
- error: 4,
12
- critical: 5,
13
- alert: 6,
14
- emergency: 7,
15
- };
16
- export function createLoggingState(minimumLevel = 'debug') {
17
- return { minimumLevel };
18
- }
19
- function canSendMcpLogs(server) {
20
- const capabilities = server.server.getClientCapabilities();
21
- if (!capabilities || typeof capabilities !== 'object')
22
- return false;
23
- return 'logging' in capabilities && Boolean(capabilities.logging);
24
- }
25
- export function logToMcp(server, level, data, minLevel = 'debug') {
26
- if (LOG_LEVEL_ORDER[level] < LOG_LEVEL_ORDER[minLevel]) {
27
- return;
28
- }
29
- if (!server || !canSendMcpLogs(server)) {
30
- console.error(`[${level.toUpperCase()}] ${data}`);
31
- return;
32
- }
33
- const params = {
34
- level,
35
- logger: MCP_LOGGER_NAME,
36
- data,
37
- };
38
- void server.sendLoggingMessage(params).catch((error) => {
39
- console.error(`Failed to send MCP log: ${level} | ${data}`, formatTransportError(error));
40
- });
41
- }
42
- function formatTransportError(error) {
43
- if (error instanceof Error)
44
- return error.message;
45
- if (typeof error === 'string')
46
- return error;
47
- try {
48
- return JSON.stringify(error);
49
- }
50
- catch {
51
- return String(error);
52
- }
53
- }
54
- export const Logger = {
55
- emit(level, message, data) {
56
- const session = SessionContext.getStore();
57
- const event = {
58
- level,
59
- message,
60
- ...(data !== undefined ? { data } : {}),
61
- ...(session?.sessionId !== undefined
62
- ? { sessionId: session.sessionId }
63
- : {}),
64
- };
65
- if (LOG_CHANNEL.hasSubscribers) {
66
- LOG_CHANNEL.publish(event);
67
- }
68
- else {
69
- // Fallback if no subscribers
70
- console.error(`[${level.toUpperCase()}] ${message}`, data ?? '');
71
- }
72
- },
73
- debug(message, data) {
74
- this.emit('debug', message, data);
75
- },
76
- info(message, data) {
77
- this.emit('info', message, data);
78
- },
79
- notice(message, data) {
80
- this.emit('notice', message, data);
81
- },
82
- warn(message, data) {
83
- this.emit('warning', message, data);
84
- },
85
- error(message, data) {
86
- this.emit('error', message, data);
87
- },
88
- critical(message, data) {
89
- this.emit('critical', message, data);
90
- },
91
- };
@@ -1,33 +0,0 @@
1
- interface OpsTraceContext {
2
- op: string;
3
- engine?: string;
4
- tool?: string;
5
- path?: string | undefined;
6
- [key: string]: unknown;
7
- }
8
- export interface TraceContext {
9
- traceparent: string;
10
- tracestate?: string;
11
- baggage?: string;
12
- }
13
- interface ToolMetrics {
14
- calls: number;
15
- errors: number;
16
- totalDurationMs: number;
17
- }
18
- export declare const globalMetrics: Map<string, ToolMetrics>;
19
- export declare function shouldPublishOpsTrace(): boolean;
20
- export declare function publishOpsTraceStart(context: OpsTraceContext): void;
21
- export declare function publishOpsTraceEnd(context: OpsTraceContext): void;
22
- export declare function publishOpsTraceError(context: OpsTraceContext, error: unknown): void;
23
- export declare function getToolContextSnapshot(): {
24
- tool: string;
25
- path?: string;
26
- } | undefined;
27
- export declare function getTraceContext(): TraceContext | undefined;
28
- export declare function startPerfMeasure(name: string, detail?: Record<string, unknown>): ((ok?: boolean) => void) | undefined;
29
- export declare function withToolDiagnostics<T>(tool: string, run: () => Promise<T>, options?: {
30
- path?: string;
31
- traceContext?: TraceContext;
32
- }): Promise<T>;
33
- export {};
@@ -1,373 +0,0 @@
1
- import { AsyncLocalStorage } from 'node:async_hooks';
2
- import { hash } from 'node:crypto';
3
- import { channel, tracingChannel } from 'node:diagnostics_channel';
4
- import { monitorEventLoopDelay, performance, PerformanceObserver, } from 'node:perf_hooks';
5
- import { parseTrueEnvFlag } from './constants.js';
6
- import { Logger } from './logger.js';
7
- import { isRecord } from './utils.js';
8
- // --- Configuration ---
9
- const ENV = process.env;
10
- let _cachedConfig;
11
- function readConfig() {
12
- _cachedConfig ??= {
13
- enabled: parseTrueEnvFlag(ENV['FS_CONTEXT_DIAGNOSTICS']),
14
- detail: parseDetail(ENV['FS_CONTEXT_DIAGNOSTICS_DETAIL']),
15
- logToolErrors: parseTrueEnvFlag(ENV['FS_CONTEXT_TOOL_LOG_ERRORS']),
16
- };
17
- return _cachedConfig;
18
- }
19
- function parseDetail(val) {
20
- if (val === '2')
21
- return 2;
22
- if (val === '1')
23
- return 1;
24
- return 0;
25
- }
26
- export const globalMetrics = new Map();
27
- function updateMetrics(tool, ok, durationMs) {
28
- const current = globalMetrics.get(tool) ?? {
29
- calls: 0,
30
- errors: 0,
31
- totalDurationMs: 0,
32
- };
33
- current.calls++;
34
- if (!ok)
35
- current.errors++;
36
- current.totalDurationMs += durationMs;
37
- globalMetrics.set(tool, current);
38
- }
39
- // --- Channels & Observability State ---
40
- const CHANNELS = {
41
- tool: channel('filesystem-mcp:tool'),
42
- perf: channel('filesystem-mcp:perf'),
43
- ops: tracingChannel('filesystem-mcp:ops'),
44
- };
45
- const toolContext = new AsyncLocalStorage({
46
- name: 'filesystem-mcp:tool',
47
- });
48
- let perfObserver;
49
- let traceCounter = 0;
50
- // --- Helpers: Result Analysis ---
51
- function extractOutcome(result) {
52
- if (!isRecord(result)) {
53
- return { ok: true };
54
- }
55
- if (result['isError'] === true) {
56
- const err = extractErrorMessage(result);
57
- return { ok: false, error: err };
58
- }
59
- if (typeof result['ok'] === 'boolean') {
60
- if (result['ok'])
61
- return { ok: true };
62
- return { ok: false, error: extractErrorMessage(result) };
63
- }
64
- const content = result['structuredContent'];
65
- if (isRecord(content) && typeof content['ok'] === 'boolean') {
66
- if (content['ok'])
67
- return { ok: true };
68
- const err = extractResultError(content);
69
- return err ? { ok: false, error: err } : { ok: false };
70
- }
71
- return { ok: true };
72
- }
73
- function extractErrorMessage(source) {
74
- if (typeof source === 'string')
75
- return source;
76
- if (source instanceof Error)
77
- return source.message;
78
- if (isRecord(source)) {
79
- const struct = source['structuredContent'];
80
- if (isRecord(struct)) {
81
- const err = struct['error'];
82
- if (isRecord(err) && typeof err['message'] === 'string')
83
- return err['message'];
84
- }
85
- if (typeof source['message'] === 'string')
86
- return source['message'];
87
- const errObj = source['error'];
88
- if (isRecord(errObj) && typeof errObj['message'] === 'string') {
89
- return errObj['message'];
90
- }
91
- }
92
- try {
93
- return String(source);
94
- }
95
- catch {
96
- return 'Unknown error';
97
- }
98
- }
99
- function extractResultError(structured) {
100
- const err = structured['error'];
101
- return isRecord(err) && typeof err['message'] === 'string'
102
- ? err['message']
103
- : undefined;
104
- }
105
- function sanitizePathForDiagnostics(path) {
106
- const { detail } = readConfig();
107
- if (!path || detail === 0)
108
- return undefined;
109
- if (detail === 2)
110
- return path;
111
- return hash('sha256', path, 'hex').slice(0, 16);
112
- }
113
- function enrichWithToolContext(detail) {
114
- const current = toolContext.getStore();
115
- if (!current)
116
- return detail;
117
- const merged = { ...(detail ?? {}) };
118
- if (!Object.hasOwn(merged, 'tool')) {
119
- merged.tool = current.tool;
120
- }
121
- const normalizedPath = sanitizePathForDiagnostics(current.path);
122
- if (normalizedPath && !Object.hasOwn(merged, 'path')) {
123
- merged.path = normalizedPath;
124
- }
125
- return merged;
126
- }
127
- // --- Perf Helpers ---
128
- function toMs(nanos) {
129
- return nanos / 1_000_000;
130
- }
131
- function getDelayStats(h) {
132
- if (h.count === 0)
133
- return undefined;
134
- return {
135
- min: toMs(h.min),
136
- max: toMs(h.max),
137
- mean: toMs(h.mean),
138
- p50: toMs(h.percentile(50)),
139
- p95: toMs(h.percentile(95)),
140
- p99: toMs(h.percentile(99)),
141
- exceeds: h.exceeds,
142
- };
143
- }
144
- function clearPublishedMeasures(entries) {
145
- if (entries.length === 0)
146
- return;
147
- const names = new Set();
148
- for (const entry of entries) {
149
- names.add(entry.name);
150
- }
151
- for (const name of names) {
152
- performance.clearMeasures(name);
153
- }
154
- }
155
- function ensureObserver() {
156
- if (perfObserver)
157
- return;
158
- perfObserver = new PerformanceObserver((list) => {
159
- const entries = list.getEntries();
160
- for (const entry of entries) {
161
- CHANNELS.perf.publish({
162
- phase: 'measure',
163
- name: entry.name,
164
- durationMs: entry.duration,
165
- detail: entry.detail,
166
- });
167
- }
168
- try {
169
- // Keep the global timeline bounded while preserving published events.
170
- clearPublishedMeasures(entries);
171
- }
172
- catch {
173
- // Never allow observability cleanup to affect tool execution.
174
- }
175
- });
176
- perfObserver.observe({ entryTypes: ['measure'] });
177
- }
178
- // --- Public API ---
179
- export function shouldPublishOpsTrace() {
180
- return readConfig().enabled && CHANNELS.ops.hasSubscribers;
181
- }
182
- export function publishOpsTraceStart(context) {
183
- CHANNELS.ops.start.publish(normalizeContext(applyToolContext(context)));
184
- }
185
- export function publishOpsTraceEnd(context) {
186
- CHANNELS.ops.end.publish(normalizeContext(applyToolContext(context)));
187
- }
188
- export function publishOpsTraceError(context, error) {
189
- CHANNELS.ops.error.publish({
190
- ...normalizeContext(applyToolContext(context)),
191
- error,
192
- });
193
- }
194
- function applyToolContext(context) {
195
- const current = toolContext.getStore();
196
- if (!current)
197
- return context;
198
- const merged = { ...context };
199
- merged.tool ??= current.tool;
200
- merged.path ??= current.path;
201
- return merged;
202
- }
203
- export function getToolContextSnapshot() {
204
- return toolContext.getStore();
205
- }
206
- export function getTraceContext() {
207
- return toolContext.getStore()?.traceContext;
208
- }
209
- function normalizeContext(ctx) {
210
- if (!ctx.path)
211
- return ctx;
212
- const normalized = sanitizePathForDiagnostics(ctx.path);
213
- if (!normalized) {
214
- const copy = { ...ctx };
215
- delete copy.path;
216
- return copy;
217
- }
218
- return { ...ctx, path: normalized };
219
- }
220
- function clearMeasureMarks(startMark, endMark) {
221
- performance.clearMarks(startMark);
222
- performance.clearMarks(endMark);
223
- }
224
- export function startPerfMeasure(name, detail) {
225
- if (!readConfig().enabled || !CHANNELS.perf.hasSubscribers)
226
- return undefined;
227
- ensureObserver();
228
- const id = ++traceCounter;
229
- const startMark = `${name}:start:${id}`;
230
- const endMark = `${name}:end:${id}`;
231
- const runInCapturedContext = AsyncLocalStorage.snapshot();
232
- let finished = false;
233
- performance.mark(startMark);
234
- return (ok) => {
235
- if (finished)
236
- return;
237
- finished = true;
238
- try {
239
- runInCapturedContext(() => {
240
- try {
241
- performance.mark(endMark);
242
- let meta = enrichWithToolContext(detail);
243
- if (ok !== undefined) {
244
- meta = { ...(meta ?? {}), ok };
245
- }
246
- performance.measure(name, {
247
- start: startMark,
248
- end: endMark,
249
- detail: meta,
250
- });
251
- }
252
- finally {
253
- clearMeasureMarks(startMark, endMark);
254
- }
255
- });
256
- }
257
- catch {
258
- clearMeasureMarks(startMark, endMark);
259
- }
260
- };
261
- }
262
- function publishToolStart(tool, pathVal, traceparent) {
263
- const event = { phase: 'start', tool };
264
- if (pathVal)
265
- event.path = pathVal;
266
- if (traceparent)
267
- event.traceparent = traceparent;
268
- CHANNELS.tool.publish(event);
269
- }
270
- function publishToolEnd(tool, ok, durationMs, errorMsg, traceparent) {
271
- const event = { phase: 'end', tool, ok, durationMs };
272
- if (errorMsg)
273
- event.error = errorMsg;
274
- if (traceparent)
275
- event.traceparent = traceparent;
276
- CHANNELS.tool.publish(event);
277
- }
278
- function publishPerfEnd(tool, durationMs, eluStart, loopMonitor) {
279
- const elu = performance.eventLoopUtilization(eluStart);
280
- const event = {
281
- phase: 'end',
282
- tool,
283
- durationMs,
284
- elu: { idle: elu.idle, active: elu.active, utilization: elu.utilization },
285
- };
286
- if (loopMonitor) {
287
- const delays = getDelayStats(loopMonitor);
288
- if (delays)
289
- event.eventLoopDelay = delays;
290
- }
291
- CHANNELS.perf.publish(event);
292
- }
293
- async function runAndObserve(tool, run, pubTool, pubPerf, logErrors, pathVal, traceparent) {
294
- const startMs = performance.now();
295
- const eluStart = pubPerf ? performance.eventLoopUtilization() : undefined;
296
- const loopMonitor = pubPerf ? monitorEventLoopDelay() : undefined;
297
- loopMonitor?.enable();
298
- if (pubTool)
299
- publishToolStart(tool, pathVal, traceparent);
300
- let result;
301
- const obs = { ok: false, errorMsg: undefined };
302
- try {
303
- result = await run();
304
- const { ok, error } = extractOutcome(result);
305
- obs.ok = ok;
306
- obs.errorMsg = error;
307
- }
308
- catch (err) {
309
- obs.errorMsg = extractErrorMessage(err);
310
- throw err;
311
- }
312
- finally {
313
- const durationMs = performance.now() - startMs;
314
- loopMonitor?.disable();
315
- if (pubPerf && eluStart)
316
- publishPerfEnd(tool, durationMs, eluStart, loopMonitor);
317
- if (pubTool)
318
- publishToolEnd(tool, obs.ok, durationMs, obs.errorMsg, traceparent);
319
- updateMetrics(tool, obs.ok, durationMs);
320
- if (logErrors && !obs.ok)
321
- logError(tool, durationMs, obs.errorMsg);
322
- }
323
- return result;
324
- }
325
- export async function withToolDiagnostics(tool, run, options) {
326
- const config = readConfig();
327
- const normalizedPath = sanitizePathForDiagnostics(options?.path);
328
- const context = {
329
- tool,
330
- ...(options?.path ? { path: options.path } : {}),
331
- ...(options?.traceContext ? { traceContext: options.traceContext } : {}),
332
- };
333
- return toolContext.run(context, async () => {
334
- if (!config.enabled) {
335
- if (!config.logToolErrors)
336
- return run();
337
- const start = performance.now();
338
- try {
339
- const res = await run();
340
- const { ok, error } = extractOutcome(res);
341
- if (!ok)
342
- logError(tool, performance.now() - start, error);
343
- return res;
344
- }
345
- catch (e) {
346
- logError(tool, performance.now() - start, extractErrorMessage(e));
347
- throw e;
348
- }
349
- }
350
- const pubTool = CHANNELS.tool.hasSubscribers;
351
- const pubPerf = CHANNELS.perf.hasSubscribers;
352
- if (!pubTool && !pubPerf) {
353
- const start = performance.now();
354
- try {
355
- const res = await run();
356
- const duration = performance.now() - start;
357
- const { ok } = extractOutcome(res);
358
- updateMetrics(tool, ok, duration);
359
- return res;
360
- }
361
- catch (e) {
362
- const duration = performance.now() - start;
363
- updateMetrics(tool, false, duration);
364
- throw e;
365
- }
366
- }
367
- return runAndObserve(tool, run, pubTool, pubPerf, config.logToolErrors, normalizedPath, options?.traceContext?.traceparent);
368
- });
369
- }
370
- function logError(tool, durationMs, msg) {
371
- const suffix = msg ? `: ${msg}` : '';
372
- Logger.error(`[ToolError] ${tool} failed in ${durationMs.toFixed(1)}ms${suffix}`);
373
- }
@@ -1,35 +0,0 @@
1
- import type { Root } from '@modelcontextprotocol/server';
2
- export declare function toPosixPath(value: string): string;
3
- export declare function isSensitivePath(requestedPath: string, resolvedPath?: string): boolean;
4
- export declare function assertAllowedFileAccess(requestedPath: string, resolvedPath?: string): void;
5
- export interface AllowedDirectoriesState {
6
- primary: string[];
7
- expanded: string[];
8
- }
9
- /**
10
- * Normalizes any path-like input to an absolute path suitable for comparisons.
11
- * - Expands "~" home directory shorthand.
12
- * - Resolves against process CWD if relative.
13
- * - Lowercases Windows drive letter for stable comparisons.
14
- */
15
- export declare function normalizePath(p: string): string;
16
- export declare function withAllowedDirectoriesState<T>(state: AllowedDirectoriesState, run: () => T): T;
17
- export declare function setAllowedDirectoriesStateResolved(state: AllowedDirectoriesState): void;
18
- export declare function getAllowedDirectories(): string[];
19
- export declare function isAllowedDirectoryRoot(normalizedPath: string): boolean;
20
- export declare function isPathWithinDirectories(normalizedPath: string, allowedDirs: readonly string[]): boolean;
21
- export declare function resolveAllowedDirectoriesState(dirs: readonly string[], signal?: AbortSignal): Promise<AllowedDirectoriesState>;
22
- export declare function setAllowedDirectoriesResolved(dirs: readonly string[], signal?: AbortSignal): Promise<void>;
23
- export declare function getReservedDeviceNameForPath(requestedPath: string): string | undefined;
24
- export declare function isWindowsDriveRelativePath(requestedPath: string): boolean;
25
- interface ValidatedPathDetails {
26
- requestedPath: string;
27
- resolvedPath: string;
28
- isSymlink: boolean;
29
- }
30
- export declare function validateExistingPathDetailed(requestedPath: string, signal?: AbortSignal): Promise<ValidatedPathDetails>;
31
- export declare function validateExistingPath(requestedPath: string, signal?: AbortSignal): Promise<string>;
32
- export declare function validateExistingDirectory(requestedPath: string, signal?: AbortSignal): Promise<string>;
33
- export declare function validatePathForWrite(requestedPath: string, signal?: AbortSignal): Promise<string>;
34
- export declare function getValidRootDirectories(roots: Root[], signal?: AbortSignal): Promise<string[]>;
35
- export {};