@j0hanz/filesystem-mcp 1.13.2 → 1.14.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 (74) hide show
  1. package/README.md +162 -145
  2. package/dist/cli.js +2 -2
  3. package/dist/completions.js +54 -51
  4. package/dist/config.d.ts +13 -14
  5. package/dist/config.js +12 -12
  6. package/dist/index.js +1 -1
  7. package/dist/lib/abort.d.ts +7 -0
  8. package/dist/lib/abort.js +81 -0
  9. package/dist/lib/constants.d.ts +3 -1
  10. package/dist/lib/constants.js +8 -2
  11. package/dist/lib/errors.d.ts +7 -3
  12. package/dist/lib/errors.js +64 -41
  13. package/dist/lib/file-operations/core.d.ts +3 -3
  14. package/dist/lib/file-operations/core.js +23 -20
  15. package/dist/lib/file-operations/metadata.d.ts +2 -2
  16. package/dist/lib/file-operations/metadata.js +69 -22
  17. package/dist/lib/file-operations/search.d.ts +0 -1
  18. package/dist/lib/file-operations/search.js +87 -95
  19. package/dist/lib/file-operations/traversal.js +13 -15
  20. package/dist/lib/fs-helpers.d.ts +3 -10
  21. package/dist/lib/fs-helpers.js +29 -108
  22. package/dist/lib/globs.d.ts +2 -0
  23. package/dist/lib/globs.js +19 -0
  24. package/dist/lib/logger.d.ts +28 -0
  25. package/dist/lib/logger.js +91 -0
  26. package/dist/lib/observability.d.ts +7 -0
  27. package/dist/lib/observability.js +19 -9
  28. package/dist/lib/paths.js +55 -55
  29. package/dist/lib/resource-store.js +4 -4
  30. package/dist/lib/utils.d.ts +0 -12
  31. package/dist/lib/utils.js +0 -13
  32. package/dist/lib/zod-codecs.d.ts +2 -0
  33. package/dist/lib/zod-codecs.js +18 -0
  34. package/dist/pkg-info.d.ts +1 -0
  35. package/dist/pkg-info.js +2 -2
  36. package/dist/prompts.js +3 -3
  37. package/dist/resources/generated-instructions.js +41 -41
  38. package/dist/resources/tool-catalog.js +33 -58
  39. package/dist/resources/tool-info.d.ts +0 -1
  40. package/dist/resources/tool-info.js +44 -67
  41. package/dist/resources/workflows.js +47 -19
  42. package/dist/resources.d.ts +1 -1
  43. package/dist/resources.js +4 -4
  44. package/dist/schemas.d.ts +185 -465
  45. package/dist/schemas.js +174 -206
  46. package/dist/server/bootstrap.d.ts +12 -11
  47. package/dist/server/bootstrap.js +95 -86
  48. package/dist/server/roots-manager.d.ts +5 -2
  49. package/dist/server/roots-manager.js +9 -7
  50. package/dist/server/task-store.d.ts +10 -0
  51. package/dist/server/task-store.js +73 -0
  52. package/dist/tools/apply-patch.js +39 -20
  53. package/dist/tools/calculate-hash.js +14 -27
  54. package/dist/tools/create-directory.js +11 -9
  55. package/dist/tools/delete-file.js +19 -19
  56. package/dist/tools/diff-files.js +16 -18
  57. package/dist/tools/edit-file.js +11 -5
  58. package/dist/tools/list-directory.js +16 -21
  59. package/dist/tools/move-file.js +105 -100
  60. package/dist/tools/read-multiple.js +15 -10
  61. package/dist/tools/read.js +6 -7
  62. package/dist/tools/replace-in-files.js +76 -115
  63. package/dist/tools/roots.js +3 -7
  64. package/dist/tools/search-content.js +158 -203
  65. package/dist/tools/search-files.js +59 -50
  66. package/dist/tools/shared.d.ts +10 -0
  67. package/dist/tools/shared.js +105 -36
  68. package/dist/tools/stat-many.js +15 -9
  69. package/dist/tools/stat.js +6 -6
  70. package/dist/tools/task-support.d.ts +10 -9
  71. package/dist/tools/task-support.js +94 -23
  72. package/dist/tools/tree.js +4 -4
  73. package/dist/tools/write-file.js +11 -12
  74. package/package.json +10 -9
