Skip to main content
Glama
rawr-ai

Filesystem MCP Server

directory_tree

Generate a recursive JSON tree structure of files and directories with depth control and exclusion patterns using glob syntax. Each entry includes name, type, and children arrays for directories. Ideal for visualizing and managing filesystem hierarchies.

Instructions

Get a recursive tree view of files and directories as a JSON structure. Supports depth limiting to control traversal depth and exclusion patterns using glob syntax. Each entry includes 'name', 'type' (file/directory), and 'children' for directories. Files have no children array, while directories always have a children array (which may be empty). Requires maxDepth parameter (default 2) to limit recursion. Use excludePatterns to filter out unwanted files/directories. The output is formatted with 2-space indentation for readability. Only works within allowed directories.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
excludePatternsNoGlob patterns for files/directories to exclude (e.g., "*.log", "node_modules").
maxDepthYesMaximum depth to traverse. Must be a positive integer. Handler default: 2.
pathYes

Implementation Reference

  • Core implementation of the directory_tree tool handler. Parses args, validates path, recursively builds directory tree structure with depth limit and exclude patterns, returns JSON tree.
    export async function handleDirectoryTree(
      args: unknown,
      allowedDirectories: string[],
      symlinksMap: Map<string, string>,
      noFollowSymlinks: boolean
    ) {
      const parsed = parseArgs(DirectoryTreeArgsSchema, args, 'directory_tree');
    
      const { path: startPath, maxDepth, excludePatterns } = parsed; // maxDepth is mandatory (handler default: 2)
      const validatedStartPath = await validatePath(startPath, allowedDirectories, symlinksMap, noFollowSymlinks);
    
      async function buildTree(
        currentPath: string,
        basePath: string,
        currentDepth: number,
        maxDepth?: number,
        excludePatterns?: string[]
      ): Promise<TreeEntry[]> {
        // Depth check
        if (maxDepth !== undefined && currentDepth >= maxDepth) {
          return []; // Stop traversal if max depth is reached
        }
    
        const validPath = await validatePath(currentPath, allowedDirectories, symlinksMap, noFollowSymlinks);
        
        let entries;
        try {
          entries = await fs.readdir(validPath, { withFileTypes: true });
        } catch (error) {
          // Handle cases where directory might not be readable
          console.error(`Error reading directory ${validPath}: ${error}`);
          return [];
        }
        
        const result: TreeEntry[] = [];
    
        for (const entry of entries) {
          const entryFullPath = path.join(currentPath, entry.name);
          const entryRelativePath = path.relative(basePath, entryFullPath);
    
          // Exclusion check using minimatch
          if (excludePatterns && excludePatterns.length > 0) {
            const shouldExclude = excludePatterns.some(pattern =>
              minimatch(entryRelativePath, pattern, { dot: true, matchBase: true })
            );
            if (shouldExclude) {
              continue; // Skip this entry if it matches any exclude pattern
            }
          }
    
          const entryData: TreeEntry = {
            name: entry.name,
            type: entry.isDirectory() ? 'directory' : 'file'
          };
    
          if (entry.isDirectory()) {
            // Recursive call with incremented depth
            entryData.children = await buildTree(
              entryFullPath,
              basePath,
              currentDepth + 1,
              maxDepth,
              excludePatterns
            );
          }
    
          result.push(entryData);
        }
    
        return result;
      }
    
      // Initial call to buildTree with base parameters
      const treeData = await buildTree(
        validatedStartPath, 
        validatedStartPath, 
        0, 
        maxDepth, 
        excludePatterns
      );
      
      return {
        content: [{
          type: "text",
          text: JSON.stringify(treeData, null, 2)
        }],
      };
    }
  • TypeBox schema defining input parameters for directory_tree: path (required), maxDepth (integer >=1), excludePatterns (optional array of glob patterns).
    export const DirectoryTreeArgsSchema = Type.Object({
      path: Type.String(),
      maxDepth: Type.Integer({
        minimum: 1,
        description: 'Maximum depth to traverse. Must be a positive integer. Handler default: 2.'
      }),
      excludePatterns: Type.Optional(
        Type.Array(Type.String(), {
          default: [],
          description: 'Glob patterns for files/directories to exclude (e.g., "*.log", "node_modules").'
        })
      )
    });
    export type DirectoryTreeArgs = Static<typeof DirectoryTreeArgsSchema>;
  • index.ts:210-211 (registration)
    Maps the 'directory_tree' tool name to the handleDirectoryTree function in the toolHandlers object, passing server context (allowedDirectories, symlinksMap, noFollowSymlinks). Used by server.addTool loop.
    directory_tree: (a: unknown) =>
      handleDirectoryTree(a, allowedDirectories, symlinksMap, noFollowSymlinks),
  • index.ts:308-308 (registration)
    Registers 'directory_tree' tool metadata (name and description) in the allTools array, filtered by permissions, then added to MCP server.
    { name: "directory_tree", description: "Directory tree view" },
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden. It discloses key behavioral traits: output format (JSON with 2-space indentation), structure details (children arrays for directories, none for files), and constraints (works only within allowed directories). However, it doesn't mention error handling, performance implications of deep recursion, or whether it follows symlinks, leaving some gaps.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with the core purpose, followed by parameter details and constraints, all in clear, efficient sentences. Every sentence adds value: no repetition or fluff, making it easy to scan and understand quickly.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no annotations and no output schema, the description does a good job covering the tool's behavior, parameters, and constraints. It explains the output structure and formatting, which compensates for the lack of output schema. However, it could mention performance considerations or error cases for completeness, given the recursive nature.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The description adds meaningful context beyond the schema: it explains that excludePatterns uses glob syntax and gives examples ('*.log', 'node_modules'), clarifies that maxDepth has a default of 2, and ties parameters to functionality (depth limiting controls traversal, excludePatterns filters unwanted items). With 67% schema coverage, this compensates well for the uncovered aspects.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the verb 'Get' and resource 'recursive tree view of files and directories as a JSON structure', distinguishing it from sibling tools like list_directory (flat listing) or get_file_info (single file metadata). It specifies the recursive nature and JSON output format, making the purpose specific and distinct.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides clear context: 'Only works within allowed directories' sets a prerequisite, and the mention of depth limiting and exclusion patterns implies use cases for controlling traversal. However, it doesn't explicitly state when to use this tool versus alternatives like list_directory or search_files, missing explicit sibling differentiation.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Related Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/rawr-ai/mcp-filesystem'

If you have feedback or need assistance with the MCP directory API, please join our Discord server