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
No recommendations available