undo
Reverse the last operation in a CSV Editor session to correct errors or revert changes. Requires the session ID to restore data to its previous state.
Instructions
Undo the last operation in a session.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| session_id | Yes |
Implementation Reference
- src/csv_editor/server.py:500-506 (handler)The primary MCP tool handler and registration for the 'undo' tool using @mcp.tool decorator. Delegates to internal _undo_operation function.@mcp.tool async def undo( session_id: str, ctx: Context = None ) -> Dict[str, Any]: """Undo the last operation in a session.""" return await _undo_operation(session_id, ctx)
- Helper function that handles session retrieval and calls the CSVSession.undo method, wrapping the result in OperationResult.async def undo_operation( session_id: str, ctx: Context = None ) -> Dict[str, Any]: """ Undo the last operation in a session. Args: session_id: Session identifier ctx: FastMCP context Returns: Dict with success status and undo result """ try: manager = get_session_manager() session = manager.get_session(session_id) if not session: return OperationResult( success=False, message="Session not found", error=f"No session with ID: {session_id}" ).model_dump() if ctx: await ctx.info(f"Undoing last operation for session {session_id}") result = await session.undo() if result["success"]: if ctx: await ctx.info(f"Successfully undid operation: {result.get('message')}") return OperationResult( success=True, message=result["message"], session_id=session_id, data=result ).model_dump() else: return OperationResult( success=False, message="Failed to undo operation", error=result.get("error") ).model_dump() except Exception as e: logger.error(f"Error undoing operation: {str(e)}") if ctx: await ctx.error(f"Failed to undo operation: {str(e)}") return OperationResult( success=False, message="Failed to undo operation", error=str(e) ).model_dump()
- CSVSession class method that executes the undo by calling history_manager.undo(), updates the dataframe, and handles auto-save.async def undo(self) -> Dict[str, Any]: """Undo the last operation.""" if not self.history_manager: return {"success": False, "error": "History is not enabled"} if not self.history_manager.can_undo(): return {"success": False, "error": "No operations to undo"} try: operation, data_snapshot = self.history_manager.undo() if data_snapshot is not None: self.df = data_snapshot # Trigger auto-save if configured if self.auto_save_manager.should_save_after_operation(): await self.auto_save_manager.trigger_save(self._save_callback, "undo") return { "success": True, "message": f"Undid operation: {operation.operation_type}", "operation": operation.to_dict(), "can_undo": self.history_manager.can_undo(), "can_redo": self.history_manager.can_redo() } else: return { "success": False, "error": "No snapshot available for undo" } except Exception as e: logger.error(f"Error during undo: {str(e)}") return {"success": False, "error": str(e)}
- Core implementation of undo logic in HistoryManager class: adjusts current_index, moves operation to redo stack, retrieves previous data snapshot.def undo(self) -> Tuple[Optional[OperationHistory], Optional[pd.DataFrame]]: """Undo the last operation and return the previous state.""" if not self.can_undo(): return None, None # Move current operation to redo stack current_op = self.history[self.current_index] self.redo_stack.append(current_op) # Move index back self.current_index -= 1 # Find the most recent snapshot before current position snapshot = None for i in range(self.current_index, -1, -1): if self.history[i].data_snapshot is not None: snapshot = self.history[i].data_snapshot.copy() break # Save state if self.storage_type != HistoryStorage.MEMORY: self._save_history() logger.info(f"Undid operation: {current_op.operation_type}") # Return the operation that was undone and the data to restore return current_op, snapshot