grep_files_with_matches
Search files in a directory for specific text patterns using regex or plain text, then list only the filenames containing matches. Filter by file extensions, case sensitivity, whole words, or exclude patterns.
Instructions
List only the names of files that contain the pattern
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| pattern | Yes | Regular expression pattern or plain text to search for | |
| target | Yes | Directory path to search in | |
| case_sensitive | No | Whether the search should be case sensitive | |
| whole_words | No | Match whole words only | |
| file_extensions | No | Only search files with these extensions | |
| exclude_patterns | No | Exclude files matching these patterns |
Implementation Reference
- src/index.ts:439-524 (handler)Handler function that validates input, builds grep command with -l -r -E options for listing files recursively containing the regex pattern, executes it via executeGrep, and returns results.async ({ pattern, target, case_sensitive, whole_words, file_extensions, exclude_patterns }) => { // Validate target path const pathValidation = validatePath(target); if (!pathValidation.isValid) { return { content: [ { type: "text", text: `Error: ${pathValidation.error}`, }, ], }; } if (!pathValidation.isDirectory) { return { content: [ { type: "text", text: `Error: Target must be a directory for this operation`, }, ], }; } const args = ['grep']; // List filenames only args.push('-l'); // Use extended regex args.push('-E'); args.push(pattern); // Add case sensitivity option if (!case_sensitive) { args.push('-i'); } // Add whole words option if (whole_words) { args.push('-w'); } // Add recursive search args.push('-r'); // Add file extension filters if (file_extensions && file_extensions.length > 0) { file_extensions.forEach(ext => { args.push('--include', `*.${ext}`); }); } // Add exclusion patterns if (exclude_patterns && exclude_patterns.length > 0) { exclude_patterns.forEach(excludePattern => { args.push('--exclude', excludePattern); }); } // Add target path args.push(target); try { const result = await executeGrep(args); return { content: [ { type: "text", text: `Pattern: ${pattern}\nExit Code: ${result.exitCode}\n\nFiles containing matches:\n${result.stdout}${result.stderr ? `\n\nErrors:\n${result.stderr}` : ''}`, }, ], }; } catch (error) { return { content: [ { type: "text", text: `Error executing grep: ${error instanceof Error ? error.message : String(error)}`, }, ], }; } }
- src/index.ts:431-438 (schema)Zod input schema defining parameters for the grep_files_with_matches tool.{ pattern: z.string().describe("Regular expression pattern or plain text to search for"), target: z.string().describe("Directory path to search in"), case_sensitive: z.boolean().optional().default(false).describe("Whether the search should be case sensitive"), whole_words: z.boolean().optional().default(false).describe("Match whole words only"), file_extensions: z.array(z.string()).optional().describe("Only search files with these extensions"), exclude_patterns: z.array(z.string()).optional().describe("Exclude files matching these patterns"), },
- src/index.ts:428-525 (registration)Registers the grep_files_with_matches tool on the MCP server with name, description, schema, and handler.server.tool( "grep_files_with_matches", "List only the names of files that contain the pattern", { pattern: z.string().describe("Regular expression pattern or plain text to search for"), target: z.string().describe("Directory path to search in"), case_sensitive: z.boolean().optional().default(false).describe("Whether the search should be case sensitive"), whole_words: z.boolean().optional().default(false).describe("Match whole words only"), file_extensions: z.array(z.string()).optional().describe("Only search files with these extensions"), exclude_patterns: z.array(z.string()).optional().describe("Exclude files matching these patterns"), }, async ({ pattern, target, case_sensitive, whole_words, file_extensions, exclude_patterns }) => { // Validate target path const pathValidation = validatePath(target); if (!pathValidation.isValid) { return { content: [ { type: "text", text: `Error: ${pathValidation.error}`, }, ], }; } if (!pathValidation.isDirectory) { return { content: [ { type: "text", text: `Error: Target must be a directory for this operation`, }, ], }; } const args = ['grep']; // List filenames only args.push('-l'); // Use extended regex args.push('-E'); args.push(pattern); // Add case sensitivity option if (!case_sensitive) { args.push('-i'); } // Add whole words option if (whole_words) { args.push('-w'); } // Add recursive search args.push('-r'); // Add file extension filters if (file_extensions && file_extensions.length > 0) { file_extensions.forEach(ext => { args.push('--include', `*.${ext}`); }); } // Add exclusion patterns if (exclude_patterns && exclude_patterns.length > 0) { exclude_patterns.forEach(excludePattern => { args.push('--exclude', excludePattern); }); } // Add target path args.push(target); try { const result = await executeGrep(args); return { content: [ { type: "text", text: `Pattern: ${pattern}\nExit Code: ${result.exitCode}\n\nFiles containing matches:\n${result.stdout}${result.stderr ? `\n\nErrors:\n${result.stderr}` : ''}`, }, ], }; } catch (error) { return { content: [ { type: "text", text: `Error executing grep: ${error instanceof Error ? error.message : String(error)}`, }, ], }; } } );
- src/index.ts:21-60 (helper)Helper function to safely spawn and execute the grep process, capturing stdout, stderr, and exit code.async function executeGrep(args: string[]): Promise<{ stdout: string; stderr: string; exitCode: number }> { return new Promise((resolve) => { // Ensure we're only calling grep with safe arguments if (!args.includes('grep')) { args.unshift('grep'); } const child = spawn('grep', args.slice(1), { stdio: ['pipe', 'pipe', 'pipe'], shell: false, }); let stdout = ''; let stderr = ''; child.stdout.on('data', (data) => { stdout += data.toString(); }); child.stderr.on('data', (data) => { stderr += data.toString(); }); child.on('close', (code) => { resolve({ stdout, stderr, exitCode: code || 0, }); }); child.on('error', (error) => { resolve({ stdout: '', stderr: error.message, exitCode: 1, }); }); }); }
- src/index.ts:63-74 (helper)Helper function to validate if a path exists and whether it is a directory using fs functions.function validatePath(path: string): { isValid: boolean; isDirectory: boolean; error?: string } { try { const resolvedPath = resolve(path); if (!existsSync(resolvedPath)) { return { isValid: false, isDirectory: false, error: `Path does not exist: ${path}` }; } const stats = statSync(resolvedPath); return { isValid: true, isDirectory: stats.isDirectory() }; } catch (error) { return { isValid: false, isDirectory: false, error: `Invalid path: ${path}` }; } }