find_files_by_chunk_content
Find files in a project that contain chunks with specified text. Returns a file tree showing which files have matches.
Instructions
Step 1: Find files containing chunks with matching text.
Returns file tree only showing which files contain matches.
You must use find_matching_chunks_in_file on each relevant file
to see the actual matches.
Example workflow:
1. Find files:
files = find_files_by_chunk_content(project, ["MyClass"])
2. For each file, find actual matches:
matches = find_matching_chunks_in_file(file, ["MyClass"])
3. Get content:
content = chunk_details(file, match_id)Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| project_name | Yes | ||
| chunk_contents_filter | Yes | Match if any of these strings appear. Match all if None/null. Single empty string or empty list will match all. |
Implementation Reference
- mcpunk/tools.py:340-360 (handler)The MCP tool handler function `find_files_by_chunk_content`. It is decorated with @mcp.tool() and @log_inputs_outputs(), and delegates to `_filter_files_by_chunk` with filter_on='name_or_content'.
@mcp.tool() @log_inputs_outputs() def find_files_by_chunk_content( project_name: str, chunk_contents_filter: FilterType, ) -> ToolResponse: """Step 1: Find files containing chunks with matching text. Returns file tree only showing which files contain matches. You must use find_matching_chunks_in_file on each relevant file to see the actual matches. Example workflow: 1. Find files: files = find_files_by_chunk_content(project, ["MyClass"]) 2. For each file, find actual matches: matches = find_matching_chunks_in_file(file, ["MyClass"]) 3. Get content: content = chunk_details(file, match_id) """ return _filter_files_by_chunk(project_name, chunk_contents_filter, "name_or_content").render() - mcpunk/tools.py:340-341 (registration)Registration via @mcp.tool() decorator on the `find_files_by_chunk_content` function, making it available as an MCP tool.
@mcp.tool() @log_inputs_outputs() - mcpunk/tools.py:484-500 (helper)The `_filter_files_by_chunk` helper function that performs the actual logic: iterates over project files and their chunks, checks if any chunk matches the filter (via `chunk.matches_filter`), and returns a file tree of matches.
def _filter_files_by_chunk( project_name: str, filter_: FilterType, filter_on: Literal["name", "name_or_content"], ) -> MCPToolOutput: project = _get_project_or_error(project_name) matching_files: set[pathlib.Path] = set() for file in project.chunk_project.files: if any(c.matches_filter(filter_, filter_on) for c in file.chunks): matching_files.add(file.abs_path) data = create_file_tree(project_root=project.root, paths=matching_files) if data is None: return MCPToolOutput(text="No files found") elif isinstance(data, str): return MCPToolOutput(text=data) else: assert_never(data) - mcpunk/file_chunk.py:75-94 (helper)The `Chunk.matches_filter` method used by _filter_files_by_chunk. It checks whether the chunk's name and/or content matches the filter criteria.
def matches_filter( self, filter_: None | list[str] | str, filter_on: Literal["name", "content", "name_or_content"], ) -> bool: """Return True if the chunk's name matches the given filter. str matches if the chunk's name contains the string. list[str] matches if the chunk's name contains any of the strings in the list. None matches all chunks. """ if filter_on == "name": data = self.name elif filter_on == "content": data = self.content elif filter_on == "name_or_content": data = self.content + self.name else: assert_never(filter_on) return matches_filter(filter_, data) - mcpunk/util.py:133-156 (helper)The `matches_filter` utility function that performs the actual string matching logic (None matches all, str checks containment, list checks any containment).
def matches_filter(filter_: None | list[str] | str, data: str | None) -> bool: """Return True if the data matches the given filter. filter_ can be: - None matches all data - str matches if the data contains the string. Empty string matches all. - list[str] matches if the data contains any of the strings in the list. Empty list matches all. I find the LLM likes to use an empty list to mean "all" even though it should probably use None so 🤷 if data is None it never matches (unless filter_ is None) """ if filter_ is None: return True if len(filter_) == 0: return True if data is None: return False if isinstance(filter_, str): return filter_ in data if isinstance(filter_, list): return any(x in data for x in filter_) assert_never(filter_)