How DesktopCommanderMCP Prevents Context Overflow in Recursive Directory Listings

DesktopCommanderMCP prevents context overflow by enforcing a default recursion depth of 2, capping nested directory entries at 100 items per folder, and injecting explicit truncation warnings into the output stream.

When working with large file systems, unbounded recursive listings can quickly exhaust an AI model's context window. The wonderwhy-er/DesktopCommanderMCP repository implements a hardened listDirectory routine in src/tools/filesystem.ts that balances comprehensive directory exploration with strict token budget protection.

Depth-Limited Recursion

The primary defense against context overflow is a configurable depth parameter. The listDirectory function accepts a depth argument that defaults to 2, meaning it traverses the target directory plus one sub-level.

In src/tools/filesystem.ts at line 720, the recursive helper checks the current depth before proceeding:

if (currentDepth <= 0) return;

This hard stop prevents the function from descending infinitely into deeply nested folder structures. The UI layer in src/ui/file-preview/src/directory-controller.ts (line 241) invokes the tool with this conservative default, while the HTTP API documented in src/server.ts (line 581) exposes the depth query parameter for power users who explicitly need deeper traversal.

Hard Cap on Nested Items (MAX_NESTED_ITEMS)

Even with limited depth, individual directories might contain thousands of files. To prevent a single massive folder from flooding the context, the code enforces a hard limit of 100 entries for any non-top-level directory.

The constant is defined at line 724 of src/tools/filesystem.ts:

const MAX_NESTED_ITEMS = 100;

When enumerating children of a nested folder, the implementation never returns more than this maximum, regardless of how many files actually exist in that subdirectory.

Selective Slicing with Hidden Item Counts

Rather than silently dropping entries, the listDirectory implementation slices the entry array and calculates exactly how many items were suppressed. At lines 751–755 of src/tools/filesystem.ts, the code performs:

const entriesToShow = entries.slice(0, MAX_NESTED_ITEMS);
const filteredCount = totalEntries - MAX_NESTED_ITEMS;

This approach preserves the first 100 items (typically the earliest alphabetically or by creation time, depending on the OS) while maintaining an accurate count of omitted files. The function tracks filteredCount separately for each truncated directory, ensuring the AI agent understands the true scale of the file system even when viewing a limited subset.

User-Visible Truncation Warnings

Transparency is critical when data is elided. After processing a directory that exceeds the item cap, the system appends a warning line to the results array at lines 777–781:

results.push(`[WARNING] ${displayPath}: ${filteredCount} items hidden ...`);

These inline warnings signal to both the user interface and the consuming AI that the view is incomplete. This prevents hallucinations or incorrect assumptions about directory contents while keeping the total output size predictable.

Standardized Error Handling

The implementation normalizes error responses to prevent exception stack traces or variable-length error messages from destabilizing context budgets. When encountering permission denials or missing directories, src/tools/filesystem.ts (lines 333–442) returns fixed-format strings:

if (err.code === 'ENOENT') return `[NOT_FOUND] ${path}`;
else if (err.code === 'EPERM') return `[DENIED] ${path}`;

These compact, consistent tokens replace verbose error objects, ensuring that even directories with hundreds of inaccessible entries contribute only minimal, fixed-size strings to the context.

Practical Implementation Examples

Basic Usage with Default Protection

import { listDirectory } from "./tools/filesystem.js";

// Default depth = 2, nested items capped at 100
const result = await listDirectory("/Users/me/Documents");
console.log(result.join("\n"));

// Output:
// [DIR] Projects
// [FILE] notes.txt
// [DIR] Projects/MyApp
// [FILE] Projects/MyApp/main.ts
// [WARNING] Projects/MyApp: 452 items hidden (showing first 100 of 552 total)

Increasing Recursion Depth

// Request deeper traversal (monitor token usage carefully)
const deepResult = await listDirectory("/var/log", 4);

Programmatic Warning Detection

for (const line of deepResult) {
  if (line.startsWith("[WARNING]")) {
    console.warn("Context truncation occurred:", line);
    // Implement pagination or targeted sub-queries here
  }
}

Summary

  • Depth limiting: Default recursion stops at level 2, configurable via the depth parameter in src/tools/filesystem.ts.
  • Item capping: The MAX_NESTED_ITEMS constant (100) restricts each nested folder to a manageable subset.
  • Transparent truncation: The system reports exactly how many files were hidden via [WARNING] prefixes.
  • Error normalization: Permission and existence errors return fixed-format tokens rather than variable-length messages.
  • Token safety: These mechanisms work together to keep directory listings within AI context limits even when scanning file systems containing thousands of nested files.

Frequently Asked Questions

What is the default recursion depth in DesktopCommanderMCP?

The default recursion depth is 2 levels, implemented in src/ui/file-preview/src/directory-controller.ts. This means the tool lists the target directory and its immediate subdirectories, but does not descend into sub-subdirectories unless explicitly requested via the depth parameter.

How does DesktopCommanderMCP handle permission errors during listing?

Permission errors (EPERM) and missing directory errors (ENOENT) are caught and converted to standardized short strings like [DENIED] /path or [NOT_FOUND] /path in src/tools/filesystem.ts. This prevents large error objects from consuming context budget while clearly signaling access issues to the AI agent.

Can I view all files in a directory that contains more than 100 items?

No, the hard cap of 100 nested items is currently enforced in src/tools/filesystem.ts via the MAX_NESTED_ITEMS constant. To access files beyond the first 100, you must execute additional targeted listDirectory calls on specific subdirectories rather than relying on recursive enumeration of the parent.

Where is the context overflow protection logic implemented?

All protection mechanisms reside in src/tools/filesystem.ts, specifically within the listDirectory function starting at line 720. The depth checking, item slicing, and warning generation are co-located in this single file to ensure consistent behavior across the DesktopCommanderMCP server and UI components.

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 →