@j0hanz/fs-context-mcp 2.7.3 → 2.7.4

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.
@@ -56,7 +56,7 @@ export function registerApplyPatchTool(server, options = {}) {
56
56
  guard: options.isInitialized,
57
57
  progressMessage: (args) => {
58
58
  const name = path.basename(args.path);
59
- return `▣ apply_patch: ${name}`;
59
+ return `🛠 apply_patch: ${name}`;
60
60
  },
61
61
  }));
62
62
  }
@@ -105,7 +105,7 @@ export function registerCalculateHashTool(server, options = {}) {
105
105
  guard: options.isInitialized,
106
106
  progressMessage: (args) => {
107
107
  const name = path.basename(args.path);
108
- return `⩩ calculate_hash: ${name}`;
108
+ return `⌗ calculate_hash: ${name}`;
109
109
  },
110
110
  }));
111
111
  }
@@ -37,6 +37,6 @@ export function registerCreateDirectoryTool(server, options = {}) {
37
37
  }, (error) => buildToolErrorResponse(error, ErrorCode.E_UNKNOWN, args.path)), { path: args.path });
38
38
  server.registerTool('mkdir', withDefaultIcons({ ...CREATE_DIRECTORY_TOOL }, options.iconInfo), wrapToolHandler(handler, {
39
39
  guard: options.isInitialized,
40
- progressMessage: (args) => `✚ mkdir: ${path.basename(args.path)}`,
40
+ progressMessage: (args) => `🛠 mkdir: ${path.basename(args.path)}`,
41
41
  }));
42
42
  }
@@ -53,6 +53,6 @@ export function registerDeleteFileTool(server, options = {}) {
53
53
  }), { path: args.path });
54
54
  server.registerTool('rm', withDefaultIcons({ ...DELETE_FILE_TOOL }, options.iconInfo), wrapToolHandler(handler, {
55
55
  guard: options.isInitialized,
56
- progressMessage: (args) => `✘ rm: ${path.basename(args.path)}`,
56
+ progressMessage: (args) => `✖ rm: ${path.basename(args.path)}`,
57
57
  }));
58
58
  }
@@ -72,7 +72,7 @@ export function registerDiffFilesTool(server, options = {}) {
72
72
  progressMessage: (args) => {
73
73
  const name1 = path.basename(args.original);
74
74
  const name2 = path.basename(args.modified);
75
- return `⟺ diff_files: ${name1} ↔ ${name2}`;
75
+ return `⇄ diff_files: ${name1} ↔ ${name2}`;
76
76
  },
77
77
  }));
78
78
  }
@@ -62,7 +62,7 @@ export function registerEditFileTool(server, options = {}) {
62
62
  guard: options.isInitialized,
63
63
  progressMessage: (args) => {
64
64
  const name = path.basename(args.path);
65
- return `✎ edit: ${name} ${args.edits.length} edits`;
65
+ return `🛠 edit: ${name} (${args.edits.length} edits)`;
66
66
  },
67
67
  }));
68
68
  }
@@ -99,9 +99,9 @@ export function registerListDirectoryTool(server, options = {}) {
99
99
  guard: options.isInitialized,
100
100
  progressMessage: (args) => {
101
101
  if (args.path) {
102
- return `≣ ls: ${path.basename(args.path)}`;
102
+ return `☰ ls: ${path.basename(args.path)}`;
103
103
  }
104
- return ' ls';
104
+ return ' ls';
105
105
  },
106
106
  }));
107
107
  }
@@ -53,6 +53,6 @@ export function registerMoveFileTool(server, options = {}) {
53
53
  }, (error) => buildToolErrorResponse(error, ErrorCode.E_UNKNOWN, args.source)), { path: args.source });
54
54
  server.registerTool('mv', withDefaultIcons({ ...MOVE_FILE_TOOL }, options.iconInfo), wrapToolHandler(handler, {
55
55
  guard: options.isInitialized,
56
- progressMessage: (args) => `➔ mv: ${path.basename(args.source)} -> ${path.basename(args.destination)}`,
56
+ progressMessage: (args) => `🛠 mv: ${path.basename(args.source)} ${path.basename(args.destination)}`,
57
57
  }));
58
58
  }
@@ -90,7 +90,7 @@ async function handleReadMultipleFiles(args, signal, resourceStore) {
90
90
  return result.path;
91
91
  })
92
92
  .join('\n');
