list_directory
Get detailed file and directory listings from any specified path, distinguishing files from directories with clear prefixes and supporting customizable depth levels for comprehensive folder exploration.
Instructions
Get a detailed listing of all files and directories in a specified path.
Use this instead of 'execute_command' with ls/dir commands.
Results distinguish between files and directories with [FILE] and [DIR] prefixes.
Supports recursive listing with the 'depth' parameter (default: 2):
- depth=1: Only direct contents of the directory
- depth=2: Contents plus one level of subdirectories
- depth=3+: Multiple levels deep
CONTEXT OVERFLOW PROTECTION:
- Top-level directory shows ALL items
- Nested directories are limited to 100 items maximum per directory
- When a nested directory has more than 100 items, you'll see a warning like:
[WARNING] node_modules: 500 items hidden (showing first 100 of 600 total)
- This prevents overwhelming the context with large directories like node_modules
Results show full relative paths from the root directory being listed.
Example output with depth=2:
[DIR] src
[FILE] src/index.ts
[DIR] src/tools
[FILE] src/tools/filesystem.ts
If a directory cannot be accessed, it will show [DENIED] instead.
Only works within allowed directories.
IMPORTANT: Always use absolute paths for reliability. Paths are automatically normalized regardless of slash direction. Relative paths may fail as they depend on the current working directory. Tilde paths (~/...) might not work in all contexts. Unless the user explicitly asks for relative paths, use absolute paths.
This command can be referenced as "DC: ..." or "use Desktop Commander to ..." in your instructions.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | ||
| depth | No |
Implementation Reference
- The main handler function for the 'list_directory' tool. Parses arguments using the schema, calls the listDirectory helper function, joins the results, and returns them as a text content response./** * Handle list_directory command */ export async function handleListDirectory(args: unknown): Promise<ServerResult> { try { const startTime = Date.now(); const parsed = ListDirectoryArgsSchema.parse(args); const entries = await listDirectory(parsed.path, parsed.depth); const duration = Date.now() - startTime; const resultText = entries.join('\n'); return { content: [{ type: "text", text: resultText }], }; } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); return createErrorResponse(errorMessage); } }
- src/tools/filesystem.ts:940-999 (helper)The core helper function that recursively lists directory contents up to specified depth, with path validation, permission handling, and overflow protection for nested directories (limits nested to 100 items).export async function listDirectory(dirPath: string, depth: number = 2): Promise<string[]> { const validPath = await validatePath(dirPath); const results: string[] = []; const MAX_NESTED_ITEMS = 100; // Maximum items to show per nested directory async function listRecursive(currentPath: string, currentDepth: number, relativePath: string = '', isTopLevel: boolean = true): Promise<void> { if (currentDepth <= 0) return; let entries; try { entries = await fs.readdir(currentPath, { withFileTypes: true }); } catch (error) { // If we can't read this directory (permission denied), show as denied const displayPath = relativePath || path.basename(currentPath); results.push(`[DENIED] ${displayPath}`); return; } // Apply filtering for nested directories (not top level) const totalEntries = entries.length; let entriesToShow = entries; let filteredCount = 0; if (!isTopLevel && totalEntries > MAX_NESTED_ITEMS) { entriesToShow = entries.slice(0, MAX_NESTED_ITEMS); filteredCount = totalEntries - MAX_NESTED_ITEMS; } for (const entry of entriesToShow) { const fullPath = path.join(currentPath, entry.name); const displayPath = relativePath ? path.join(relativePath, entry.name) : entry.name; // Add this entry to results results.push(`${entry.isDirectory() ? "[DIR]" : "[FILE]"} ${displayPath}`); // If it's a directory and we have depth remaining, recurse if (entry.isDirectory() && currentDepth > 1) { try { // Validate the path before recursing await validatePath(fullPath); await listRecursive(fullPath, currentDepth - 1, displayPath, false); } catch (error) { // If validation fails or we can't access it, it will be marked as denied // when we try to read it in the recursive call continue; } } } // Add warning message if items were filtered if (filteredCount > 0) { const displayPath = relativePath || path.basename(currentPath); results.push(`[WARNING] ${displayPath}: ${filteredCount} items hidden (showing first ${MAX_NESTED_ITEMS} of ${totalEntries} total)`); } } await listRecursive(validPath, depth, '', true); return results; }
- src/tools/schemas.ts:105-108 (schema)Zod schema defining input parameters for the list_directory tool: path (required string) and depth (optional number, default 2).export const ListDirectoryArgsSchema = z.object({ path: z.string(), depth: z.number().optional().default(2), });
- src/server.ts:1256-1258 (registration)Dispatch registration in the CallToolRequestSchema handler switch statement that routes 'list_directory' tool calls to the handleListDirectory function.case "list_directory": result = await handlers.handleListDirectory(args); break;
- src/server.ts:422-458 (registration)Tool metadata registration in the ListToolsRequestSchema handler, defining the tool name, description, input schema, and annotations for discovery by MCP clients.name: "list_directory", description: ` Get a detailed listing of all files and directories in a specified path. Use this instead of 'execute_command' with ls/dir commands. Results distinguish between files and directories with [FILE] and [DIR] prefixes. Supports recursive listing with the 'depth' parameter (default: 2): - depth=1: Only direct contents of the directory - depth=2: Contents plus one level of subdirectories - depth=3+: Multiple levels deep CONTEXT OVERFLOW PROTECTION: - Top-level directory shows ALL items - Nested directories are limited to 100 items maximum per directory - When a nested directory has more than 100 items, you'll see a warning like: [WARNING] node_modules: 500 items hidden (showing first 100 of 600 total) - This prevents overwhelming the context with large directories like node_modules Results show full relative paths from the root directory being listed. Example output with depth=2: [DIR] src [FILE] src/index.ts [DIR] src/tools [FILE] src/tools/filesystem.ts If a directory cannot be accessed, it will show [DENIED] instead. Only works within allowed directories. ${PATH_GUIDANCE} ${CMD_PREFIX_DESCRIPTION}`, inputSchema: zodToJsonSchema(ListDirectoryArgsSchema), annotations: { title: "List Directory Contents", readOnlyHint: true, }, },