search_files
Search for content within files using text or regex patterns. Specify file types and limit results to efficiently locate relevant information across directories.
Instructions
Search for content within files using regex or text matching
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| 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 | |
| query | Yes | Search query (text or regex pattern) |
Implementation Reference
- server.js:907-919 (handler)Handler function that extracts parameters from tool call arguments, delegates to searchFiles helper method, and returns search results as JSON-formatted text content.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:109-137 (schema)Tool registration entry defining the name, description, and input schema (JSON Schema) for validation of search_files tool parameters.{ 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)Tool dispatcher case statement that maps the 'search_files' tool name to its handler method during tool execution.case 'search_files': return await this.handleSearchFiles(args);
- server.js:1009-1074 (helper)Core helper function implementing recursive directory traversal, file filtering by extension, content reading, regex/text matching, and collection of match results with line numbers.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; }