93
- return buildToolResponse(text, structured, resourceLinks);
93
+ return buildToolResponse(text, structured, resourceLinks, resourceStore);
94
94
  }
95
95
  export function registerReadMultipleFilesTool(server, options = {}) {
96
96
  const handler = (args, extra) => {
@@ -54,7 +54,7 @@ async function handleReadFile(args, signal, resourceStore) {
54
54
  };
55
55
  const externalized = maybeExternalizeTextContent(resourceStore, result.content, { name: `read:${path.basename(args.path)}`, mimeType: 'text/plain' });
56
56
  if (!externalized) {
57
- return buildToolResponse(result.content, structured);
57
+ return buildToolResponse(result.content, structured, [], resourceStore);
58
58
  }
59
59
  const { entry, preview } = externalized;
60
60
  const structuredWithResource = {
@@ -75,7 +75,7 @@ async function handleReadFile(args, signal, resourceStore) {
75
75
  mimeType: entry.mimeType,
76
76
  description: 'Full file contents',
77
77
  }),
78
- ]);
78
+ ], resourceStore);
79
79
  }
80
80
  export function registerReadFileTool(server, options = {}) {
81
81
  const handler = (args, extra) => withToolDiagnostics('read', () => withToolErrorHandling(async () => {
@@ -93,7 +93,7 @@ export function registerReadFileTool(server, options = {}) {
93
93
  const name = path.basename(args.path);
94
94
  if (args.startLine !== undefined) {
95
95
  const end = args.endLine ?? '…';
96
- return `🕮 read: ${name} ${args.startLine}-${end}`;
96
+ return `🕮 read: ${name} [${args.startLine}-${end}]`;
97
97
  }
98
98
  return `🕮 read: ${name}`;
99
99
  },
@@ -176,7 +176,7 @@ export function registerSearchAndReplaceTool(server, options = {}) {
176
176
  const handler = (args, extra) => withToolDiagnostics('search_and_replace', () => withToolErrorHandling(async () => {
177
177
  notifyProgress(extra, {
178
178
  current: 0,
179
- message: `⟳ search_and_replace: ${args.filePattern}`,
179
+ message: `🛠 search_and_replace: ${args.filePattern}`,
180
180
  });
181
181
  const { signal, cleanup } = createTimedAbortSignal(extra.signal);
182
182
  try {
@@ -185,7 +185,7 @@ export function registerSearchAndReplaceTool(server, options = {}) {
185
185
  const finalCurrent = (sc.processedFiles ?? 0) + 1;
186
186
  notifyProgress(extra, {
187
187
  current: finalCurrent,
188
- message: `⟳ search_and_replace: ${args.filePattern} → ${String(sc.filesChanged ?? 0)} files`,
188
+ message: `🛠 search_and_replace: ${args.filePattern} → ${String(sc.filesChanged ?? 0)} files`,
189
189
  });
190
190
  return result;
191
191
  }
@@ -38,6 +38,6 @@ export function registerListAllowedDirectoriesTool(server, options = {}) {
38
38
  const handler = () => withToolErrorHandling(() => withToolDiagnostics('roots', () => Promise.resolve(handleListAllowedDirectories())), (error) => buildToolErrorResponse(error, ErrorCode.E_UNKNOWN));
39
39
  server.registerTool('roots', withDefaultIcons({ ...LIST_ALLOWED_DIRECTORIES_TOOL }, options.iconInfo), wrapToolHandler(handler, {
40
40
  guard: options.isInitialized,
41
- progressMessage: () => ' roots',
41
+ progressMessage: () => ' roots',
42
42
  }));
43
43
  }
@@ -17,7 +17,7 @@ export declare function buildResourceLink(params: {
17
17
  mimeType?: string;
18
18
  description?: string;
19
19
  }): ContentBlock;
20
- export declare function buildToolResponse<T>(text: string, structuredContent: T, extraContent?: ContentBlock[]): {
20
+ export declare function buildToolResponse<T>(text: string, structuredContent: T, extraContent?: ContentBlock[], resourceStore?: ResourceStore): {
21
21
  content: ContentBlock[];
22
22
  structuredContent: T;
23
23
  };
@@ -32,7 +32,7 @@ export function buildResourceLink(params) {
32
32
  ...(params.mimeType ? { mimeType: params.mimeType } : {}),
33
33
  };
34
34
  }
35
- function buildContentBlock(text, structuredContent, extraContent = []) {
35
+ function buildContentBlock(text, structuredContent, extraContent = [], resourceStore) {
36
36
  let json;
37
37
  try {
38
38
  json = JSON.stringify(structuredContent);
@@ -51,12 +51,23 @@ function buildContentBlock(text, structuredContent, extraContent = []) {
51
51
  preview,
52
52
  });
53
53
  }
54
+ const externalized = maybeExternalizeTextContent(resourceStore, json, {
55
+ name: 'tool:structuredContent',
56
+ mimeType: 'application/json',
57
+ });
58
+ const jsonContent = externalized
59
+ ? [
60
+ { type: 'text', text: externalized.preview },
61
+ buildResourceLink({
62
+ uri: externalized.entry.uri,
63
+ name: externalized.entry.name,
64
+ mimeType: externalized.entry.mimeType,
65
+ description: 'Full structuredContent JSON',
66
+ }),
67
+ ]
68
+ : [{ type: 'text', text: json }];
54
69
  return {
55
- content: [
56
- { type: 'text', text },
57
- ...extraContent,
58
- { type: 'text', text: json },
59
- ],
70
+ content: [{ type: 'text', text }, ...extraContent, ...jsonContent],
60
71
  structuredContent,
61
72
  };
62
73
  }
@@ -68,8 +79,8 @@ function resolveDetailedError(error, defaultCode, path) {
68
79
  }
69
80
  return detailed;
70
81
  }
71
- export function buildToolResponse(text, structuredContent, extraContent = []) {
72
- return buildContentBlock(text, structuredContent, extraContent);
82
+ export function buildToolResponse(text, structuredContent, extraContent = [], resourceStore) {
83
+ return buildContentBlock(text, structuredContent, extraContent, resourceStore);
73
84
  }
74
85
  function canSendProgress(extra) {
75
86
  return (extra._meta?.progressToken !== undefined &&
@@ -87,7 +87,7 @@ export function registerGetMultipleFileInfoTool(server, options = {}) {
87
87
  };
88
88
  const wrappedHandler = wrapToolHandler(handler, {
89
89
  guard: options.isInitialized,
90
- progressMessage: (args) => `ⓘ+ stat_many: ${args.paths.length} paths`,
90
+ progressMessage: (args) => `🛈 stat_many: ${args.paths.length} paths`,
91
91
  });
92
92
  const taskOptions = options.isInitialized
93
93
  ? { guard: options.isInitialized }
@@ -74,6 +74,6 @@ export function registerGetFileInfoTool(server, options = {}) {
74
74
  }, (error) => buildToolErrorResponse(error, ErrorCode.E_NOT_FOUND, args.path)), { path: args.path });
75
75
  server.registerTool('stat', withDefaultIcons({ ...GET_FILE_INFO_TOOL }, options.iconInfo), wrapToolHandler(handler, {
76
76
  guard: options.isInitialized,
77
- progressMessage: (args) => `ⓘ stat: ${path.basename(args.path)}`,
77
+ progressMessage: (args) => `🛈 stat: ${path.basename(args.path)}`,
78
78
  }));
79
79
  }
@@ -58,9 +58,9 @@ export function registerTreeTool(server, options = {}) {
58
58
  guard: options.isInitialized,
59
59
  progressMessage: (args) => {
60
60
  if (args.path) {
61
- return `⊨ tree: ${path.basename(args.path)}`;
61
+ return `⎇ tree: ${path.basename(args.path)}`;
62
62
  }
63
- return ' tree';
63
+ return ' tree';
64
64
  },
65
65
  });
66
66
  const taskOptions = options.isInitialized
@@ -41,6 +41,6 @@ export function registerWriteFileTool(server, options = {}) {
41
41
  }, (error) => buildToolErrorResponse(error, ErrorCode.E_UNKNOWN, args.path)), { path: args.path });
42
42
  server.registerTool('write', withDefaultIcons({ ...WRITE_FILE_TOOL }, options.iconInfo), wrapToolHandler(handler, {
43
43
  guard: options.isInitialized,
44
- progressMessage: (args) => `✎ write: ${path.basename(args.path)}`,
44
+ progressMessage: (args) => `🛠 write: ${path.basename(args.path)}`,
45
45
  }));
46
46
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@j0hanz/fs-context-mcp",
3
- "version": "2.7.3",
3
+ "version": "2.7.4",
4
4
  "mcpName": "io.github.j0hanz/fs-context",
5
5
  "description": "MCP Server that enables LLMs to interact with the local filesystem.",
6
6
  "type": "module",