Skip to main content
Glama
wonderwhy-er

Claude Desktop Commander MCP

search_files

Locate files by name using case-insensitive substring matching across subdirectories. Specify absolute paths for reliable results, with a customizable 30-second timeout. Designed for secure and efficient file searching.

Instructions

                    Finds files by name using a case-insensitive substring matching.
                    
                    Use this instead of 'execute_command' with find/dir/ls for locating files.
                    Searches through all subdirectories from the starting path.
                    
                    Has a default timeout of 30 seconds which can be customized using the timeoutMs parameter.
                    Only searches 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
NameRequiredDescriptionDefault
pathYes
patternYes
timeoutMsNo

Implementation Reference

  • Main implementation of searchFiles function, which performs file search using ripgrep via searchManager with polling for synchronous results, falls back to pure Node.js recursive search.
    export async function searchFiles(rootPath: string, pattern: string): Promise<string[]> {
        // Use the new search manager for better performance
        // This provides a temporary compatibility layer until we fully migrate to search sessions
        const { searchManager } = await import('../search-manager.js');
    
        try {
            const result = await searchManager.startSearch({
                rootPath,
                pattern,
                searchType: 'files',
                ignoreCase: true,
                maxResults: 5000, // Higher limit for compatibility
                earlyTermination: true, // Use early termination for better performance
            });
    
            const sessionId = result.sessionId;
    
            // Poll for results until complete
            let allResults: string[] = [];
            let isComplete = result.isComplete;
            let startTime = Date.now();
    
            // Add initial results
            for (const searchResult of result.results) {
                if (searchResult.type === 'file') {
                    allResults.push(searchResult.file);
                }
            }
    
            while (!isComplete) {
                await new Promise(resolve => setTimeout(resolve, 100)); // Wait 100ms
    
                const results = searchManager.readSearchResults(sessionId);
                isComplete = results.isComplete;
    
                // Add new file paths to results
                for (const searchResult of results.results) {
                    if (searchResult.file !== '__LAST_READ_MARKER__' && searchResult.type === 'file') {
                        allResults.push(searchResult.file);
                    }
                }
    
                // Safety check to prevent infinite loops (30 second timeout)
                if (Date.now() - startTime > 30000) {
                    searchManager.terminateSearch(sessionId);
                    break;
                }
            }
    
            // Log only the count of found files, not their paths
            capture('server_search_files_complete', {
                resultsCount: allResults.length,
                patternLength: pattern.length,
                usedRipgrep: true
            });
    
            return allResults;
        } catch (error) {
            // Fallback to original Node.js implementation if ripgrep fails
            capture('server_search_files_ripgrep_fallback', {
                error: error instanceof Error ? error.message : 'Unknown error'
            });
    
            return await searchFilesNodeJS(rootPath, pattern);
        }
    }
  • Fallback Node.js implementation for searchFiles when ripgrep/searchManager fails. Recursively searches directories for files matching pattern in name.
    async function searchFilesNodeJS(rootPath: string, pattern: string): Promise<string[]> {
        const results: string[] = [];
    
        async function search(currentPath: string): Promise<void> {
            let entries;
            try {
                entries = await fs.readdir(currentPath, { withFileTypes: true });
            } catch (error) {
                return; // Skip this directory on error
            }
    
            for (const entry of entries) {
                const fullPath = path.join(currentPath, entry.name);
    
                try {
                    await validatePath(fullPath);
    
                    if (entry.name.toLowerCase().includes(pattern.toLowerCase())) {
                        results.push(fullPath);
                    }
    
                    if (entry.isDirectory()) {
                        await search(fullPath);
                    }
                } catch (error) {
                    continue;
                }
            }
        }
    
        try {
            // Validate root path before starting search
            const validPath = await validatePath(rootPath);
            await search(validPath);
    
            // Log only the count of found files, not their paths
            capture('server_search_files_complete', {
                resultsCount: results.length,
                patternLength: pattern.length,
                usedRipgrep: false
            });
    
            return results;
        } catch (error) {
            // For telemetry only - sanitize error info
            capture('server_search_files_error', {
                errorType: error instanceof Error ? error.name : 'Unknown',
                error: 'Error with root path',
                isRootPathError: true
            });
    
            // Re-throw the original error for the caller
            throw error;
        }
    }

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/wonderwhy-er/DesktopCommanderMCP'

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