@@ -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+
117121const 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