diff --git a/src/excel_mcp/server.py b/src/excel_mcp/server.py index 8fcdf64..902e802 100644 --- a/src/excel_mcp/server.py +++ b/src/excel_mcp/server.py @@ -33,6 +33,10 @@ from excel_mcp.sheet import ( merge_range, unmerge_range, get_merged_ranges, + insert_row, + insert_cols, + delete_rows, + delete_cols, ) # Get project root directory path for log file path. @@ -599,6 +603,78 @@ def get_data_validation_info( logger.error(f"Error getting validation info: {e}") raise +@mcp.tool() +def insert_rows( + filepath: str, + sheet_name: str, + start_row: int, + count: int = 1 +) -> str: + """Insert one or more rows starting at the specified row.""" + try: + full_path = get_excel_path(filepath) + result = insert_row(full_path, sheet_name, start_row, count) + return result["message"] + except (ValidationError, SheetError) as e: + return f"Error: {str(e)}" + except Exception as e: + logger.error(f"Error inserting rows: {e}") + raise + +@mcp.tool() +def insert_columns( + filepath: str, + sheet_name: str, + start_col: int, + count: int = 1 +) -> str: + """Insert one or more columns starting at the specified column.""" + try: + full_path = get_excel_path(filepath) + result = insert_cols(full_path, sheet_name, start_col, count) + return result["message"] + except (ValidationError, SheetError) as e: + return f"Error: {str(e)}" + except Exception as e: + logger.error(f"Error inserting columns: {e}") + raise + +@mcp.tool() +def delete_sheet_rows( + filepath: str, + sheet_name: str, + start_row: int, + count: int = 1 +) -> str: + """Delete one or more rows starting at the specified row.""" + try: + full_path = get_excel_path(filepath) + result = delete_rows(full_path, sheet_name, start_row, count) + return result["message"] + except (ValidationError, SheetError) as e: + return f"Error: {str(e)}" + except Exception as e: + logger.error(f"Error deleting rows: {e}") + raise + +@mcp.tool() +def delete_sheet_columns( + filepath: str, + sheet_name: str, + start_col: int, + count: int = 1 +) -> str: + """Delete one or more columns starting at the specified column.""" + try: + full_path = get_excel_path(filepath) + result = delete_cols(full_path, sheet_name, start_col, count) + return result["message"] + except (ValidationError, SheetError) as e: + return f"Error: {str(e)}" + except Exception as e: + logger.error(f"Error deleting columns: {e}") + raise + async def run_sse(): """Run Excel MCP server in SSE mode.""" # Assign value to EXCEL_FILES_PATH in SSE mode diff --git a/src/excel_mcp/sheet.py b/src/excel_mcp/sheet.py index 034f6e6..357a32d 100644 --- a/src/excel_mcp/sheet.py +++ b/src/excel_mcp/sheet.py @@ -365,3 +365,111 @@ def delete_range_operation( except Exception as e: logger.error(f"Failed to delete range: {e}") raise SheetError(str(e)) + +def insert_row(filepath: str, sheet_name: str, start_row: int, count: int = 1) -> Dict[str, Any]: + """Insert one or more rows starting at the specified row.""" + try: + wb = load_workbook(filepath) + if sheet_name not in wb.sheetnames: + raise SheetError(f"Sheet '{sheet_name}' not found") + + worksheet = wb[sheet_name] + + # Validate parameters + if start_row < 1: + raise ValidationError("Start row must be 1 or greater") + if count < 1: + raise ValidationError("Count must be 1 or greater") + + worksheet.insert_rows(start_row, count) + wb.save(filepath) + + return {"message": f"Inserted {count} row(s) starting at row {start_row} in sheet '{sheet_name}'"} + except (ValidationError, SheetError) as e: + logger.error(str(e)) + raise + except Exception as e: + logger.error(f"Failed to insert rows: {e}") + raise SheetError(str(e)) + +def insert_cols(filepath: str, sheet_name: str, start_col: int, count: int = 1) -> Dict[str, Any]: + """Insert one or more columns starting at the specified column.""" + try: + wb = load_workbook(filepath) + if sheet_name not in wb.sheetnames: + raise SheetError(f"Sheet '{sheet_name}' not found") + + worksheet = wb[sheet_name] + + # Validate parameters + if start_col < 1: + raise ValidationError("Start column must be 1 or greater") + if count < 1: + raise ValidationError("Count must be 1 or greater") + + worksheet.insert_cols(start_col, count) + wb.save(filepath) + + return {"message": f"Inserted {count} column(s) starting at column {start_col} in sheet '{sheet_name}'"} + except (ValidationError, SheetError) as e: + logger.error(str(e)) + raise + except Exception as e: + logger.error(f"Failed to insert columns: {e}") + raise SheetError(str(e)) + +def delete_rows(filepath: str, sheet_name: str, start_row: int, count: int = 1) -> Dict[str, Any]: + """Delete one or more rows starting at the specified row.""" + try: + wb = load_workbook(filepath) + if sheet_name not in wb.sheetnames: + raise SheetError(f"Sheet '{sheet_name}' not found") + + worksheet = wb[sheet_name] + + # Validate parameters + if start_row < 1: + raise ValidationError("Start row must be 1 or greater") + if count < 1: + raise ValidationError("Count must be 1 or greater") + if start_row > worksheet.max_row: + raise ValidationError(f"Start row {start_row} exceeds worksheet bounds (max row: {worksheet.max_row})") + + worksheet.delete_rows(start_row, count) + wb.save(filepath) + + return {"message": f"Deleted {count} row(s) starting at row {start_row} in sheet '{sheet_name}'"} + except (ValidationError, SheetError) as e: + logger.error(str(e)) + raise + except Exception as e: + logger.error(f"Failed to delete rows: {e}") + raise SheetError(str(e)) + +def delete_cols(filepath: str, sheet_name: str, start_col: int, count: int = 1) -> Dict[str, Any]: + """Delete one or more columns starting at the specified column.""" + try: + wb = load_workbook(filepath) + if sheet_name not in wb.sheetnames: + raise SheetError(f"Sheet '{sheet_name}' not found") + + worksheet = wb[sheet_name] + + # Validate parameters + if start_col < 1: + raise ValidationError("Start column must be 1 or greater") + if count < 1: + raise ValidationError("Count must be 1 or greater") + if start_col > worksheet.max_column: + raise ValidationError(f"Start column {start_col} exceeds worksheet bounds (max column: {worksheet.max_column})") + + worksheet.delete_cols(start_col, count) + wb.save(filepath) + + return {"message": f"Deleted {count} column(s) starting at column {start_col} in sheet '{sheet_name}'"} + except (ValidationError, SheetError) as e: + logger.error(str(e)) + raise + except Exception as e: + logger.error(f"Failed to delete columns: {e}") + raise SheetError(str(e))