Skip to main content
Glama
hyunjae-labs

xlwings Excel MCP Server

by hyunjae-labs

close_workbook

Closes an Excel workbook session in xlwings Excel MCP Server, optionally saving changes before termination to ensure data integrity.

Instructions

Close a workbook session. Args: session_id: Session ID from open_workbook save: Whether to save changes (default: True) Returns: Success message

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
session_idYes
saveNo

Implementation Reference

  • MCP tool handler for 'close_workbook'. Calls SESSION_MANAGER.close_workbook and handles errors.
    @mcp.tool() def close_workbook( session_id: str, save: bool = True ) -> str: """ Close a workbook session. Args: session_id: Session ID from open_workbook save: Whether to save changes (default: True) Returns: Success message """ try: success = SESSION_MANAGER.close_workbook(session_id, save) if not success: raise WorkbookError(f"Session {session_id} not found") return f"Workbook session {session_id} closed successfully" except Exception as e: logger.error(f"Error closing workbook: {e}") raise WorkbookError(f"Failed to close workbook: {str(e)}")
  • Core implementation of closing workbook session in ExcelSessionManager. Handles cleanup, saving, and session removal.
    def close_workbook(self, session_id: str, save: bool = True) -> bool: """Close a workbook and remove session""" # Ensure COM is initialized for this thread _com_initialize() with self._sessions_lock: # Handle redirect mapping if exists actual_session_id = self._session_redirects.get(session_id, session_id) session = self._sessions.get(actual_session_id) if not session: logger.warning(f"Cannot close: session {session_id} not found") return False try: with session.lock: logger.debug(f"Closing session {session_id} (actual: {actual_session_id})") # Save and close workbook if session.workbook: if save and not session.read_only: session.workbook.save() session.workbook.close() # Quit Excel app if session.app: session.app.quit() # Remove from sessions del self._sessions[actual_session_id] # Clean up auto-recovery related data if session_id in self._expired_sessions: del self._expired_sessions[session_id] # Clean up redirect mappings redirect_keys_to_remove = [] for k, v in self._session_redirects.items(): if k == session_id or v == actual_session_id: redirect_keys_to_remove.append(k) for key in redirect_keys_to_remove: del self._session_redirects[key] logger.info(f"Session {session_id} closed permanently (remaining sessions: {len(self._sessions)})") return True except Exception as e: logger.error(f"Error closing session {session_id}: {e}") # Force remove from sessions even on error if actual_session_id in self._sessions: del self._sessions[actual_session_id] # Clean up recovery data on error too if session_id in self._expired_sessions: del self._expired_sessions[session_id] if session_id in self._session_redirects: del self._session_redirects[session_id] return False
  • Helper function for force closing workbook by path, used in error handling.
    def force_close_workbook_by_path(filepath: str) -> Dict[str, Any]: """ Force close a specific workbook from any running Excel process. Args: filepath: Absolute path to the workbook to close Returns: Dictionary with 'closed' (bool) and 'message' (str) """ if not PYWIN32_AVAILABLE: return { "closed": False, "message": "Force close not available (pywin32 not installed or not on Windows)" } # Normalize the file path target_path = os.path.abspath(filepath).lower() try: # Initialize COM for this thread pythoncom.CoInitialize() found = False closed = False try: # Try to connect to running Excel instance xl = win32com.client.GetObject(Class="Excel.Application") # Check all open workbooks for wb in xl.Workbooks: try: # Compare full paths (case-insensitive on Windows) wb_path = os.path.abspath(wb.FullName).lower() if wb_path == target_path: logger.info(f"Found workbook to force close: {wb.FullName}") found = True # Force close without saving wb.Close(SaveChanges=False) closed = True logger.info(f"Successfully force closed: {filepath}") break except Exception as e: logger.warning(f"Error checking/closing workbook: {e}") continue # If no workbooks remain, optionally quit Excel if closed and xl.Workbooks.Count == 0: try: xl.Quit() logger.info("Excel application quit (no remaining workbooks)") except: pass except Exception as e: # No Excel instance running or other COM error logger.debug(f"Could not connect to Excel: {e}") return { "closed": False, "message": f"No Excel instance found or cannot connect: {str(e)}" } finally: # Uninitialize COM pythoncom.CoUninitialize() if not found: return { "closed": False, "message": f"Workbook not found in any Excel instance: {filepath}" } return { "closed": closed, "message": f"Successfully force closed workbook: {filepath}" } except Exception as e: logger.error(f"Force close failed for {filepath}: {e}") return { "closed": False, "message": f"Force close failed: {str(e)}" }
  • The @mcp.tool() decorator registers this function as the MCP tool named 'close_workbook'.
    @mcp.tool() def close_workbook( session_id: str, save: bool = True ) -> str: """ Close a workbook session. Args: session_id: Session ID from open_workbook save: Whether to save changes (default: True) Returns: Success message """ try: success = SESSION_MANAGER.close_workbook(session_id, save) if not success: raise WorkbookError(f"Session {session_id} not found") return f"Workbook session {session_id} closed successfully" except Exception as e: logger.error(f"Error closing workbook: {e}") raise WorkbookError(f"Failed to close workbook: {str(e)}")

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/hyunjae-labs/xlwings-mcp-server'

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