read_directory
List files and directories in a specified path with options for recursion, depth limits, hidden files, and pattern filtering to organize and access file system contents.
Instructions
List contents of a directory
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | Path to the directory | |
| recursive | No | Include subdirectories | |
| max_depth | No | Max recursion depth | |
| include_hidden | No | Include hidden files | |
| pattern | No | Glob pattern filter |
Implementation Reference
- src/tools/read.ts:138-216 (handler)The core implementation of the read_directory tool logic.
async function readDirectoryImpl( input: ReadDirectoryInput, currentDepth = 0 ): Promise<ToolResult> { try { const absolutePath = path.resolve(input.path); // Check if directory exists const stats = await fs.stat(absolutePath); if (!stats.isDirectory()) { return { isError: true, content: [ { type: 'text', text: JSON.stringify({ code: 'INVALID_PATH', message: `Path is not a directory: ${input.path}`, }), }, ], }; } // Check depth limit if (input.recursive && currentDepth >= input.max_depth) { return { isError: true, content: [ { type: 'text', text: JSON.stringify({ code: 'DEPTH_EXCEEDED', message: `Maximum recursion depth ${input.max_depth} exceeded`, }), }, ], }; } // Read directory entries const entries = await fs.readdir(absolutePath, { withFileTypes: true }); const results: DirectoryEntry[] = []; for (const entry of entries) { // Skip hidden files if not requested if (!input.include_hidden && entry.name.startsWith('.')) { continue; } // Apply glob pattern filter if specified if (input.pattern) { // Simple glob matching (basic implementation) const regex = globToRegex(input.pattern); if (!regex.test(entry.name)) { continue; } } const entryPath = path.join(absolutePath, entry.name); const isFile = entry.isFile(); const isDirectory = entry.isDirectory(); const dirEntry: DirectoryEntry = { name: entry.name, path: entryPath, isFile, isDirectory, }; // Get size for files if (isFile) { try { const entryStats = await fs.stat(entryPath); dirEntry.size = entryStats.size; } catch { // Ignore stat errors for individual files } - src/tools/read.ts:373-388 (registration)Tool registration for read_directory in the MCP server.
// read_directory tool server.tool( 'read_directory', 'List contents of a directory', { path: z.string().describe('Path to the directory'), recursive: z.boolean().optional().describe('Include subdirectories'), max_depth: z.number().optional().describe('Max recursion depth'), include_hidden: z.boolean().optional().describe('Include hidden files'), pattern: z.string().optional().describe('Glob pattern filter'), }, async (args) => { const input = ReadDirectoryInputSchema.parse(args); return await readDirectoryImpl(input); } ); - src/types.ts:162-168 (schema)Zod schema for validating the read_directory input.
export const ReadDirectoryInputSchema = z.object({ path: z.string().describe('Path to directory'), recursive: z.boolean().default(false).describe('Include subdirectories'), max_depth: z.number().default(5).describe('Max recursion depth'), include_hidden: z.boolean().default(false).describe('Include hidden files'), pattern: z.string().optional().describe('Glob pattern filter'), });