Content
# MCP File Management Server
A file management server built on FastMCP, providing secure file read/write, search, move, copy, delete, and recovery functions.
## 🚀 Quick Start
### 1. Install Dependencies
```bash
pip install -r requirements.txt
```
### 2. Configure Path (Optional)
Edit `utils.py` to modify the base directory:
```python
BASE_PATH = Path(r'D:\LLM_Data\Data') # File operation root directory
RECOVERY_PATH = Path(r"D:\LLM_Data\Recovery") # Recycle bin directory
```
## 📂 Project Structure
```
FileOperateMCP/
├── Data # LLM operation space
├── Recovery # Recycle bin
├── main.py # Main program, contains all Tool implementations
├── utils.py # Utility functions (path safety, ID generation, log decorators, etc.)
├── mcp.db # SQLite3 database (recycle bin metadata)
├── record.csv # Operation log file
├── requirements.txt # Dependency list
└── README.md # Project documentation
```
## 📋 Project Overview
### Features
- **Secure File Operations**: All operations are restricted within a sandbox directory (`D:\LLM_Data\Data`) to prevent path traversal attacks
- **Flexible Text Reading**: Supports reading text files by line number, range, reverse count, etc.
- **Binary File Support**: Safely transmits binary data through Base64 encoding, supports reading before and after bytes
- **Powerful Text Search**: Uses Python's native regular expression engine, cross-platform compatible, and prevents command injection
- **Recycle Bin Mechanism**: Deleted files are automatically moved to the recycle bin and can be recovered by ID
- **Complete Log Records**: All operations are automatically recorded to a CSV log file, including parameters and results
- **Multi-Encoding Support**: Automatically detects and handles multiple file encodings (UTF-8, GBK, etc.)
### Technical Implementation
- **Framework**: FastMCP (Model Context Protocol)
- **Path Safety**: Uses `pathlib.Path.resolve()` and `relative_to()` to verify paths
- **ID Generation**: UUID4 first 20 characters, nearly zero collision probability
- **Log System**: CSV format + JSON serialized parameters, UTF-8-SIG encoding
- **Database**: SQLite3 stores recycle bin metadata
- **Error Handling**: Unified exception capture and friendly error messages
## 🛠️ Tools List
### 📑 Directory
1. [read_file_content](#1-read_file_content) - Read file content
2. [find_str](#2-find_str) - Text search
3. [write_file_content](#3-write_file_content) - Write file content
4. [move_file](#4-move_file) - Move/rename file
5. [copy_file](#5-copy_file) - Copy file
6. [delete_file](#6-delete_file) - Delete file (recycle bin)
7. [recovery_file](#7-recovery_file) - Recover file
8. [clean_recovery](#8-clean_recovery) - Empty recycle bin/permanently delete
9. [create_dir](#9-create_dir) - Create directory
10. [list_dir](#10-list_dir) - List directory contents
11. [search_file](#11-search_file) - Search file/directory
### 1. read_file_content
Reads file content, supporting text and binary modes.
**Parameters:**
- `user_path` (str): File path relative to the base directory
- `mode` (str, default='text'): Read mode
- `'text'`: Text mode
- `'binary'`: Binary mode (returns Base64 encoded)
- `encoding` (str, default='utf-8'): Text encoding (only applies to text mode)
- `lines` (str, default=''): Line range expression (only applies to text mode)
- `''`: Read all lines (default)
- `'5'`: 5th line
- `'-1'`: Last line
- `'-5'`: 5th line from the end
- `'2-10'`: 2nd to 10th lines
- `'2,6,4'`: 2nd, 6th, 4th lines
- `'2-5 11,12'`: 2nd-5th lines and 11th, 12th lines
- `bytes_count` (int|None, default=None): Byte count limit (only applies to binary mode)
- `None`: Read all bytes (default)
- Positive integer: Read first N bytes
- Negative integer: Read last N bytes (-1 means last byte)
**Returns:** File text content or Base64 encoded binary data
**Example:**
```python
# Read all text
content = read_file_content('document.txt')
# Read 5th line
line5 = read_file_content('document.txt', lines='5')
# Read last 3 lines
last3 = read_file_content('document.txt', lines='-3')
# Read first 100 bytes (binary)
header = read_file_content('image.png', mode='binary', bytes_count=100)
# Read last 50 bytes (binary)
tail = read_file_content('data.bin', mode='binary', bytes_count=-50)
```
### 2. find_str
Searches for matching text in files (using Python's native regular expression, preventing command injection).
**Parameters:**
- `user_path` (str): Path from the base directory (file or directory)
- `regx` (str): Regular expression string
- `ignore_ul` (bool, default=False): Whether to ignore case
- `recursive` (bool, default=True): Whether to recursively search subdirectories
**Returns:** Match result string, formatted as `"file path:line number:matched content"`, one match per line
**Example:**
```python
# Search for lines containing "error" (case-sensitive)
results = find_str('logs', 'error')
# Search ignoring case
results = find_str('logs', 'ERROR', ignore_ul=True)
# Search for email addresses using regular expression
results = find_str('contacts', r'[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}')
# Search only in current directory (not recursive)
results = find_str('docs', 'TODO', recursive=False)
```
### 3. write_file_content
Creates a file and writes content to the specified path.
**Parameters:**
- `user_path` (str): File path relative to the base directory
- `content` (str, default=''): Content to write
- Text mode: ordinary string
- Binary mode: Base64 encoded string
- `mode` (str, default='text'): Write mode
- `'text'`: Overwrite text
- `'append'`: Append text
- `'binary'`: Overwrite binary
- `'append_binary'`: Append binary
- `encoding` (str, default='utf-8'): Encoding method (only applies to text mode)
**Returns:** Success message string ('File created successfully' / 'Written successfully' / 'Appended successfully' / 'Binary written successfully' / 'Binary appended successfully')
**Example:**
```python
# Write to text file
write_file_content('hello.txt', 'Hello World!')
# Append text
write_file_content('log.txt', 'New log entry\n', mode='append')
# Write binary file (needs Base64 encoding)
import base64
binary_data = b'\x89PNG\r\n\x1a\n'
base64_str = base64.b64encode(binary_data).decode('ascii')
write_file_content('image.png', base64_str, mode='binary')
```
### 4. move_file
Moves or renames a file or directory.
**Parameters:**
- `src` (str): Source path (from base path)
- `dst` (str): Destination path (from base path)
- `override` (bool, default=False): Whether to override if the destination exists
**Returns:** 'Moved successfully' or 'Renamed successfully'
**Example:**
```python
# Move file to another directory
move_file('old_folder/file.txt', 'new_folder/file.txt')
# Rename file (move within the same directory)
move_file('document.txt', 'document_renamed.txt')
# Override existing file
move_file('file1.txt', 'file2.txt', override=True)
```
### 5. copy_file
Copies a file or directory.
**Parameters:**
- `src` (str): Source path (from base path)
- `dst` (str): Destination path (from base path)
- `override` (bool, default=False): Whether to override if the destination exists
**Returns:** 'Success'
**Example:**
```python
# Copy file
copy_file('source.txt', 'backup/source_copy.txt')
# Copy directory
copy_file('folder', 'backup/folder_backup')
# Override existing file
copy_file('file1.txt', 'file2.txt', override=True)
```
### 6. delete_file
Deletes a file or directory (moves to recycle bin).
**Parameters:**
- `user_path` (str): Path from the base directory to be deleted
**Returns:** Success message with recovery ID
**Example:**
```python
# Delete file
result = delete_file('unwanted.txt')
print(result) # "Success! File deleted, if needed, you can recover it with ID:abc123... through recovery_file"
# Save ID for recovery
recovery_id = result.split('ID:')[1].split()[0]
```
### 7. recovery_file
Recovers a file using the ID returned during deletion.
**Parameters:**
- `_id` (str): ID returned during file deletion
- `override` (bool, default=False): Whether to override if a file with the same name exists during recovery
**Returns:** Success message
**Example:**
```python
# Recover file
result = recovery_file('abc123def456ghi789jk')
print(result) # "File recovered successfully to \folder\file.txt"
# Override existing file
result = recovery_file('abc123def456ghi789jk', override=True)
```
### 8. clean_recovery
Empties the recycle bin or permanently deletes files (cannot be recovered).
**Parameters:**
- `_id` (str): Operation type, supports three modes:
- `'ALL'`: Empties the entire recycle bin (deletes all files and database records), use with caution!
- `'DATABASE'`: Cleans up invalid records in the database (files do not exist but records still exist)
- Specific ID: Permanently deletes the file with the specified ID and its database record
**Returns:** Operation result message
**Example:**
```python
# Empty entire recycle bin (use with caution!)
result = clean_recovery('ALL')
print(result) # "Recycle bin completely emptied"
# Clean up orphaned records in database
result = clean_recovery('DATABASE')
print(result) # "Database cleanup successful!"
# Permanently delete specific file (irreversible!)
result = clean_recovery('abc123def456ghi789jk')
print(result) # "File abc123def456ghi789jk permanently deleted"
```
**⚠️ Warning:**
- `clean_recovery('ALL')` **permanently deletes** all files in the recycle bin and cannot be recovered
- `clean_recovery('specific ID')` **permanently deletes** the specified file and cannot be recovered
- It is recommended to first recover needed files using `recovery_file()`, then empty the recycle bin
### 9. create_dir
Creates a folder (supports automatic creation of multi-level directories).
**Parameters:**
- `user_path` (str): Path from the base directory
**Returns:** 'Success'
**Example:**
```python
# Create single-level directory
create_dir('new_folder')
# Create multi-level directory
create_dir('parent/child/grandchild')
```
### 10. list_dir
Lists all objects in a directory.
**Parameters:**
- `user_path` (str, default='./'): Path from the base directory
**Returns:** Dictionary `{object name: type}`, type is 'f' (file) or 'd' (folder)
**Example:**
```python
# List root directory
contents = list_dir()
# Returns: {'file1.txt': 'f', 'folder1': 'd', 'file2.py': 'f'}
# List specified directory
contents = list_dir('documents')
```
### 11. search_file
Searches for files or directories using regular expressions.
**Parameters:**
- `pattern` (str): Regular expression to match object names
- `user_path` (str, default='./'): Search path from the base directory
- `types` (str, default='f'): Search object type
- `'f'`: Files only
- `'d'`: Folders only
- `'a'`: Files + folders
**Returns:** Dictionary `{relative path: type}`
**Example:**
```python
# Search for all Python files
py_files = search_file(r'.*\.py$', types='f')
# Returns: {'src/main.py': 'f', 'utils/helper.py': 'f'}
# Search for folders containing "test"
test_dirs = search_file(r'test', types='d')
# Search for all objects
all_matches = search_file(r'readme', types='a')
```
## 🔒 Security Features
### 1. Path Sandbox
All file operations are restricted within `BASE_PATH` (`D:\LLM_Data\Data`) using the `safe_path()` function:
```python
full_path = (BASE_PATH / path).resolve()
full_path.relative_to(BASE_PATH.resolve()) # Ensure within sandbox
```
### 2. Command Injection Protection
`find_str` uses Python's native `re` module, does not call system commands, and completely prevents command injection attacks.
### 3. Regular Expression Verification
All functions accepting regular expressions are compiled and verified first, capturing invalid regular expressions:
```python
try:
pattern = re.compile(regx)
except re.error as e:
raise ValueError(f"Invalid regular expression - {str(e)}")
```
### 4. Unique ID Generation
Uses UUID4 first 20 characters to generate recycle bin IDs, with extremely low collision probability (about 2^60):
```python
_id = str(uuid.uuid4())[:20]
```
## 📝 Log System
All tool calls are automatically recorded to the `record.csv` file:
**Log format:**
```csv
func_name,args_str,kwargs_str,status,timestamp,error_msg
read_file_content,"[]","{""user_path"": ""test.txt"", ""lines"": ""5""}",Success,2024-01-01 12:00:00,
find_str,"[]","{""user_path"": ""logs"", ""regx"": ""error""}",Fail,2024-01-01 12:01:00,Path does not exist
```
**Features:**
- CSV format, using `csv.writer` to ensure correct format
- JSON serializes parameters to avoid special characters breaking the format
- UTF-8-SIG encoding, Chinese displays normally when opened in Excel
- Records args and kwargs, fully tracking call information
## 🗄️ Database Structure
SQLite3 database (`mcp.db`) stores recycle bin metadata:
```sql
CREATE TABLE recovery (
id CHAR(20) NOT NULL PRIMARY KEY UNIQUE,
ori_path VARCHAR(1024) NOT NULL,
datetime DATETIME
);
```
**Field explanation:**
- `id`: 20-character unique identifier (UUID4 prefix)
- `ori_path`: Original file path (absolute path)
- `datetime`: Deletion time
## ⚠️ Precautions
1. **Path restriction**: All paths must be within `BASE_PATH`, no `..` allowed to escape
2. **Encoding issue**: Text files default to UTF-8, Windows files may require GBK
3. **Large file handling**: Use `lines` or `bytes_count` to limit range when reading large files
4. **Recycle bin cleanup**: Regularly clean up `RECOVERY_PATH` to free disk space
5. **Log rotation**: `record.csv` will continue to grow, recommend regular archiving
## 🤝 Contribution
Welcome to submit Issues and Pull Requests!
## 📄 License
MIT License
## 👨💻 Author
Pieyue
Connection Info
You Might Also Like
markitdown
MarkItDown-MCP is a lightweight server for converting URIs to Markdown.
markitdown
Python tool for converting files and office documents to Markdown.
Filesystem
Node.js MCP Server for filesystem operations with dynamic access control.
TrendRadar
TrendRadar: Your hotspot assistant for real news in just 30 seconds.
mempalace
The highest-scoring AI memory system ever benchmarked. And it's free.
mempalace
The highest-scoring AI memory system ever benchmarked. And it's free.