search_files
Recursively locate files and directories using a case-insensitive pattern match from a specified path. Control search depth and result limits to efficiently find matching items, even when exact locations are unknown. Ideal for quick file discovery within permitted directories.
Instructions
Recursively search for files and directories matching a pattern. Searches through all subdirectories from the starting path. The search is case-insensitive and matches partial names. Returns full paths to all matching items. Requires maxDepth (default 2) and maxResults (default 10) parameters. Great for finding files when you don't know their exact location. Only searches within allowed directories.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| excludePatterns | No | ||
| maxDepth | Yes | Maximum directory depth to search. Must be a positive integer. Handler default: 2. | |
| maxResults | Yes | Maximum number of results to return. Must be a positive integer. Handler default: 10. | |
| path | Yes | ||
| pattern | Yes |
Implementation Reference
- src/handlers/utility-handlers.ts:53-66 (handler)The main handler function for the 'search_files' tool. It parses arguments using the schema, validates the path, calls the searchFiles helper, and formats the response.export async function handleSearchFiles( args: unknown, allowedDirectories: string[], symlinksMap: Map<string, string>, noFollowSymlinks: boolean ) { const parsed = parseArgs(SearchFilesArgsSchema, args, 'search_files'); const { path: startPath, pattern, excludePatterns, maxDepth, maxResults } = parsed; const validPath = await validatePath(startPath, allowedDirectories, symlinksMap, noFollowSymlinks); const results = await searchFiles(validPath, pattern, excludePatterns, maxDepth, maxResults); return { content: [{ type: "text", text: results.length > 0 ? results.join("\n") : "No matches found" }], }; }
- TypeBox schema definition for SearchFilesArgs, defining input parameters: path, pattern, excludePatterns, maxDepth, maxResults.export const SearchFilesArgsSchema = Type.Object({ path: Type.String(), pattern: Type.String(), excludePatterns: Type.Optional( Type.Array(Type.String(), { default: [] }) ), maxDepth: Type.Integer({ minimum: 1, description: 'Maximum directory depth to search. Must be a positive integer. Handler default: 2.' }), maxResults: Type.Integer({ minimum: 1, description: 'Maximum number of results to return. Must be a positive integer. Handler default: 10.' }) }); export type SearchFilesArgs = Static<typeof SearchFilesArgsSchema>;
- src/utils/file-utils.ts:34-90 (helper)Core helper function that performs the recursive file search based on pattern, respecting depth, results limit, and exclusions using minimatch.export async function searchFiles( rootPath: string, pattern: string, excludePatterns: string[] = [], maxDepth: number = 2, // Default depth maxResults: number = 10 // Default results ): Promise<ReadonlyArray<string>> { const results: string[] = []; async function search(currentPath: string, currentDepth: number) { // Stop if max depth is reached if (currentDepth >= maxDepth) { return; } // Stop if max results are reached if (results.length >= maxResults) { return; } const entries = await fsPromises.readdir(currentPath, { withFileTypes: true }); for (const entry of entries) { const fullPath = path.join(currentPath, entry.name); // Check if path matches any exclude pattern const relativePath = path.relative(rootPath, fullPath); const shouldExclude = excludePatterns.some(pattern => { const globPattern = pattern.includes('*') ? pattern : `**/${pattern}/**`; return minimatch(relativePath, globPattern, { dot: true }); }); if (shouldExclude) { continue; } if (entry.name.toLowerCase().includes(pattern.toLowerCase())) { if (results.length < maxResults) { results.push(fullPath); } // Check again if max results reached after adding if (results.length >= maxResults) { return; // Stop searching this branch } } if (entry.isDirectory()) { // Check results length before recursing if (results.length < maxResults) { await search(fullPath, currentDepth + 1); } } } } await search(rootPath, 0); // Start search at depth 0 return results; }
- index.ts:236-237 (registration)Registration of the 'search_files' tool handler in the toolHandlers object, which is used to add the tool to the MCP server.search_files: (a: unknown) => handleSearchFiles(a, allowedDirectories, symlinksMap, noFollowSymlinks),
- index.ts:309-309 (registration)Tool metadata registration in the allTools array, including name and description, used conditionally in server.addTool calls.{ name: "search_files", description: "Search files by name" },