Skip to content

Commit deffdb9

Browse files
author
Enrico Ballardini
committed
directory_tree base implementation
1 parent a096c95 commit deffdb9

File tree

1 file changed

+48
-0
lines changed

1 file changed

+48
-0
lines changed

src/filesystem/index.ts

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,10 @@ const ListDirectoryArgsSchema = z.object({
114114
path: z.string(),
115115
});
116116

117+
const DirectoryTreeArgsSchema = z.object({
118+
path: z.string(),
119+
});
120+
117121
const MoveFileArgsSchema = z.object({
118122
source: z.string(),
119123
destination: z.string(),
@@ -251,6 +255,16 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
251255
"finding specific files within a directory. Only works within allowed directories.",
252256
inputSchema: zodToJsonSchema(ListDirectoryArgsSchema) as ToolInput,
253257
},
258+
{
259+
name: "directory_tree",
260+
description:
261+
"Get a recursive tree view of files and directories starting from a specified path. " +
262+
"Results are formatted in a hierarchical ASCII tree structure with proper indentation " +
263+
"using pipes and dashes (│ ├ └ ─). Files and directories are distinguished " +
264+
"with [F] and [D] prefixes. This tool provides a comprehensive visualization of nested " +
265+
"directory structures. Only works within allowed directories.",
266+
inputSchema: zodToJsonSchema(DirectoryTreeArgsSchema) as ToolInput,
267+
},
254268
{
255269
name: "move_file",
256270
description:
@@ -373,6 +387,40 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
373387
};
374388
}
375389

390+
case "directory_tree": {
391+
const parsed = ListDirectoryArgsSchema.safeParse(args);
392+
if (!parsed.success) {
393+
throw new Error(`Invalid arguments for directory_tree: ${parsed.error}`);
394+
}
395+
396+
async function buildTree(currentPath: string, prefix = ""): Promise<string> {
397+
const validPath = await validatePath(currentPath);
398+
const entries = await fs.readdir(validPath, {withFileTypes: true});
399+
let result = "";
400+
401+
for (let i = 0; i < entries.length; i++) {
402+
const entry = entries[i];
403+
const isLast = i === entries.length - 1;
404+
const connector = isLast ? "└── " : "├── ";
405+
const newPrefix = prefix + (isLast ? " " : "│ ");
406+
407+
result += `${prefix}${connector}${entry.isDirectory() ? "[D]" : "[F]"} ${entry.name}\n`;
408+
409+
if (entry.isDirectory()) {
410+
const subPath = path.join(currentPath, entry.name);
411+
result += await buildTree(subPath, newPrefix);
412+
}
413+
}
414+
415+
return result;
416+
}
417+
418+
const treeOutput = await buildTree(parsed.data.path);
419+
return {
420+
content: [{type: "text", text: treeOutput}],
421+
};
422+
}
423+
376424
case "move_file": {
377425
const parsed = MoveFileArgsSchema.safeParse(args);
378426
if (!parsed.success) {

0 commit comments

Comments
 (0)