Skip to main content
Glama
mcollina

MCP Ripgrep Server

by mcollina

advanced-search

Search files using regex or literal patterns with customizable filters, context display, and output formatting options.

Instructions

Advanced search with ripgrep with more options

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
patternYesThe search pattern (regex by default)
pathYesDirectory or file(s) to search.
caseSensitiveNoUse case sensitive search (default: auto)
fixedStringsNoTreat pattern as a literal string, not a regex
filePatternNoFilter by file type or glob
fileTypeNoFilter by file type (e.g., js, py)
maxResultsNoLimit the number of matching lines
contextNoShow N lines before and after each match
invertMatchNoShow lines that don't match the pattern
wordMatchNoOnly show matches surrounded by word boundaries
includeHiddenNoSearch in hidden files and directories
followSymlinksNoFollow symbolic links
showFilenamesOnlyNoOnly show filenames of matches, not content
showLineNumbersNoShow line numbers
useColorsNoUse colors in output (default: false)

Implementation Reference

  • Handler for 'advanced-search' tool: extracts parameters, constructs ripgrep command with advanced flags, executes it, and returns formatted output.
    case "advanced-search": {
      const pattern = String(args.pattern || "");
      const path = String(args.path);
      const caseSensitive = typeof args.caseSensitive === 'boolean' ? args.caseSensitive : undefined;
      const fixedStrings = typeof args.fixedStrings === 'boolean' ? args.fixedStrings : undefined;
      const filePattern = args.filePattern ? String(args.filePattern) : undefined;
      const fileType = args.fileType ? String(args.fileType) : undefined;
      const maxResults = typeof args.maxResults === 'number' ? args.maxResults : undefined;
      const context = typeof args.context === 'number' ? args.context : undefined;
      const invertMatch = typeof args.invertMatch === 'boolean' ? args.invertMatch : undefined;
      const wordMatch = typeof args.wordMatch === 'boolean' ? args.wordMatch : undefined;
      const includeHidden = typeof args.includeHidden === 'boolean' ? args.includeHidden : undefined;
      const followSymlinks = typeof args.followSymlinks === 'boolean' ? args.followSymlinks : undefined;
      const showFilenamesOnly = typeof args.showFilenamesOnly === 'boolean' ? args.showFilenamesOnly : undefined;
      const showLineNumbers = typeof args.showLineNumbers === 'boolean' ? args.showLineNumbers : undefined;
      const useColors = typeof args.useColors === 'boolean' ? args.useColors : false;
      
      if (!pattern) {
        return {
          isError: true,
          content: [{ type: "text", text: "Error: Pattern is required" }]
        };
      }
      
      // Build the rg command with flags
      let command = "rg";
      
      // Add case sensitivity flag if specified
      if (caseSensitive === true) {
        command += " -s"; // Case sensitive
      } else if (caseSensitive === false) {
        command += " -i"; // Case insensitive
      }
      
      // Add fixed strings flag if specified
      if (fixedStrings === true) {
        command += " -F"; // Fixed strings
      }
      
      // Add file pattern if specified
      if (filePattern) {
        command += ` -g ${escapeShellArg(filePattern)}`;
      }
      
      // Add file type if specified
      if (fileType) {
        command += ` -t ${fileType}`;
      }
      
      // Add max results if specified
      if (maxResults !== undefined && maxResults > 0) {
        command += ` -m ${maxResults}`;
      }
      
      // Add context lines if specified
      if (context !== undefined && context > 0) {
        command += ` -C ${context}`;
      }
      
      // Add invert match if specified
      if (invertMatch === true) {
        command += " -v";
      }
      
      // Add word match if specified
      if (wordMatch === true) {
        command += " -w";
      }
      
      // Add hidden files flag if specified
      if (includeHidden === true) {
        command += " -."
      }
      
      // Add follow symlinks flag if specified
      if (followSymlinks === true) {
        command += " -L";
      }
      
      // Add filenames only flag if specified
      if (showFilenamesOnly === true) {
        command += " -l";
      }
      
      // Add line numbers flag if specified
      if (showLineNumbers === true) {
        command += " -n";
      } else if (showLineNumbers === false) {
        command += " -N";
      } else {
        // Default to showing line numbers
        command += " -n";
      }
      
      // Add color setting
      command += useColors ? " --color always" : " --color never";
      
      // Add pattern and path
      command += ` ${escapeShellArg(pattern)} ${escapeShellArg(path)}`;
      
      console.error(`Executing: ${command}`);
      const { stdout, stderr } = await exec(command);
      
      // If there's anything in stderr, log it for debugging
      if (stderr) {
        console.error(`ripgrep stderr: ${stderr}`);
      }
      
      return {
        content: [
          {
            type: "text",
            text: processOutput(stdout, useColors) || "No matches found"
          }
        ]
      };
    }
  • Schema definition for 'advanced-search' tool, listing all input parameters and their descriptions.
    {
      name: "advanced-search",
      description: "Advanced search with ripgrep with more options",
      inputSchema: {
        type: "object",
        properties: {
          pattern: { type: "string", description: "The search pattern (regex by default)" },
          path: { type: "string", description: "Directory or file(s) to search." },
          caseSensitive: { type: "boolean", description: "Use case sensitive search (default: auto)" },
          fixedStrings: { type: "boolean", description: "Treat pattern as a literal string, not a regex" },
          filePattern: { type: "string", description: "Filter by file type or glob" },
          fileType: { type: "string", description: "Filter by file type (e.g., js, py)" },
          maxResults: { type: "number", description: "Limit the number of matching lines" },
          context: { type: "number", description: "Show N lines before and after each match" },
          invertMatch: { type: "boolean", description: "Show lines that don't match the pattern" },
          wordMatch: { type: "boolean", description: "Only show matches surrounded by word boundaries" },
          includeHidden: { type: "boolean", description: "Search in hidden files and directories" },
          followSymlinks: { type: "boolean", description: "Follow symbolic links" },
          showFilenamesOnly: { type: "boolean", description: "Only show filenames of matches, not content" },
          showLineNumbers: { type: "boolean", description: "Show line numbers" },
          useColors: { type: "boolean", description: "Use colors in output (default: false)" }
        },
        required: ["pattern", "path"]
      }
    },
  • src/index.ts:94-179 (registration)
    Registration of all tools including 'advanced-search' in the ListToolsRequestSchema handler.
    server.setRequestHandler(ListToolsRequestSchema, async () => {
      return {
        tools: [
          {
            name: "search",
            description: "Search files for patterns using ripgrep (rg)",
            inputSchema: {
              type: "object",
              properties: {
                pattern: { type: "string", description: "The search pattern (regex by default)" },
                path: { type: "string", description: "Directory or file(s) to search." },
                caseSensitive: { type: "boolean", description: "Use case sensitive search (default: auto)" },
                filePattern: { type: "string", description: "Filter by file type or glob" },
                maxResults: { type: "number", description: "Limit the number of matching lines" },
                context: { type: "number", description: "Show N lines before and after each match" },
                useColors: { type: "boolean", description: "Use colors in output (default: false)" }
              },
              required: ["pattern", "path"]
            }
          },
          {
            name: "advanced-search",
            description: "Advanced search with ripgrep with more options",
            inputSchema: {
              type: "object",
              properties: {
                pattern: { type: "string", description: "The search pattern (regex by default)" },
                path: { type: "string", description: "Directory or file(s) to search." },
                caseSensitive: { type: "boolean", description: "Use case sensitive search (default: auto)" },
                fixedStrings: { type: "boolean", description: "Treat pattern as a literal string, not a regex" },
                filePattern: { type: "string", description: "Filter by file type or glob" },
                fileType: { type: "string", description: "Filter by file type (e.g., js, py)" },
                maxResults: { type: "number", description: "Limit the number of matching lines" },
                context: { type: "number", description: "Show N lines before and after each match" },
                invertMatch: { type: "boolean", description: "Show lines that don't match the pattern" },
                wordMatch: { type: "boolean", description: "Only show matches surrounded by word boundaries" },
                includeHidden: { type: "boolean", description: "Search in hidden files and directories" },
                followSymlinks: { type: "boolean", description: "Follow symbolic links" },
                showFilenamesOnly: { type: "boolean", description: "Only show filenames of matches, not content" },
                showLineNumbers: { type: "boolean", description: "Show line numbers" },
                useColors: { type: "boolean", description: "Use colors in output (default: false)" }
              },
              required: ["pattern", "path"]
            }
          },
          {
            name: "count-matches",
            description: "Count matches in files using ripgrep",
            inputSchema: {
              type: "object",
              properties: {
                pattern: { type: "string", description: "The search pattern (regex by default)" },
                path: { type: "string", description: "Directory or file(s) to search." },
                caseSensitive: { type: "boolean", description: "Use case sensitive search (default: auto)" },
                filePattern: { type: "string", description: "Filter by file type or glob" },
                countLines: { type: "boolean", description: "Count matching lines instead of total matches" },
                useColors: { type: "boolean", description: "Use colors in output (default: false)" }
              },
              required: ["pattern", "path"]
            }
          },
          {
            name: "list-files",
            description: "List files that would be searched by ripgrep without actually searching them",
            inputSchema: {
              type: "object",
              properties: {
                path: { type: "string", description: "Directory or file(s) to search." },
                filePattern: { type: "string", description: "Filter by file type or glob" },
                fileType: { type: "string", description: "Filter by file type (e.g., js, py)" },
                includeHidden: { type: "boolean", description: "Include hidden files and directories" }
              },
              required: ["path"]
            }
          },
          {
            name: "list-file-types",
            description: "List all supported file types in ripgrep",
            inputSchema: {
              type: "object",
              properties: {}
            }
          }
        ]
      };
    });

