Skip to main content
Glama
PWalaGov

Enhanced Directory Context MCP Server

by PWalaGov

batch_file_operations

Execute multiple file operations like create, update, delete, or rename in a single transaction with rollback capability for error handling.

Instructions

Perform multiple file operations in a single transaction

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
operationsYesArray of file operations to perform
rollback_on_errorNoRollback all operations if any fails

Implementation Reference

  • Core handler function for 'batch_file_operations' tool. Executes multiple file operations sequentially, tracks performed actions for potential rollback, returns JSON summary of results.
    async handleBatchFileOperations(args) {
      const { operations, rollback_on_error = true } = args;
      const results = [];
      const performedOperations = [];
      
      try {
        for (const op of operations) {
          const { operation, params } = op;
          
          try {
            let result;
            switch (operation) {
              case 'create':
                result = await this.handleCreateFile(params);
                performedOperations.push({ type: 'create', path: params.path });
                break;
              
              case 'update':
                result = await this.handleUpdateFile({ ...params, backup: false });
                performedOperations.push({ type: 'update', path: params.path, backupPath: `${params.path}.batch-backup` });
                break;
              
              case 'append':
                result = await this.handleAppendToFile(params);
                performedOperations.push({ type: 'append', path: params.path });
                break;
              
              case 'delete':
                result = await this.handleDeleteFile({ ...params, backup: false });
                performedOperations.push({ type: 'delete', path: params.path });
                break;
              
              case 'rename':
                result = await this.handleRenameFile(params);
                performedOperations.push({ type: 'rename', oldPath: params.old_path, newPath: params.new_path });
                break;
              
              default:
                throw new Error(`Unknown operation: ${operation}`);
            }
            
            results.push({
              operation,
              status: 'success',
              message: result.content[0].text,
            });
          } catch (error) {
            results.push({
              operation,
              status: 'error',
              message: error.message,
            });
            
            if (rollback_on_error) {
              // Rollback performed operations
              await this.rollbackOperations(performedOperations);
              throw new Error(`Batch operation failed at step ${results.length}. All changes rolled back. Error: ${error.message}`);
            }
          }
        }
        
        return {
          content: [
            {
              type: 'text',
              text: JSON.stringify({
                summary: `Batch operations completed: ${results.filter(r => r.status === 'success').length}/${operations.length} successful`,
                results,
              }, null, 2),
            },
          ],
        };
      } catch (error) {
        throw new McpError(ErrorCode.InternalError, `Batch operations failed: ${error.message}`);
      }
    }
  • Input schema defining the structure for batch_file_operations arguments: array of operations (each with type and params) and optional rollback flag.
    inputSchema: {
      type: 'object',
      properties: {
        operations: {
          type: 'array',
          description: 'Array of file operations to perform',
          items: {
            type: 'object',
            properties: {
              operation: {
                type: 'string',
                enum: ['create', 'update', 'append', 'delete', 'rename'],
                description: 'Type of operation',
              },
              params: {
                type: 'object',
                description: 'Parameters for the operation',
              },
            },
            required: ['operation', 'params'],
          },
        },
        rollback_on_error: {
          type: 'boolean',
          description: 'Rollback all operations if any fails',
          default: true,
        },
      },
      required: ['operations'],
    },
  • server.js:337-370 (registration)
    Tool registration in ListToolsRequestSchema handler, defining name, description, and inputSchema for batch_file_operations.
    {
      name: 'batch_file_operations',
      description: 'Perform multiple file operations in a single transaction',
      inputSchema: {
        type: 'object',
        properties: {
          operations: {
            type: 'array',
            description: 'Array of file operations to perform',
            items: {
              type: 'object',
              properties: {
                operation: {
                  type: 'string',
                  enum: ['create', 'update', 'append', 'delete', 'rename'],
                  description: 'Type of operation',
                },
                params: {
                  type: 'object',
                  description: 'Parameters for the operation',
                },
              },
              required: ['operation', 'params'],
            },
          },
          rollback_on_error: {
            type: 'boolean',
            description: 'Rollback all operations if any fails',
            default: true,
          },
        },
        required: ['operations'],
      },
    },
  • server.js:491-492 (registration)
    Dispatch case in CallToolRequestSchema handler that routes calls to batch_file_operations to the handleBatchFileOperations method.
    case 'batch_file_operations':
      return await this.handleBatchFileOperations(args);
  • Supporting helper method called by the handler to rollback operations in reverse order if an error occurs and rollback is enabled.
    async rollbackOperations(operations) {
      // Rollback in reverse order
      for (let i = operations.length - 1; i >= 0; i--) {
        const op = operations[i];
        try {
          switch (op.type) {
            case 'create':
              await fs.unlink(path.resolve(this.workingDirectory, op.path));
              break;
            
            case 'update':
              if (op.backupPath) {
                const fullPath = path.resolve(this.workingDirectory, op.path);
                const backupPath = path.resolve(this.workingDirectory, op.backupPath);
                await fs.copyFile(backupPath, fullPath);
                await fs.unlink(backupPath);
              }
              break;
            
            case 'rename':
              await fs.rename(
                path.resolve(this.workingDirectory, op.newPath),
                path.resolve(this.workingDirectory, op.oldPath)
              );
              break;
            
            // append and delete are harder to rollback without backups
          }
        } catch (error) {
          console.error(`Failed to rollback operation:`, op, error);
        }
      }
    }

Latest Blog Posts

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/PWalaGov/File-Control-MCP'

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