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}` };
      }
    }
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden of behavioral disclosure. It mentions 'search' but doesn't describe what gets returned (e.g., lines, matches, counts), error handling, performance implications, or any constraints like rate limits or permissions. For a tool with 9 parameters and no annotations, this is a significant gap in transparency.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, efficient sentence with zero waste. It's appropriately sized and front-loaded, clearly stating the core function without unnecessary elaboration, making it easy for an agent to parse quickly.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the complexity (9 parameters, no annotations, no output schema), the description is incomplete. It doesn't explain what the tool returns (e.g., search results format), behavioral traits, or how it differs from siblings. For a search tool with rich parameters, more context is needed to guide effective use.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents all parameters thoroughly. The description adds no additional meaning beyond the schema, such as explaining interactions between parameters (e.g., how 'whole_words' modifies 'pattern') or providing usage examples. Baseline 3 is appropriate when the schema does the heavy lifting.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose3/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description 'Search using a direct regex pattern' states the verb ('search') and resource ('regex pattern'), but it's vague about what exactly is being searched (files, text, etc.) and doesn't distinguish from sibling tools like 'grep_advanced' or 'grep_search_intent'. It provides a basic purpose but lacks specificity and differentiation.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance is provided on when to use this tool versus alternatives like 'grep_advanced' or 'grep_search_intent'. The description implies a direct regex search, but it doesn't specify contexts, prerequisites, or exclusions, leaving the agent with no usage direction beyond the tool name.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other 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