Skip to main content
Glama

File Patch MCP Server

by shenning00
WORKFLOWS.md12.1 kB
# Error Recovery Workflow Patterns This document describes the four error recovery workflow patterns implemented in the Patch MCP Server. These patterns demonstrate best practices for safe and reliable patch operations by combining multiple tools into common workflows. ## Overview The Patch MCP Server provides 7 individual tools that can be combined into powerful error recovery patterns: 1. **Try-Revert**: Sequential patches with automatic rollback 2. **Backup-Restore**: Safe experimentation with automatic restore 3. **Validate-All-Then-Apply**: Atomic batch operations (all-or-nothing) 4. **Progressive Validation**: Step-by-step validation with detailed reporting --- ## Pattern 1: Try-Revert **Use Case**: Apply multiple patches sequentially, reverting all on first failure ### When to Use - Applying a series of dependent patches - Transactional patch application - Safe multi-step modifications ### How It Works 1. Apply patches one by one in order 2. Track each successfully applied patch 3. If any patch fails, revert all previously applied patches in reverse order 4. Return success only if all patches apply successfully ### Example Workflow ```python # Scenario: Apply 3 related patches to config.py patches = [timeout_patch, retry_patch, debug_patch] # Apply with automatic revert on failure result = apply_patches_with_revert("config.py", patches) if result["success"]: print(f"✓ Applied {result['patches_applied']} patches") else: print(f"✗ Failed at patch {result['failed_at']}") print(f" Error: {result['error']}") print(f" Reverted: {result['reverted']}") ``` ### Manual Implementation ```python # Using individual tools applied = [] for i, patch in enumerate(patches): result = apply_patch("config.py", patch) if not result["success"]: # Revert all previously applied patches for applied_patch in reversed(applied): revert_patch("config.py", applied_patch) break applied.append(patch) ``` ### Return Values **Success**: ```json { "success": true, "patches_applied": 3, "message": "Successfully applied 3 patches" } ``` **Failure**: ```json { "success": false, "patches_applied": 2, "failed_at": 3, "error": "context_mismatch", "reverted": true } ``` --- ## Pattern 2: Backup-Restore **Use Case**: Apply patch with automatic backup and restore on failure ### When to Use - Safe experimentation with patches - Critical file modifications - Testing patches before committing changes ### How It Works 1. Create a timestamped backup of the target file 2. Attempt to apply the patch 3. If patch fails, automatically restore from backup 4. On success, optionally keep or delete the backup ### Example Workflow ```python # Apply patch with automatic cleanup result = apply_patch_with_backup("app.py", patch) # Or keep backup for safety result = apply_patch_with_backup("critical.py", patch, keep_backup=True) if result["success"]: print("✓ Patch applied successfully") if result["backup_file"]: print(f" Backup saved at: {result['backup_file']}") else: print(f"✗ Patch failed: {result['error']}") if result.get("restored"): print(" ✓ File restored from backup") ``` ### Manual Implementation ```python # Using individual tools # 1. Create backup backup_result = backup_file("app.py") backup_path = backup_result["backup_file"] # 2. Apply patch result = apply_patch("app.py", patch) if not result["success"]: # 3. Restore on failure restore_backup(backup_path) print("Restored from backup") else: # 4. Optionally clean up backup import os os.remove(backup_path) ``` ### Return Values **Success**: ```json { "success": true, "backup_file": "app.py.backup.20250119_143052", "message": "Patch applied successfully" } ``` **Failure (Restored)**: ```json { "success": false, "error": "context_mismatch", "restored": true, "phase": "apply" } ``` **Critical Failure**: ```json { "success": false, "error": "context_mismatch", "restore_failed": true, "backup_file": "app.py.backup.20250119_143052", "phase": "restore" } ``` --- ## Pattern 3: Validate-All-Then-Apply **Use Case**: Apply multiple patches to multiple files atomically (all-or-nothing) ### When to Use - Multi-file refactoring - Coordinated changes across files - Ensuring consistency across multiple files ### How It Works 1. Validate all patches against all files first 2. If any validation fails, stop immediately (no files modified) 3. Create backups for all files 4. Apply all patches 5. If any apply fails, restore all files from backups ### Example Workflow ```python # Scenario: Refactor function across 3 files pairs = [ ("config.py", config_patch), ("utils.py", utils_patch), ("main.py", main_patch), ] result = apply_patches_atomic(pairs) if result["success"]: print(f"✓ Applied {result['applied']} patches atomically") else: if result["phase"] == "validation": print(f"✗ Validation failed for {result['failed']} files:") for failure in result["failures"]: print(f" - {failure['file']}: {failure['reason']}") else: print(f"✗ Apply failed at {result['failed_at']}") print(f" Rolled back: {result['rolled_back']}") ``` ### Manual Implementation ```python # Using individual tools files_and_patches = [("config.py", patch1), ("utils.py", patch2)] # 1. Validate all for file_path, patch in files_and_patches: result = validate_patch(file_path, patch) if not result["can_apply"]: print(f"Validation failed for {file_path}") exit(1) # 2. Backup all backups = {} for file_path, _ in files_and_patches: backup_result = backup_file(file_path) backups[file_path] = backup_result["backup_file"] # 3. Apply all (with rollback on failure) try: for file_path, patch in files_and_patches: result = apply_patch(file_path, patch) if not result["success"]: # Restore all backups for fp, backup in backups.items(): restore_backup(backup) print("Rolled back all changes") exit(1) print("All patches applied successfully") except Exception as e: # Emergency restore for fp, backup in backups.items(): restore_backup(backup) ``` ### Return Values **Success**: ```json { "success": true, "applied": 3, "message": "Atomically applied 3 patches" } ``` **Validation Failure**: ```json { "success": false, "phase": "validation", "validated": 3, "failed": 1, "failures": [ {"file": "utils.py", "reason": "context_mismatch"} ] } ``` **Apply Failure**: ```json { "success": false, "phase": "apply", "applied": 2, "failed_at": "main.py", "error": "permission_denied", "rolled_back": true } ``` --- ## Pattern 4: Progressive Validation **Use Case**: Apply patch with step-by-step validation and detailed error reporting ### When to Use - Debugging patch failures - Understanding exactly where problems occur - Maximum visibility into the patch process ### How It Works 1. **Safety Check**: Validate file exists, is writable, has disk space 2. **Validation**: Check patch format and applicability 3. **Backup**: Create backup before modification 4. **Apply**: Apply the patch 5. **Restore** (if apply fails): Automatically restore from backup Each step is tracked with success/failure status and details. ### Example Workflow ```python # Apply with maximum visibility result = apply_patch_progressive("module.py", patch) if result["success"]: print("✓ Patch applied successfully") print(f" Backup: {result['backup_file']}") print(f" Changes: {result['changes']}") else: print(f"✗ Failed at: {result['failed_at']}") print(f" Error: {result['error']}") print(f" Error type: {result['error_type']}") # Show which steps passed for step, status in result["steps"].items(): marker = "✓" if status["passed"] else "✗" print(f" {marker} {step}") ``` ### Manual Implementation ```python # Using individual tools with step-by-step checking results = {"steps": {}} # Step 1: Safety check from patch_mcp.utils import validate_file_safety from pathlib import Path safety = validate_file_safety(Path("module.py"), check_write=True, check_space=True) results["steps"]["safety_check"] = {"passed": safety is None} if safety: print(f"Safety check failed: {safety['error']}") exit(1) # Step 2: Validate patch validation = validate_patch("module.py", patch) results["steps"]["validation"] = {"passed": validation.get("can_apply", False)} if not validation.get("can_apply"): print(f"Validation failed: {validation.get('reason')}") exit(1) # Step 3: Create backup backup = backup_file("module.py") results["steps"]["backup"] = {"passed": backup["success"]} if not backup["success"]: print(f"Backup failed: {backup['error']}") exit(1) # Step 4: Apply patch apply_result = apply_patch("module.py", patch) results["steps"]["apply"] = {"passed": apply_result["success"]} if not apply_result["success"]: # Step 5: Restore restore_backup(backup["backup_file"]) print(f"Apply failed: {apply_result['error']}, restored from backup") exit(1) print("Success!") ``` ### Return Values **Success**: ```json { "success": true, "steps": { "safety_check": {"passed": true, "details": null}, "validation": {"passed": true, "details": {...}}, "backup": {"passed": true, "details": {...}}, "apply": {"passed": true, "details": {...}} }, "backup_file": "module.py.backup.20250119_143052", "changes": { "lines_added": 5, "lines_removed": 2, "hunks_applied": 1 } } ``` **Failure**: ```json { "success": false, "steps": { "safety_check": {"passed": true, "details": null}, "validation": {"passed": false, "details": {...}} }, "error": "context_mismatch at line 42", "error_type": "context_mismatch", "failed_at": "validation" } ``` --- ## Choosing the Right Pattern | Pattern | Best For | Complexity | Atomicity | Visibility | |---------|----------|------------|-----------|------------| | **Try-Revert** | Sequential dependent patches | Medium | Per-file | Medium | | **Backup-Restore** | Single file experimentation | Low | Single-file | Low | | **Validate-All-Then-Apply** | Multi-file refactoring | High | Multi-file | Medium | | **Progressive Validation** | Debugging, critical files | Medium | Single-file | High | ### Quick Decision Guide - **Single file, test safely** → Use **Backup-Restore** - **Multiple dependent patches to one file** → Use **Try-Revert** - **Multiple files, must succeed together** → Use **Validate-All-Then-Apply** - **Need detailed error info** → Use **Progressive Validation** --- ## Implementation These patterns are implemented in `src/patch_mcp/workflows.py` as helper functions: - `apply_patches_with_revert(file_path, patches)` - Pattern 1 - `apply_patch_with_backup(file_path, patch, keep_backup)` - Pattern 2 - `apply_patches_atomic(file_patch_pairs)` - Pattern 3 - `apply_patch_progressive(file_path, patch)` - Pattern 4 ### Using in Python ```python from patch_mcp.workflows import ( apply_patches_with_revert, apply_patch_with_backup, apply_patches_atomic, apply_patch_progressive, ) # Pattern 1: Sequential with revert result = apply_patches_with_revert("config.py", [patch1, patch2, patch3]) # Pattern 2: Safe experimentation result = apply_patch_with_backup("app.py", patch, keep_backup=True) # Pattern 3: Atomic multi-file pairs = [("file1.py", patch1), ("file2.py", patch2)] result = apply_patches_atomic(pairs) # Pattern 4: Maximum visibility result = apply_patch_progressive("module.py", patch) ``` --- ## Testing All workflow patterns have comprehensive test coverage (21 workflow integration tests + 14 example workflow tests = 35 tests total). See `tests/integration/` for examples. --- ## See Also - [README.md](README.md) - Main documentation - [SECURITY.md](SECURITY.md) - Security features and best practices - [CONTRIBUTING.md](CONTRIBUTING.md) - Development guidelines

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/shenning00/patch_mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server