Skip to main content
Glama

grep

Search file contents using regular expressions to find specific patterns across codebases. Filter results by file type and retrieve paths sorted by modification time.

Instructions

Fast content search tool that works with any codebase size. Searches file contents using regular expressions. Supports full regex syntax (eg. "log.Error", "function\s+\w+", etc.). Filter files by pattern with the include parameter (eg. ".js", "*.{ts,tsx}"). Returns matching file paths sorted by modification time. Use this tool when you need to find files containing specific patterns. When you are doing an open ended search that may require multiple rounds of globbing and grepping, use the Agent tool instead.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
includeNoFile pattern to include in the search (e.g. "*.js", "*.{ts,tsx}")*
pathNoThe directory to search in. Defaults to the current working directory..
patternYesThe regular expression pattern to search for in file contents

Implementation Reference

  • Registration of filesystem tools including the Grep tool via ToolRegistry.register_tools. This is where the 'grep' tool is registered with the MCP server.
    def register_filesystem_tools( mcp_server: FastMCP, permission_manager: PermissionManager, ) -> list[BaseTool]: """Register all filesystem tools with the MCP server. Args: mcp_server: The FastMCP server instance permission_manager: Permission manager for access control Returns: List of registered tools """ tools = get_filesystem_tools(permission_manager) ToolRegistry.register_tools(mcp_server, tools) return tools
  • Instantiation of Grep tool instance in get_filesystem_tools, which is used for registration.
    def get_filesystem_tools(permission_manager: PermissionManager) -> list[BaseTool]: """Create instances of all filesystem tools. Args: permission_manager: Permission manager for access control Returns: List of filesystem tool instances """ return [ ReadTool(permission_manager), Write(permission_manager), Edit(permission_manager), MultiEdit(permission_manager), DirectoryTreeTool(permission_manager), Grep(permission_manager), ContentReplaceTool(permission_manager), GrepAstTool(permission_manager), ]
  • Import of the Grep class used for the 'grep' tool.
    from mcp_claude_code.tools.filesystem.grep import Grep
  • Calling register_filesystem_tools in register_all_tools, which registers the 'grep' tool among others.
    # Register all filesystem tools filesystem_tools = register_filesystem_tools(mcp_server, permission_manager) for tool in filesystem_tools: all_tools[tool.name] = tool
  • Handler implementation for grep_ast tool, which is a specialized grep-like tool for source code with AST context. May be related or the closest to 'grep'.
    async def call( self, ctx: MCPContext, **params: Unpack[GrepAstToolParams], ) -> str: """Execute the tool with the given parameters. Args: ctx: MCP context **params: Tool parameters Returns: Tool result """ tool_ctx = self.create_tool_context(ctx) self.set_tool_context_info(tool_ctx) # Extract parameters pattern: Pattern = params["pattern"] path: SearchPath = params["path"] ignore_case = params.get("ignore_case", False) line_number = params.get("line_number", False) # Validate the path path_validation = self.validate_path(path) if not path_validation.is_valid: await tool_ctx.error(f"Invalid path: {path_validation.error_message}") return f"Error: Invalid path: {path_validation.error_message}" # Check if path is allowed is_allowed, error_message = await self.check_path_allowed(path, tool_ctx) if not is_allowed: return error_message # Check if path exists is_exists, error_message = await self.check_path_exists(path, tool_ctx) if not is_exists: return error_message await tool_ctx.info(f"Searching for '{pattern}' in {path}") # Get the files to process path_obj = Path(path) files_to_process = [] if path_obj.is_file(): files_to_process.append(str(path_obj)) elif path_obj.is_dir(): for root, _, files in os.walk(path_obj): for file in files: file_path = Path(root) / file if self.is_path_allowed(str(file_path)): files_to_process.append(str(file_path)) if not files_to_process: await tool_ctx.warning(f"No source code files found in {path}") return f"No source code files found in {path}" # Process each file results = [] processed_count = 0 await tool_ctx.info(f"Found {len(files_to_process)} file(s) to process") for file_path in files_to_process: await tool_ctx.report_progress(processed_count, len(files_to_process)) try: # Read the file with open(file_path, "r", encoding="utf-8") as f: code = f.read() # Process the file with grep-ast try: tc = TreeContext( file_path, code, color=False, verbose=False, line_number=line_number, ) # Find matches loi = tc.grep(pattern, ignore_case) if loi: tc.add_lines_of_interest(loi) tc.add_context() output = tc.format() # Add the result to our list results.append(f"\n{file_path}:\n{output}\n") except Exception as e: # Skip files that can't be parsed by tree-sitter await tool_ctx.warning(f"Could not parse {file_path}: {str(e)}") except UnicodeDecodeError: await tool_ctx.warning(f"Could not read {file_path} as text") except Exception as e: await tool_ctx.error(f"Error processing {file_path}: {str(e)}") processed_count += 1 # Final progress report await tool_ctx.report_progress(len(files_to_process), len(files_to_process)) if not results: await tool_ctx.warning(f"No matches found for '{pattern}' in {path}") return f"No matches found for '{pattern}' in {path}" await tool_ctx.info(f"Found matches in {len(results)} file(s)") # Join the results return "\n".join(results) @override def register(self, mcp_server: FastMCP) -> None: """Register this tool with the MCP server. Creates a wrapper function with explicitly defined parameters that match the tool's parameter schema and registers it with the MCP server. Args: mcp_server: The FastMCP server instance """ tool_self = self # Create a reference to self for use in the closure @mcp_server.tool(name=self.name, description=self.description) async def grep_ast( ctx: MCPContext, pattern: Pattern, path: SearchPath, ignore_case: IgnoreCase, line_number: LineNumber, ) -> str: ctx = get_context() return await tool_self.call( ctx, pattern=pattern, path=path, ignore_case=ignore_case, line_number=line_number, )

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/SDGLBL/mcp-claude-code'

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