How DesktopCommander MCP Handles Recursive Directory Listing in Large Directories

DesktopCommander MCP limits recursive directory listing through a configurable depth parameter (default 2) and enforces a 100-item cap per nested folder, appending explicit [WARNING] tags when content is truncated to keep responses performant and memory-safe.

DesktopCommanderMCP is a Model Context Protocol server that exposes filesystem operations to AI assistants and user interfaces. When performing recursive directory listing on large directories or deep folder trees, the system implements architectural safeguards in src/tools/filesystem.ts to prevent unbounded memory consumption while maintaining transparency about filtered results.

Depth-Limited Recursion Architecture

The foundation of safe directory traversal lies in controlled recursion depth. Rather than walking entire filesystem trees, the listDirectory utility accepts a depth parameter that governs how many levels deep the enumeration proceeds.

The listRecursive Implementation

In src/tools/filesystem.ts, the private helper listRecursive manages the descent logic. The function accepts a currentDepth parameter and terminates recursion when currentDepth <= 0. This prevents the server from exhaustively scanning massive directory structures like node_modules or system folders that might contain hundreds of thousands of files. By default, the RPC handler handleListDirectory in src/handlers/filesystem-handlers.ts sets this depth to 2, balancing comprehensiveness with performance.

Per-Folder Item Caps for Large Directories

Beyond depth limits, DesktopCommander MCP implements horizontal constraints through the MAX_NESTED_ITEMS = 100 constant. This limit applies to every directory except the top-level path being requested, ensuring that individual folders with excessive contents do not overwhelm the response buffer.

When listRecursive encounters a subdirectory containing more than 100 entries, it processes only the first 100 items and calculates the remainder. This cap is crucial for directories like build outputs or log archives that might contain thousands of homogeneous files, keeping the response size predictable regardless of folder contents.

Warning System and Error Transparency

Truncation Alerts

When the 100-item cap filters content, the utility appends a machine-readable warning line to the output array:


[WARNING] subdir: 250 items hidden (showing first 100 of 350 total)

This format allows client applications and language models to detect truncation programmatically and request deeper listings if necessary. The warning includes both the hidden count and total count, providing complete visibility into the scope of filtered data.

Graceful Error Handling

The recursion logic distinguishes between different failure modes using specific error codes (ENOENT, EPERM, EACCES, ETIMEDOUT). When encountering permission-denied or inaccessible paths—such as cloud-only files or protected system directories—the handler inserts a descriptive marker instead of crashing:


[DENIED] secret_folder — not accessible (permission denied, cloud-only file, or Full Disk Access not granted)

This approach ensures the scan continues past blocked entries while informing the user exactly why certain paths remain invisible.

Implementation Details and Usage

Each filesystem entry is prefixed with [DIR] or [FILE] to facilitate downstream rendering. The following examples demonstrate how to invoke the protected listing logic from client code.

RPC Invocation via MCP Client

import { rpc } from '@desktop-commander/mcp';

// Enumerate the home directory with depth 3
const result = await rpc.list_directory({
  path: '~',
  depth: 3,
  origin: 'ui'   // UI receives structuredContent for navigation
});
console.log(result.content.join('\n'));

The handleListDirectory function in src/handlers/filesystem-handlers.ts forwards these parameters to listDirectory, which orchestrates the recursive walk with safety guards enabled.

Direct Utility Access

import { listDirectory } from './src/tools/filesystem.js';

async function demo() {
  const entries = await listDirectory('/usr', 2);
  for (const line of entries) {
    console.log(line);
  }
}
demo();

Executing this against a directory with thousands of files yields at most 100 entries per nested subdirectory, followed by [WARNING] lines wherever truncation occurs.

Programmatic Warning Detection

if (line.startsWith('[WARNING]')) {
  // Parse the hidden count and request a deeper listing if needed
  const match = line.match(/(\d+) items hidden/);
  if (match) console.log(`Found ${match[1]} hidden items`);
}

The predictable [WARNING] <path>: <n> items hidden format enables automated responses to truncated data.

Summary

  • Depth-limited recursion stops traversal when currentDepth <= 0, preventing unbounded tree walks on deep filesystems.
  • 100-item caps (MAX_NESTED_ITEMS) restrict each nested folder to manageable output sizes.
  • Explicit warnings communicate truncation details via standardized [WARNING] tags for transparency.
  • Robust error handling converts permission errors (EPERM, EACCES) into [DENIED] messages without halting execution.
  • Type prefixes ([DIR], [FILE]) simplify parsing for UI rendering and automated processing.

Frequently Asked Questions

What is the default recursion depth for directory listings?

The default depth is 2 levels, as specified in the handleListDirectory RPC handler within src/handlers/filesystem-handlers.ts. Users can override this by passing a depth parameter, but the system enforces the MAX_NESTED_ITEMS cap of 100 entries per folder regardless of depth specified.

How does DesktopCommander MCP prevent memory issues with massive directories?

The system implements a dual limiting strategy: vertical constraints via the configurable depth limit, and horizontal constraints via MAX_NESTED_ITEMS = 100. When listing node_modules or log directories containing thousands of files, the utility outputs only the first 100 items per subdirectory and appends a warning line, ensuring the response array remains bounded and serializable.

Why am seeing [WARNING] tags in my directory output?

[WARNING] tags indicate that a subdirectory contained more than 100 items and the output was truncated. This is not an error but a transparency mechanism. The message format [WARNING] <path>: <n> items hidden (showing first 100 of <total> total) allows you to identify folders requiring deeper inspection or alternative search strategies using the search manager.

What happens when the server encounters a permission-denied folder?

Rather than throwing an uncaught exception, the listDirectory function in src/tools/filesystem.ts catches EPERM, EACCES, ENOENT, and ETIMEDOUT errors. It inserts a [DENIED] line into the results array describing the restriction and continues recursing through accessible siblings. This ensures that missing Full Disk Access permissions or cloud-only files do not terminate the entire directory enumeration.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →