compare_files
Compare two text files and display differences in text or JSON format. Specify file paths, encoding, and output format to analyze file content variations efficiently.
Instructions
Compare two text files and show differences.
Args:
file1: First file path
file2: Second file path
encoding: Text encoding (default: utf-8)
format: Output format ('text' or 'json')
ctx: MCP context
Returns:
Comparison results
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| encoding | No | utf-8 | |
| file1 | Yes | ||
| file2 | Yes | ||
| format | No | text |
Implementation Reference
- mcp_filesystem/advanced.py:509-584 (handler)Core handler function that implements the file comparison logic using difflib for unified diffs, line change counts, similarity ratio, and path validation.async def compare_files( self, file1: Union[str, Path], file2: Union[str, Path], encoding: str = "utf-8" ) -> Dict: """Compare two text files and show differences. Args: file1: First file path file2: Second file path encoding: Text encoding (default: utf-8) Returns: Dictionary with comparison results Raises: ValueError: If paths are outside allowed directories """ import difflib path1, allowed1 = await self.validator.validate_path(file1) if not allowed1: raise ValueError(f"Path outside allowed directories: {file1}") path2, allowed2 = await self.validator.validate_path(file2) if not allowed2: raise ValueError(f"Path outside allowed directories: {file2}") try: content1 = await anyio.to_thread.run_sync(path1.read_text, encoding) content2 = await anyio.to_thread.run_sync(path2.read_text, encoding) # Get file names for display name1 = path1.name name2 = path2.name # Split into lines lines1 = content1.splitlines() lines2 = content2.splitlines() # Calculate differences diff = list( difflib.unified_diff( lines1, lines2, fromfile=name1, tofile=name2, lineterm="" ) ) # Count added, removed, and changed lines added = sum( 1 for line in diff if line.startswith("+") and not line.startswith("+++") ) removed = sum( 1 for line in diff if line.startswith("-") and not line.startswith("---") ) # Calculate similarity ratio matcher = difflib.SequenceMatcher(None, content1, content2) similarity = matcher.ratio() return { "diff": "\n".join(diff), "added_lines": added, "removed_lines": removed, "similarity": similarity, "are_identical": content1 == content2, } except FileNotFoundError as e: raise FileNotFoundError(f"File not found: {e}") except PermissionError as e: raise ValueError(f"Permission denied: {e}") except UnicodeDecodeError as e: raise ValueError(f"Cannot decode file as {encoding}: {e}")
- mcp_filesystem/server.py:567-614 (registration)MCP tool registration using @mcp.tool() decorator. This is the entrypoint handler that validates input, calls the core implementation in AdvancedFileOperations, and formats the output for text or JSON.@mcp.tool() async def compare_files( file1: str, file2: str, ctx: Context, encoding: str = "utf-8", format: str = "text", ) -> str: """Compare two text files and show differences. Args: file1: First file path file2: Second file path encoding: Text encoding (default: utf-8) format: Output format ('text' or 'json') ctx: MCP context Returns: Comparison results """ try: components = get_components() result = await components["advanced"].compare_files(file1, file2, encoding) if format.lower() == "json": return json.dumps(result, indent=2) # Format as text similarity_pct = f"{result['similarity'] * 100:.1f}%" if result["are_identical"]: return "Files are identical (100% similarity)" lines = [ f"Comparing {file1} with {file2}", f"Similarity: {similarity_pct}", f"Lines added: {result['added_lines']}", f"Lines removed: {result['removed_lines']}", "", "Diff:", result["diff"], ] return "\n".join(lines) except Exception as e: return f"Error comparing files: {str(e)}"