Skip to main content
Glama
247arjun

Grep MCP Server

by 247arjun

grep_files_with_matches

Search and list files containing a specific pattern in a target directory. Supports regex, case sensitivity, whole word matching, file extensions, and exclusion patterns for precise results.

Instructions

List only the names of files that contain the pattern

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
case_sensitiveNoWhether the search should be case sensitive
exclude_patternsNoExclude files matching these patterns
file_extensionsNoOnly search files with these extensions
patternYesRegular expression pattern or plain text to search for
targetYesDirectory path to search in
whole_wordsNoMatch whole words only

Implementation Reference

  • The main handler function for the 'grep_files_with_matches' tool. It validates the input directory, builds grep command arguments using '-l' to list only filenames with matches, '-r' for recursive search, and other options, then executes it using the executeGrep helper and formats the response.
    // 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)}`, }, ], }; } }
  • Zod schema defining the input 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"), }, async ({ pattern, target, case_sensitive, whole_words, file_extensions, exclude_patterns }) => {
  • src/index.ts:429-525 (registration)
    The server.tool call that registers the 'grep_files_with_matches' tool with MCP server, including name, description, schema, and handler.
    "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)}`, }, ], }; } } );
  • Helper function used by all grep tools 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, }); }); }); }
  • Helper function to validate if a path exists and whether it is a directory, used in the handler.
    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}` }; } }

Other Tools

Related Tools

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/247arjun/mcp-grep'

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