Skip to main content
Glama
247arjun

Grep MCP Server

by 247arjun

grep_regex

Search files and directories using regular expression patterns to find specific text content with customizable options like case sensitivity and context display.

Instructions

Search using a direct regex pattern

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
patternYesRegular expression pattern to search for
targetYesFile or directory path to search in
case_sensitiveNoWhether the search should be case sensitive
whole_wordsNoMatch whole words only
invert_matchNoShow lines that don't match the pattern
max_resultsNoMaximum number of results to return
show_contextNoShow surrounding lines for context
context_linesNoNumber of context lines to show before/after matches
file_extensionsNoOnly search files with these extensions (e.g., ['js', 'ts'])

Implementation Reference

  • The main execution handler for the 'grep_regex' tool. It constructs grep arguments based on input parameters like pattern, target path, case sensitivity, etc., validates the path, and calls the executeGrep helper.
    async ({ pattern, target, case_sensitive, whole_words, invert_match, max_results, show_context, context_lines, file_extensions }) => {
      // Validate target path
      const pathValidation = validatePath(target);
      if (!pathValidation.isValid) {
        return {
          content: [
            {
              type: "text",
              text: `Error: ${pathValidation.error}`,
            },
          ],
        };
      }
    
      const args = ['grep'];
      
      // 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 invert match option
      if (invert_match) {
        args.push('-v');
      }
      
      // Add recursive search if target is directory
      if (pathValidation.isDirectory) {
        args.push('-r');
      }
      
      // Add line numbers
      args.push('-n');
      
      // Add context if requested
      if (show_context && context_lines > 0) {
        args.push(`-C${context_lines}`);
      }
      
      // Add max results limit
      if (max_results) {
        args.push('-m', max_results.toString());
      }
      
      // Add file extension filters
      if (file_extensions && file_extensions.length > 0 && pathValidation.isDirectory) {
        file_extensions.forEach(ext => {
          args.push('--include', `*.${ext}`);
        });
      }
      
      // Add target path
      args.push(target);
      
      try {
        const result = await executeGrep(args);
        
        return {
          content: [
            {
              type: "text",
              text: `Pattern: ${pattern}\nExit Code: ${result.exitCode}\n\nResults:\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_regex tool, including pattern, target, and various grep options.
    {
      pattern: z.string().describe("Regular expression pattern to search for"),
      target: z.string().describe("File or 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"),
      invert_match: z.boolean().optional().default(false).describe("Show lines that don't match the pattern"),
      max_results: z.number().optional().describe("Maximum number of results to return"),
      show_context: z.boolean().optional().default(false).describe("Show surrounding lines for context"),
      context_lines: z.number().optional().default(2).describe("Number of context lines to show before/after matches"),
      file_extensions: z.array(z.string()).optional().describe("Only search files with these extensions (e.g., ['js', 'ts'])"),
    },
  • src/index.ts:237-336 (registration)
    The server.tool() call that registers the 'grep_regex' tool with its name, description, schema, and handler function.
    server.tool(
      "grep_regex",
      "Search using a direct regex pattern",
      {
        pattern: z.string().describe("Regular expression pattern to search for"),
        target: z.string().describe("File or 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"),
        invert_match: z.boolean().optional().default(false).describe("Show lines that don't match the pattern"),
        max_results: z.number().optional().describe("Maximum number of results to return"),
        show_context: z.boolean().optional().default(false).describe("Show surrounding lines for context"),
        context_lines: z.number().optional().default(2).describe("Number of context lines to show before/after matches"),
        file_extensions: z.array(z.string()).optional().describe("Only search files with these extensions (e.g., ['js', 'ts'])"),
      },
      async ({ pattern, target, case_sensitive, whole_words, invert_match, max_results, show_context, context_lines, file_extensions }) => {
        // Validate target path
        const pathValidation = validatePath(target);
        if (!pathValidation.isValid) {
          return {
            content: [
              {
                type: "text",
                text: `Error: ${pathValidation.error}`,
              },
            ],
          };
        }
    
        const args = ['grep'];
        
        // 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 invert match option
        if (invert_match) {
          args.push('-v');
        }
        
        // Add recursive search if target is directory
        if (pathValidation.isDirectory) {
          args.push('-r');
        }
        
        // Add line numbers
        args.push('-n');
        
        // Add context if requested
        if (show_context && context_lines > 0) {
          args.push(`-C${context_lines}`);
        }
        
        // Add max results limit
        if (max_results) {
          args.push('-m', max_results.toString());
        }
        
        // Add file extension filters
        if (file_extensions && file_extensions.length > 0 && pathValidation.isDirectory) {
          file_extensions.forEach(ext => {
            args.push('--include', `*.${ext}`);
          });
        }
        
        // Add target path
        args.push(target);
        
        try {
          const result = await executeGrep(args);
          
          return {
            content: [
              {
                type: "text",
                text: `Pattern: ${pattern}\nExit Code: ${result.exitCode}\n\nResults:\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 to safely execute the grep command via child_process.spawn, collecting 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 the target path exists and whether it is a directory, used before executing grep.
    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}` };
      }
    }

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