search_files
Search for content within files using text or regex patterns to locate specific information across your project directory.
Instructions
Search for content within files using regex or text matching
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | Search query (text or regex pattern) | |
| file_types | No | File extensions to search in | |
| is_regex | No | Whether the query is a regex pattern | |
| max_results | No | Maximum number of results to return |
Implementation Reference
- server.js:907-919 (handler)The main handler function for the 'search_files' tool. It parses the input arguments, delegates the search to the searchFiles helper method, and returns the results formatted as a JSON string in the MCP response format.async handleSearchFiles(args) { const { query, file_types, is_regex = false, max_results = 50 } = args; const results = await this.searchFiles(query, file_types, is_regex, max_results); return { content: [ { type: 'text', text: JSON.stringify(results, null, 2), }, ], }; }
- server.js:1009-1074 (helper)Supporting utility that performs the actual recursive file search in the working directory. Supports regex and text search, filters by file types, limits results, and collects line-level matches with context.async searchFiles(query, fileTypes, isRegex, maxResults) { const results = []; const searchPattern = isRegex ? new RegExp(query, 'gim') : query.toLowerCase(); async function searchInDirectory(dirPath) { try { const entries = await fs.readdir(dirPath, { withFileTypes: true }); for (const entry of entries) { if (results.length >= maxResults) break; const fullPath = path.join(dirPath, entry.name); if (entry.isDirectory() && !entry.name.startsWith('.')) { await searchInDirectory(fullPath); } else if (entry.isFile()) { const ext = path.extname(entry.name); if (!fileTypes || fileTypes.includes(ext)) { try { const content = await fs.readFile(fullPath, 'utf8'); const matches = []; if (isRegex) { let match; while ((match = searchPattern.exec(content)) !== null && matches.length < 10) { const lineNumber = content.substring(0, match.index).split('\n').length; const line = content.split('\n')[lineNumber - 1]; matches.push({ line: lineNumber, content: line.trim(), match: match[0], }); } } else { const lines = content.split('\n'); lines.forEach((line, index) => { if (line.toLowerCase().includes(searchPattern) && matches.length < 10) { matches.push({ line: index + 1, content: line.trim(), match: query, }); } }); } if (matches.length > 0) { results.push({ file: path.relative(this.workingDirectory, fullPath), matches, }); } } catch (error) { // Skip files that can't be read as text } } } } } catch (error) { // Skip directories that can't be read } } await searchInDirectory(this.workingDirectory); return results; }
- server.js:110-137 (schema)Input schema definition for the search_files tool, specifying parameters like query, file_types, is_regex, and max_results with types, descriptions, and defaults.name: 'search_files', description: 'Search for content within files using regex or text matching', inputSchema: { type: 'object', properties: { query: { type: 'string', description: 'Search query (text or regex pattern)', }, file_types: { type: 'array', description: 'File extensions to search in', items: { type: 'string' }, }, is_regex: { type: 'boolean', description: 'Whether the query is a regex pattern', default: false, }, max_results: { type: 'number', description: 'Maximum number of results to return', default: 50, }, }, required: ['query'], }, },
- server.js:463-464 (registration)Dispatch case in the central tool switch statement that routes 'search_files' calls to the handleSearchFiles method.case 'search_files': return await this.handleSearchFiles(args);