Skip to main content
Glama
hyunjae-labs

xlwings Excel MCP Server

by hyunjae-labs

open_workbook

Open an Excel workbook to create a session for data manipulation, formatting, and worksheet management through native Excel integration.

Instructions

Open an Excel workbook and create a session.

Args:
    filepath: Path to Excel file
    visible: Whether to show Excel window (default: False)
    read_only: Whether to open in read-only mode (default: False)
    
Returns:
    Dictionary with session_id, filepath, visible, read_only, and sheets

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
filepathYes
visibleNo
read_onlyNo

Implementation Reference

  • MCP tool registration and handler for 'open_workbook'. Handles input validation, path resolution via get_excel_path, delegates to SESSION_MANAGER.open_workbook, retrieves session info and returns structured response with session details.
    @mcp.tool()
    def open_workbook(
        filepath: str,
        visible: bool = False,
        read_only: bool = False
    ) -> Dict[str, Any]:
        """
        Open an Excel workbook and create a session.
        
        Args:
            filepath: Path to Excel file
            visible: Whether to show Excel window (default: False)
            read_only: Whether to open in read-only mode (default: False)
            
        Returns:
            Dictionary with session_id, filepath, visible, read_only, and sheets
        """
        try:
            full_path = get_excel_path(filepath)
            session_id = SESSION_MANAGER.open_workbook(full_path, visible, read_only)
            
            # Get session info
            session = SESSION_MANAGER.get_session(session_id)
            if not session:
                raise WorkbookError(f"Failed to create session for {filepath}")
            
            return {
                "session_id": session_id,
                "filepath": session.filepath,
                "visible": session.visible,
                "read_only": session.read_only,
                "sheets": [sheet.name for sheet in session.workbook.sheets]
            }
            
        except Exception as e:
            logger.error(f"Error opening workbook: {e}")
            raise WorkbookError(f"Failed to open workbook: {str(e)}")
  • Core implementation of workbook opening in ExcelSessionManager.open_workbook. Manages session limits (LRU eviction), COM initialization, Excel app creation, file locking checks, workbook opening/creation, session object creation and storage, with proper error handling and cleanup.
    def open_workbook(self, filepath: str, visible: bool = False,
                     read_only: bool = False) -> str:
        """Open a workbook and create a new session"""
    
        # Generate session ID
        session_id = str(uuid.uuid4())
    
        # Check if we need to evict old sessions (LRU)
        with self._sessions_lock:
            if len(self._sessions) >= self._max_sessions:
                self._evict_lru_session()
    
        # Ensure COM is initialized for this thread (needed for auto-recovery in worker threads)
        _com_initialize()
    
        try:
            # Log session creation
            logger.debug(f"Creating session {session_id} for {filepath} (visible={visible}, read_only={read_only})")
    
            # Create Excel app instance
            app = xw.App(visible=visible, add_book=False)
            app.display_alerts = False
            app.screen_updating = not visible  # Disable screen updating for hidden instances
            
            # Open workbook
            abs_path = os.path.abspath(filepath)
            
            if os.path.exists(abs_path):
                # Check if file is locked before trying to open
                if not read_only and is_file_locked(abs_path):
                    app.quit()  # Clean up the app we just created
                    raise IOError(f"FILE_ACCESS_ERROR: '{abs_path}' is locked by another process. Use force_close_workbook_by_path() to force close it first.")
                
                wb = app.books.open(abs_path, read_only=read_only)
                logger.debug(f"Opened existing workbook: {abs_path}")
            else:
                # Create new workbook if doesn't exist
                wb = app.books.add()
                Path(abs_path).parent.mkdir(parents=True, exist_ok=True)
                wb.save(abs_path)
                logger.debug(f"Created new workbook: {abs_path}")
            
            # Create session
            session = ExcelSession(session_id, abs_path, app, wb, visible, read_only)
            
            # Store session
            with self._sessions_lock:
                self._sessions[session_id] = session
                logger.info(f"Session {session_id} created for {filepath} (total sessions: {len(self._sessions)})")
            
            return session_id
            
        except Exception as e:
            logger.error(f"Failed to create session for {filepath}: {e}")
            # Clean up on failure
            if 'app' in locals():
                try:
                    app.quit()
                except:
                    pass
            raise
  • Import of global SESSION_MANAGER singleton used by the open_workbook tool handler.
    from xlwings_mcp.session import SESSION_MANAGER
    from xlwings_mcp.force_close import force_close_workbook_by_path
  • Helper function to resolve relative filepaths to absolute paths based on SSE mode configuration.
    def get_excel_path(filename: str) -> str:
        """Get full path to Excel file.
        
        Args:
            filename: Name of Excel file
            
        Returns:
            Full path to Excel file
        """
        # If filename is already an absolute path, return it
        if os.path.isabs(filename):
            return filename
    
        # Check if in SSE mode (EXCEL_FILES_PATH is not None)
        if EXCEL_FILES_PATH is None:
            # Must use absolute path
            raise ValueError(f"Invalid filename: {filename}, must be an absolute path when not in SSE mode")
    
        # In SSE mode, if it's a relative path, resolve it based on EXCEL_FILES_PATH
        return os.path.join(EXCEL_FILES_PATH, filename)

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