@@ -1,10 +1,11 @@
1
- import * as fs from 'node:fs/promises';
2
- import * as path from 'node:path';
1
+ import { cp, mkdir, rename, rm, stat } from 'node:fs/promises';
2
+ import { basename, dirname, join, resolve, sep } from 'node:path';
3
+ import { withAbort } from '../lib/abort.js';
3
4
  import { ErrorCode, formatUnknownErrorMessage, isNodeError, McpError, } from '../lib/errors.js';
4
- import { withAbort } from '../lib/fs-helpers.js';
5
+ import { Logger } from '../lib/logger.js';
5
6
  import { assertAllowedFileAccess, validateExistingPath, validatePathForWrite, } from '../lib/paths.js';
6
7
  import { MoveFileInputSchema, MoveFileOutputSchema } from '../schemas.js';
7
- import { buildToolErrorResponse, buildToolResponse, DESTRUCTIVE_WRITE_TOOL_ANNOTATIONS, executeToolWithDiagnostics, withDefaultIcons, withValidatedArgs, wrapToolHandler, } from './shared.js';
8
+ import { buildStructuredError, buildToolErrorResponse, buildToolResponse, DESTRUCTIVE_WRITE_TOOL_ANNOTATIONS, executeToolWithDiagnostics, withDefaultIcons, withValidatedArgs, wrapToolHandler, } from './shared.js';
8
9
  import { registerToolTaskIfAvailable } from './task-support.js';
9
10
  export const MOVE_FILE_TOOL = {
10
11
  name: 'mv',
@@ -13,121 +14,124 @@ export const MOVE_FILE_TOOL = {
13
14
  inputSchema: MoveFileInputSchema,
14
15
  outputSchema: MoveFileOutputSchema,
15
16
  annotations: DESTRUCTIVE_WRITE_TOOL_ANNOTATIONS,
16
- nuances: ['Cross-device moves fall back to copy+delete.'],
17
17
  gotchas: [
18
18
  'On POSIX, an existing destination is silently overwritten; on Windows, rename fails with EEXIST if destination exists.',
19
19
  ],
20
20
  taskSupport: 'forbidden',
21
21
  };
22
- async function handleMoveFile(args, signal) {
23
- const sources = args.sources ?? (args.source ? [args.source] : []);
24
- if (sources.length === 0) {
25
- throw new McpError(ErrorCode.E_INVALID_INPUT, 'No sources provided.');
22
+ function toMoveFailure(source, error, defaultCode = ErrorCode.UNKNOWN) {
23
+ return {
24
+ source,
25
+ error: buildStructuredError(error, defaultCode, source),
26
+ };
27
+ }
28
+ async function handleMoveError(error, src, validSource, targetPath, movedSources, failed, signal) {
29
+ if (isNodeError(error) && error.code === 'EXDEV') {
30
+ try {
31
+ await withAbort(cp(validSource, targetPath, { recursive: true }), signal);
32
+ }
33
+ catch (copyError) {
34
+ failed.push(toMoveFailure(src, copyError));
35
+ return;
36
+ }
37
+ try {
38
+ await withAbort(rm(validSource, { recursive: true, force: true }), signal);
39
+ movedSources.push(validSource);
40
+ }
41
+ catch (deleteError) {
42
+ try {
43
+ await rm(targetPath, { recursive: true, force: true });
44
+ }
45
+ catch {
46
+ failed.push(toMoveFailure(src, new McpError(ErrorCode.UNKNOWN, `Cross-device move partial: data at both source and destination. ${formatUnknownErrorMessage(deleteError)}`, src)));
47
+ return;
48
+ }
49
+ failed.push(toMoveFailure(src, new McpError(ErrorCode.UNKNOWN, `Cross-device move failed: source not removed. ${formatUnknownErrorMessage(deleteError)}`, src)));
50
+ }
51
+ }
52
+ else {
53
+ failed.push(toMoveFailure(src, error));
54
+ }
55
+ }
56
+ async function processSingleMove(src, destIsDirectory, validDest, movedSources, failed, signal) {
57
+ let validSource;
58
+ try {
59
+ validSource = await validateExistingPath(src, signal);
60
+ assertAllowedFileAccess(src, validSource);
61
+ }
62
+ catch (error) {
63
+ failed.push(toMoveFailure(src, error, ErrorCode.ACCESS_DENIED));
64
+ return;
65
+ }
66
+ const targetPath = destIsDirectory
67
+ ? join(validDest, basename(validSource))
68
+ : validDest;
69
+ if (resolve(validSource) === resolve(targetPath)) {
70
+ return;
71
+ }
72
+ if (resolve(targetPath).startsWith(resolve(validSource) + sep)) {
73
+ failed.push(toMoveFailure(src, new McpError(ErrorCode.INVALID_INPUT, 'Cannot move a directory into its own subdirectory', src), ErrorCode.INVALID_INPUT));
74
+ return;
26
75
  }
27
- const validDest = await validatePathForWrite(args.destination, signal);
28
- // Check if destination exists and is a directory
29
- let destIsDirectory = false;
30
76
  try {
31
- const stats = await fs.stat(validDest);
32
- destIsDirectory = stats.isDirectory();
77
+ await withAbort(rename(validSource, targetPath), signal);
78
+ movedSources.push(validSource);
79
+ }
80
+ catch (error) {
81
+ await handleMoveError(error, src, validSource, targetPath, movedSources, failed, signal);
82
+ }
83
+ }
84
+ async function getDestinationStatus(validDest) {
85
+ try {
86
+ const stats = await stat(validDest);
87
+ return stats.isDirectory();
33
88
  }
34
89
  catch (error) {
35
90
  if (isNodeError(error) && error.code !== 'ENOENT') {
36
91
  throw error;
37
92
  }
38
93
  }
94
+ return false;
95
+ }
96
+ function formatMoveMessage(moved, failed, destination) {
97
+ const movedItemStr = `item${moved === 1 ? '' : 's'}`;
98
+ const failedItemStr = `item${failed === 1 ? '' : 's'}`;
99
+ if (failed > 0) {
100
+ return `Moved ${moved} ${movedItemStr}; failed to move ${failed} ${failedItemStr}`;
101
+ }
102
+ return `Successfully moved ${moved} ${movedItemStr} to ${destination}`;
103
+ }
104
+ async function handleMoveFile(args, signal) {
105
+ const sources = args.sources ?? (args.source ? [args.source] : []);
106
+ if (sources.length === 0) {
107
+ throw new McpError(ErrorCode.INVALID_INPUT, 'No sources provided.');
108
+ }
109
+ const validDest = await validatePathForWrite(args.destination, signal);
110
+ const destIsDirectory = await getDestinationStatus(validDest);
39
111
  if (sources.length > 1 && !destIsDirectory) {
40
- throw new McpError(ErrorCode.E_INVALID_INPUT, 'Destination must be an existing directory when moving multiple files.');
112
+ throw new McpError(ErrorCode.INVALID_INPUT, 'Destination must be an existing directory for multiple sources.');
41
113
  }
42
- // Ensure destination parent directory exists if it's not an existing directory
43
114
  if (!destIsDirectory) {
44
- await withAbort(fs.mkdir(path.dirname(validDest), { recursive: true }), signal);
115
+ await withAbort(mkdir(dirname(validDest), { recursive: true }), signal);
45
116
  }
46
117
  const movedSources = [];
47
118
  const failed = [];
48
119
  for (const src of sources) {
49
- let validSource;
50
- try {
51
- validSource = await validateExistingPath(src, signal);
52
- assertAllowedFileAccess(src, validSource);
53
- }
54
- catch (error) {
55
- failed.push({
56
- source: src,
57
- error: formatUnknownErrorMessage(error),
58
- });
59
- continue;
60
- }
61
- const targetPath = destIsDirectory
62
- ? path.join(validDest, path.basename(validSource))
63
- : validDest;
64
- // Prevent moving a file onto itself
65
- if (path.resolve(validSource) === path.resolve(targetPath)) {
66
- continue;
67
- }
68
- // Prevent moving a directory into its own subdirectory
69
- // Fixes "Missing validation for moving directory into its own subdirectory" finding
70
- if (path.resolve(targetPath).startsWith(path.resolve(validSource) + path.sep)) {
71
- failed.push({
72
- source: src,
73
- error: `Cannot move directory '${src}' into its own subdirectory '${targetPath}'`,
74
- });
75
- continue;
76
- }
77
- try {
78
- await withAbort(fs.rename(validSource, targetPath), signal);
79
- movedSources.push(validSource);
80
- }
81
- catch (error) {
82
- if (isNodeError(error) && error.code === 'EXDEV') {
83
- // Cross-device link, fallback to copy + delete
84
- try {
85
- await withAbort(fs.cp(validSource, targetPath, { recursive: true }), signal);
86
- }
87
- catch (copyError) {
88
- failed.push({
89
- source: src,
90
- error: formatUnknownErrorMessage(copyError),
91
- });
92
- continue;
93
- }
94
- // Copy succeeded — now remove source
95
- try {
96
- await withAbort(fs.rm(validSource, { recursive: true, force: true }), signal);
97
- movedSources.push(validSource);
98
- }
99
- catch (deleteError) {
100
- // Source delete failed after copy — rollback by removing the copy
101
- try {
102
- await fs.rm(targetPath, { recursive: true, force: true });
103
- }
104
- catch {
105
- // Rollback failed — data exists in both locations
106
- failed.push({
107
- source: src,
108
- error: `Cross-device move partially failed: data exists at both '${validSource}' and '${targetPath}'. ${formatUnknownErrorMessage(deleteError)}`,
109
- });
110
- continue;
111
- }
112
- failed.push({
113
- source: src,
114
- error: `Cross-device move failed: could not remove source. ${formatUnknownErrorMessage(deleteError)}`,
115
- });
116
- }
117
- }
118
- else {
119
- failed.push({
120
- source: src,
121
- error: formatUnknownErrorMessage(error),
122
- });
123
- }
120
+ await processSingleMove(src, destIsDirectory, validDest, movedSources, failed, signal);
121
+ }
122
+ const message = formatMoveMessage(movedSources.length, failed.length, args.destination);
123
+ const movedSource = sources.length === 1 ? movedSources[0] : undefined;
124
+ const failedSuffix = failed.length > 0 ? ` (${failed.length} failed)` : '';
125
+ Logger.info(`mv: ${movedSources.length} item(s) → ${args.destination}${failedSuffix}`);
126
+ if (movedSources.length === 0 && failed.length > 0) {
127
+ const firstFailure = failed[0];
128
+ if (firstFailure) {
129
+ throw new McpError(firstFailure.error.code, message, firstFailure.error.path);
124
130
  }
125
131
  }
126
- const message = failed.length > 0
127
- ? `Moved ${movedSources.length} item${movedSources.length === 1 ? '' : 's'}; failed to move ${failed.length} item${failed.length === 1 ? '' : 's'}`
128
- : `Successfully moved ${movedSources.length} item${movedSources.length === 1 ? '' : 's'} to ${args.destination}`;
129
132
  return buildToolResponse(message, {
130
133
  ok: failed.length === 0,
134
+ ...(movedSource ? { source: movedSource } : {}),
131
135
  sources: movedSources,
132
136
  destination: validDest,
133
137
  ...(failed.length > 0 ? { failed } : {}),
@@ -137,25 +141,26 @@ export function registerMoveFileTool(server, options = {}) {
137
141
  const handler = (args, extra) => executeToolWithDiagnostics({
138
142
  toolName: 'mv',
139
143
  extra,
144
+ outputSchema: MoveFileOutputSchema,
140
145
  timedSignal: {},
141
146
  context: { path: args.source ?? args.sources?.[0] },
142
147
  run: (signal) => handleMoveFile(args, signal),
143
- onError: (error) => buildToolErrorResponse(error, ErrorCode.E_UNKNOWN, args.source ?? args.sources?.[0]),
148
+ onError: (error) => buildToolErrorResponse(error, ErrorCode.UNKNOWN, args.source ?? args.sources?.[0]),
144
149
  });
145
150
  const wrappedHandler = wrapToolHandler(handler, {
146
151
  guard: options.isInitialized,
147
152
  progressMessage: (args) => {
148
- const dest = path.basename(args.destination);
153
+ const dest = basename(args.destination);
149
154
  if (args.source && !args.sources?.length) {
150
- return `🛠 mv: ${path.basename(args.source)} → ${dest}`;
155
+ return `🛠 mv: ${basename(args.source)} → ${dest}`;
151
156
  }
152
157
  const count = (args.source ? 1 : 0) + (args.sources?.length ?? 0);
153
158
  return `🛠 mv: ${count} items → ${dest}`;
154
159
  },
155
160
  completionMessage: (args, result) => {
156
- const dest = path.basename(args.destination);
161
+ const dest = basename(args.destination);
157
162
  if (args.source && !args.sources?.length) {
158
- const src = path.basename(args.source);
163
+ const src = basename(args.source);
159
164
  if (result.isError)
160
165
  return `🛠 mv: ${src} → ${dest} • failed`;
161
166
  return `🛠 mv: ${src} → ${dest}`;
@@ -1,9 +1,9 @@
1
- import * as path from 'node:path';
1
+ import { basename } from 'node:path';
2
2
  import { DEFAULT_SEARCH_TIMEOUT_MS } from '../lib/constants.js';
3
3
  import { ErrorCode } from '../lib/errors.js';
4
4
  import { readMultipleFiles } from '../lib/file-operations/metadata.js';
5
5
  import { ReadMultipleFilesInputSchema, ReadMultipleFilesOutputSchema, } from '../schemas.js';
6
- import { buildBatchCompletionSuffix, buildBatchPathContext, buildResourceLink, buildToolErrorResponse, buildToolResponse, createBatchProgressCallbacks, executeToolWithDiagnostics, maybeExternalizeTextContent, READ_ONLY_TOOL_ANNOTATIONS, resolveFinalProgressCurrent, withDefaultIcons, withValidatedArgs, wrapToolHandler, } from './shared.js';
6
+ import { buildBatchCompletionSuffix, buildBatchPathContext, buildResourceLink, buildStructuredError, buildToolErrorResponse, buildToolResponse, createBatchProgressCallbacks, executeToolWithDiagnostics, maybeExternalizeTextContent, READ_ONLY_TOOL_ANNOTATIONS, resolveFinalProgressCurrent, withDefaultIcons, withValidatedArgs, wrapToolHandler, } from './shared.js';
7
7
  import { registerToolTaskIfAvailable } from './task-support.js';
8
8
  const READ_MANY_TOOL_NAME = 'read_many';
9
9
  const READ_MANY_TOOL_LABEL = '🕮 read_many';
@@ -17,13 +17,9 @@ export const READ_MANY_TOOL = {
17
17
  outputSchema: ReadMultipleFilesOutputSchema,
18
18
  annotations: READ_ONLY_TOOL_ANNOTATIONS,
19
19
  taskSupport: 'optional',
20
- nuances: ['Total read budget is capped by `MAX_READ_MANY_TOTAL_SIZE`.'],
21
- gotchas: [
22
- 'Per-file `truncationReason` can be `head`, `tail`, `range`, or `externalized`.',
23
- ],
24
20
  };
25
21
  function buildReadManyResourceName(filePath) {
26
- return `read:${path.basename(filePath)}`;
22
+ return `read:${basename(filePath)}`;
27
23
  }
28
24
  function toStructuredReadManyResult(result) {
29
25
  const structuredResult = {
@@ -72,8 +68,12 @@ function resolveReadManyTruncationReason(result) {
72
68
  }
73
69
  function maybeExternalizeReadManyResult(result, resourceStore) {
74
70
  const truncationReason = resolveReadManyTruncationReason(result);
71
+ const { error, ...rest } = result;
75
72
  const baseResult = {
76
- ...result,
73
+ ...rest,
74
+ ...(error
75
+ ? { error: buildStructuredError(error, ErrorCode.UNKNOWN, result.path) }
76
+ : {}),
77
77
  ...(truncationReason ? { truncationReason } : {}),
78
78
  };
79
79
  if (!result.content) {
@@ -89,12 +89,13 @@ function maybeExternalizeReadManyResult(result, resourceStore) {
89
89
  truncated: true,
90
90
  resourceUri: externalized.entry.uri,
91
91
  truncationReason: 'externalized',
92
+ expiresAt: externalized.entry.expiresAt,
92
93
  };
93
94
  }
94
95
  function buildReadManyTextSection(result) {
95
96
  const header = `=== ${result.path} ===`;
96
97
  if (result.error) {
97
- return `${header}\nError: ${result.error}`;
98
+ return `${header}\nError [${result.error.code}]: ${result.error.message}`;
98
99
  }
99
100
  return `${header}\n${result.content ?? ''}`;
100
101
  }
@@ -128,6 +129,9 @@ function buildReadManyResponsePayload(results, resourceStore) {
128
129
  uri: mappedResult.resourceUri,
129
130
  name: buildReadManyResourceName(mappedResult.path),
130
131
  description: FULL_FILE_CONTENTS_DESCRIPTION,
132
+ ...(mappedResult.expiresAt
133
+ ? { expiresAt: mappedResult.expiresAt }
134
+ : {}),
131
135
  }));
132
136
  }
133
137
  if (mappedResult.error === undefined)
@@ -162,6 +166,7 @@ export function registerReadMultipleFilesTool(server, options = {}) {
162
166
  return executeToolWithDiagnostics({
163
167
  toolName: READ_MANY_TOOL_NAME,
164
168
  extra,
169
+ outputSchema: ReadMultipleFilesOutputSchema,
165
170
  timedSignal: { timeoutMs: DEFAULT_SEARCH_TIMEOUT_MS },
166
171
  context: { path: primaryPath },
167
172
  run: async (signal) => {
@@ -186,7 +191,7 @@ export function registerReadMultipleFilesTool(server, options = {}) {
186
191
  throw error;
187
192
  }
188
193
  },
189
- onError: (error) => buildToolErrorResponse(error, ErrorCode.E_NOT_FILE, primaryPath),
194
+ onError: (error) => buildToolErrorResponse(error, ErrorCode.NOT_FILE, primaryPath),
190
195
  });
191
196
  };
192
197
  const wrappedHandler = wrapToolHandler(handler, {
@@ -1,5 +1,5 @@
1
- import * as path from 'node:path';
2
1
  import { createHash } from 'node:crypto';
2
+ import { basename } from 'node:path';
3
3
  import { DEFAULT_SEARCH_TIMEOUT_MS, MAX_TEXT_FILE_SIZE, } from '../lib/constants.js';
4
4
  import { ErrorCode } from '../lib/errors.js';
5
5
  import { readFile } from '../lib/fs-helpers.js';
@@ -24,7 +24,7 @@ const READ_TOOL_NAME = 'read';
24
24
  const READ_TOOL_LABEL = '🕮 read';
25
25
  const FULL_FILE_CONTENTS_DESCRIPTION = 'Full file contents';
26
26
  function buildReadResourceName(filePath) {
27
- return `read:${path.basename(filePath)}`;
27
+ return `read:${basename(filePath)}`;
28
28
  }
29
29
  function buildReadOptions(args, signal) {
30
30
  const options = {
@@ -99,7 +99,7 @@ function maybeBuildExternalizedReadResponse(filePath, content, structured, resou
99
99
  ]);
100
100
  }
101
101
  function buildReadProgressMessage(args) {
102
- const name = path.basename(args.path);
102
+ const name = basename(args.path);
103
103
  if (args.startLine !== undefined) {
104
104
  const end = args.endLine ?? '…';
105
105
  return `${READ_TOOL_LABEL}: ${name} [lines ${args.startLine}–${end}]`;
@@ -111,12 +111,10 @@ function buildReadProgressMessage(args) {
111
111
  return `${READ_TOOL_LABEL}: ${name}`;
112
112
  }
113
113
  function buildReadCompletionMessage(args, result) {
114
- const name = path.basename(args.path);
114
+ const name = basename(args.path);
115
115
  if (result.isError)
116
116
  return `${READ_TOOL_LABEL}: ${name} • failed`;
117
117
  const structured = result.structuredContent;
118
- if (!structured.ok)
119
- return `${READ_TOOL_LABEL}: ${name} • failed`;
120
118
  const lines = structured.linesRead ?? structured.totalLines;
121
119
  if (structured.startLine !== undefined) {
122
120
  const end = structured.linesRead
@@ -158,10 +156,11 @@ export function registerReadFileTool(server, options = {}) {
158
156
  const handler = (args, extra) => executeToolWithDiagnostics({
159
157
  toolName: READ_TOOL_NAME,
160
158
  extra,
159
+ outputSchema: ReadFileOutputSchema,
161
160
  timedSignal: { timeoutMs: DEFAULT_SEARCH_TIMEOUT_MS },
162
161
  context: { path: args.path },
163
162
  run: (signal) => handleReadFile(args, signal, options.resourceStore),
164
- onError: (error) => buildToolErrorResponse(error, ErrorCode.E_NOT_FILE, args.path),
163
+ onError: (error) => buildToolErrorResponse(error, ErrorCode.NOT_FILE, args.path),
165
164
  });
166
165
  const wrappedHandler = wrapToolHandler(handler, {
167
166
  guard: options.isInitialized,