@@ -114,6 +114,10 @@ const ListDirectoryArgsSchema = z.object({
114
114
path : z . string ( ) ,
115
115
} ) ;
116
116
117
+ const DirectoryTreeArgsSchema = z . object ( {
118
+ path : z . string ( ) ,
119
+ } ) ;
120
+
117
121
const MoveFileArgsSchema = z . object ( {
118
122
source : z . string ( ) ,
119
123
destination : z . string ( ) ,
@@ -251,6 +255,16 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
251
255
"finding specific files within a directory. Only works within allowed directories." ,
252
256
inputSchema : zodToJsonSchema ( ListDirectoryArgsSchema ) as ToolInput ,
253
257
} ,
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
+ } ,
254
268
{
255
269
name : "move_file" ,
256
270
description :
@@ -373,6 +387,40 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
373
387
} ;
374
388
}
375
389
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
+
376
424
case "move_file" : {
377
425
const parsed = MoveFileArgsSchema . safeParse ( args ) ;
378
426
if ( ! parsed . success ) {
0 commit comments