mcp-intellidiff
MCP 服务配置
复制以下 JSON 到 OPClaw 或其他 MCP 客户端的配置文件中即可使用
{
"mcpServers": {
"intellidiff": {
"type": "http",
"url": "http://localhost:8000/mcp/"
}
}
}
服务介绍
IntelliDiff MCP Server
An intelligent file and folder comparison MCP server with advanced text normalization and duplicate detection capabilities.
Features
- File Comparison: CRC32-based exact comparison and smart text comparison with normalization
- Folder Comparison: Recursive directory comparison with orphan detection
- Duplicate Detection: Find identical files within directories
- Text Normalization: Handle case, whitespace, tabs, line endings, and Unicode differences
- Line-Level Analysis: Detailed diff output with line ranges and targeted file reading
- Clean Output: Markdown-formatted text responses instead of JSON bloat
- Security: Workspace root validation prevents path traversal attacks
- Performance: Streaming for large files, configurable limits, symlink loop prevention
Installation
# Clone or download the project
cd intellidiff-mcp
# Install with uv
uv init --python 3.12
uv add "fastmcp>=2.11"
# Run the server
uv run python intellidiff_server.py /path/to/workspace/root
Project Structure
The server is built with a clean modular architecture:
intellidiff_server.py(52 lines) - Main server entry point and tool registrationworkspace_security.py- Path validation and workspace boundary enforcementfile_operations.py- Core file utilities (CRC32, text detection, normalization)tools.py- Individual MCP tool implementationsfolder_operations.py- Folder comparison and duplicate detection logic
MCP Configuration
Local/stdio Configuration
{
"mcpServers": {
"intellidiff": {
"type": "stdio",
"command": "uv",
"args": ["run", "--directory", "/path/to/intellidiff-mcp", "python", "intellidiff_server.py", "/workspace/root"]
}
}
}
Local/stdio Configuration with Environment Variables
{
"mcpServers": {
"intellidiff": {
"type": "stdio",
"command": "uv",
"args": ["run", "--directory", "/path/to/intellidiff-mcp", "python", "intellidiff_server.py", "/workspace/root"],
"env": {
"INTELLIDIFF_MAX_TEXT_SIZE": "5242880",
"INTELLIDIFF_MAX_BINARY_SIZE": "1073741824",
"INTELLIDIFF_MAX_DEPTH": "15",
"INTELLIDIFF_CHUNK_SIZE": "32768"
}
}
}
}
Remote/HTTP Configuration
{
"mcpServers": {
"intellidiff": {
"type": "http",
"url": "http://localhost:8000/mcp/"
}
}
}
Place this configuration in:
- VS Code:
.vscode/mcp.json(project) or user settings - Claude Desktop:
claude_desktop_config.json - Cursor:
.cursor/mcp.json(project) or~/.cursor/mcp.json(user) - LM Studio:
~/.lmstudio/mcp.json
Environment Variables
| Variable | Default | Description |
|---|---|---|
INTELLIDIFF_MAX_TEXT_SIZE |
10485760 (10MB) | Maximum size for text file comparison |
INTELLIDIFF_MAX_BINARY_SIZE |
1073741824 (1GB) | Maximum size for binary file CRC32 |
INTELLIDIFF_MAX_DEPTH |
10 | Maximum directory recursion depth |
INTELLIDIFF_CHUNK_SIZE |
65536 (64KB) | File reading chunk size |
Tools
validate_workspace_path
Validate that a path is within the workspace root.
Parameters:
path(string): Path to validate
get_file_hash
Get CRC32 hash and basic information about a file.
Parameters:
file_path(string): Path to the file
compare_files
Compare two files with various modes and options.
Parameters:
left_path(string): Path to first fileright_path(string): Path to second filemode(string): Comparison mode - "exact", "smart_text", or "binary"ignore_blank_lines(boolean): Skip empty lines during comparisonignore_newline_differences(boolean): Normalize line endingsignore_whitespace(boolean): Ignore leading/trailing whitespaceignore_case(boolean): Case-insensitive comparisonnormalize_tabs(boolean): Convert tabs to spacesunicode_normalize(boolean): Apply Unicode NFKC normalization
compare_folders
Compare two folder structures recursively.
Parameters:
left_path(string): Path to first folderright_path(string): Path to second foldermax_depth(integer): Maximum recursion depth (default: from env var)include_binary(boolean): Include binary files in comparisoncomparison_mode(string): "exact" or "smart_text"
find_identical_files
Find files with identical content within a folder.
Parameters:
folder_path(string): Path to folder to scanmax_depth(integer): Maximum recursion depth (default: from env var)
read_file_lines
Read specific line ranges from a text file with optional context.
Parameters:
file_path(string): Path to the text filestart_line(integer): Starting line number (1-based, default: 1)end_line(integer): Ending line number (1-based, default: end of file)context_lines(integer): Additional context lines before/after range (default: 0)
Usage Examples
Compare Two Files
# Exact comparison - clean markdown output
result = await client.call_tool("compare_files", {
"left_path": "file1.txt",
"right_path": "file2.txt",
"mode": "exact"
})
print(result.content[0].text)
# Output: **Exact Comparison**
# Left: file1.txt (CRC32: abc123)
# Right: file2.txt (CRC32: abc123)
# Result: Identical
# Smart text comparison with normalization
result = await client.call_tool("compare_files", {
"left_path": "file1.txt",
"right_path": "file2.txt",
"mode": "smart_text",
"ignore_case": True,
"ignore_whitespace": True,
"normalize_tabs": True
})
print(result.content[0].text)
# Output: **Smart Text Comparison - Identical**
# Left: file1.txt (1.2KB)
# Right: file2.txt (1.3KB)
# Result: Identical (normalized: case, whitespace, tabs)
Compare Folders
result = await client.call_tool("compare_folders", {
"left_path": "folder_a",
"right_path": "folder_b",
"max_depth": 5
})
# Folder comparison returns structured data for programmatic access
summary = result.data["summary"]
orphans = result.data["orphans"]
identical_files = result.data["identical_files"]
Find Duplicates
result = await client.call_tool("find_identical_files", {
"folder_path": "my_folder",
"max_depth": 10
})
# Duplicate detection returns structured data for analysis
duplicates = result.data["duplicates"]
wasted_bytes = result.data["summary"]["total_wasted_bytes"]
Read Specific Lines
# Read lines 10-20 with 2 lines of context
result = await client.call_tool("read_file_lines", {
"file_path": "my_file.txt",
"start_line": 10,
"end_line": 20,
"context_lines": 2
})
# Clean line-numbered output with >>> markers for requested range
print(result.content[0].text)
# Output: 8| function setup() {
# 9| console.log("Starting...");
# >>> 10| const data = loadData();
# >>> 11| if (!data) {
# >>> 12| throw new Error("No data");
# >>> 13| }
# 14| }
Working with Diff Results
# Compare files and get detailed diff information
result = await client.call_tool("compare_files", {
"left_path": "file1.txt",
"right_path": "file2.txt",
"mode": "smart_text"
})
# Access structured diff data
if not result.structured_content["identical"]:
change_summary = result.structured_content["change_summary"]
# Get affected line ranges
left_ranges = change_summary["line_ranges"]["left_affected"]
right_ranges = change_summary["line_ranges"]["right_affected"]
# Read specific sections that changed
for range_info in left_ranges:
lines_result = await client.call_tool("read_file_lines", {
"file_path": "file1.txt",
"start_line": range_info["start"],
"end_line": range_info["end"],
"context_lines": 3
})
print(f"Changed section: {lines_result.content[0].text}")
Security
- All file paths are validated against the workspace root
- Path traversal attacks are prevented through path resolution
- Symlink loops are detected and avoided
- File size limits prevent memory exhaustion
- Read-only operations only
Performance
- Streaming I/O for large files
- Early exit on size mismatches
- CRC32 caching for repeated operations
- Configurable chunk sizes and limits
- Progress reporting for large operations
License
MIT License - see LICENSE file for details.