undo
Revert the last change made to your CSV data within the current editing session. Use this action to correct mistakes or restore previous states during data manipulation.
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 (registration)Registers the 'undo' MCP tool using @mcp.tool decorator. Provides type hints for input schema (session_id: str) and delegates to implementation.@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)
- Executes the undo tool logic: retrieves CSV session, invokes session.undo(), wraps result with OperationResult, handles errors and context logging.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 undo method: checks history, calls history_manager.undo(), restores dataframe snapshot, triggers auto-save, returns status.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 HistoryManager.undo(): shifts current operation to redo stack, decrements history index, locates and returns prior data snapshot for restoration.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