Schema Changelog

Changes observed during successful MCP inspections.

  1. First observed

TDQS

C2.9/5.0
Behavior2/5

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

With no annotations, the description carries the full burden for behavioral disclosure. It mentions ripgrep but does not reveal important traits like performance impact, default behaviors (e.g., case sensitivity auto), or side effects. This is insufficient for a tool with many configuration options.

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

Conciseness4/5

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

The description is a single concise sentence, front-loading the tool's purpose (advanced search with ripgrep). It is not overly verbose, but could be slightly expanded to include key differentiators without losing conciseness.

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 of 15 parameters and no output schema or annotations, the description is too sparse. It fails to explain the tool's advanced features, return format, or typical usage scenarios, leaving the agent to infer from parameter names alone.

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?

All 15 parameters are described in the schema, achieving 100% coverage. The description adds no additional meaning or context beyond the parameter names and types, meeting the baseline for high schema coverage.

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

Purpose4/5

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

The description states it's an advanced search using ripgrep with more options, clearly indicating the tool's function. However, it does not explicitly differentiate from sibling 'search' beyond implying more features, leaving some ambiguity.

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 usage guidance is provided. The description does not indicate when to use this tool over its siblings (count-matches, list-files, list-file-types, search), nor does it mention any prerequisites or restrictions.

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