MCP server for Excel automation via xlwings COM. Works with DRM-protected files by controlling the live Excel process.
This server demonstrates solid tool organization and schema coverage, placing it in the 'Fair' range. All 9 tools are explicitly defined with names, descriptions, and input schemas. Tool annotations (readOnlyHint/destructiveHint) are used correctly. However, there are consistent gaps: descriptions lack actionable context (e.g., error recovery paths), parameter descriptions in some tools are generic, output schemas are not documented, and there is no guidance on when/why to call each tool vs. alternatives. The 'manage_workbooks' and 'manage_sheets' tools combine multiple actions into one definition, which violates single-responsibility and forces LLMs to choose between sub-actions within a parameter enum. Error handling is minimal, no recovery guidance or error categorization is visible in the code.
Search for text in a sheet, optionally replacing it. Args: find: Text to search for. workbook: Workbook name or path. Defaults to active workbook. sheet: Sheet name. Defaults to active sheet. replace: Replacement text. If omitted, search only. match_case: Case-sensitive matching.
Apply formatting to a cell range. Args: cell_range: Range like 'A1:D10'. workbook: Workbook name or path. Defaults to active workbook. sheet: Sheet name. Defaults to active sheet. bold: Set bold. italic: Set italic. underline: Set underline. font_size: Font size in points. font_color: Hex colour like '#FF0000'. bg_color: Background hex colour like '#FFFF00'. number_format: Excel format like '#,##0.00'. alignment: 'left', 'center', 'right', 'justify'. wrap_text: Enable text wrapping. border: Apply thin borders.
Get the currently active workbook info including sheets, active sheet, and current selection address with its data.
Get all formulas in a range. Returns only cells that contain formulas. Args: cell_range: Range like 'A1:U99'. workbook: Workbook name or path. Defaults to active workbook. sheet: Sheet name. Defaults to active sheet. values_too: Include calculated values alongside formulas.
manage_workbooks combines 5 distinct actions ('list', 'open', 'save', 'close', 'recalculate') into one tool via an action enum. This violates single-responsibility and forces LLMs to choose between sub-actions. Should be split into separate tools: list_workbooks, open_workbook, save_workbook, close_workbook, recalculate_workbook.
manage_sheets combines 9 distinct actions ('list', 'add', 'delete', 'rename', 'copy', 'activate', 'insert_rows', 'delete_rows', 'insert_columns', 'delete_columns') into one tool via an action enum. This creates cognitive load and ambiguity for LLM tool selection. Should be split into separate tools: list_sheets, add_sheet, delete_sheet, rename_sheet, copy_sheet, activate_sheet, insert_rows, delete_rows, insert_columns, delete_columns.
Output schemas are not documented in any tool. While input schemas are present and properly typed, the expected return structure is not documented. LLMs cannot plan downstream calls or extract required fields without knowing what fields each tool returns (e.g., does read_data return 'data', 'headers', 'summary'? does get_active_workbook return 'sheets', 'active_sheet', 'selection'?).
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | D | 59 | 2026-07-28+ | v2 |
| 2026-03-09 | D | 50 | - | v1 |
Manage sheets and structure. Args: action: One of 'list', 'add', 'delete', 'rename', 'copy', 'activate', 'insert_rows', 'delete_rows', 'insert_columns', 'delete_columns'. workbook: Workbook name or path. Defaults to active workbook. sheet: Target sheet name (required for delete/rename/copy/activate). new_name: New name (for rename; optional for add/copy). position: Row/column number (1-based) for insert/delete actions. count: Number of rows/columns to insert or delete.
Manage Excel workbooks: list, open, save, close, or recalculate. Args: action: One of 'list', 'open', 'save', 'close', 'recalculate'. workbook: Workbook name or path. Defaults to active workbook. filepath: For 'open': file path (use 'new' for blank). For 'save': Save As path. read_only: For 'open': open in read-only mode. save: For 'close': save before closing.
Read data from an Excel range. When cell_range is omitted, returns a sheet summary (used range address, total rows/columns, headers) WITHOUT reading all data -- call again with a specific cell_range to fetch the actual data. Set detail=True on a single cell to get formula, type, and formatting info. Use sheet="*" to batch-read all sheets in one call. Args: workbook: Workbook name or path. Defaults to active workbook. sheet: Sheet name. Defaults to active sheet. Use '*' to read all sheets. cell_range: Range like 'A1:D10' or cell like 'B5'. Returns sheet summary if omitted. headers: Treat first row as column headers. detail: For single cells, include formula, type, number format, and font info. merge_info: Fill merged cells with the merge area's value instead of null. header_row: 1-based row number to use as headers (e.g. 3 means row 3 is headers).
Run a VBA macro in Excel and return its result. Args: macro_name: Macro name (e.g. 'MyMacro' or 'Module1.MyMacro'). workbook: Workbook name. If omitted, Excel resolves globally. args: Optional arguments to pass to the macro.
Write data or a formula to Excel cells. Provide 'data' for a 2D array, or 'formula' for a single-cell formula. Args: start_cell: Top-left cell (e.g. 'A1'). data: 2D list of values. Mutually exclusive with formula. formula: Excel formula like '=SUM(A1:A10)'. Mutually exclusive with data. workbook: Workbook name or path. Defaults to active workbook. sheet: Sheet name. Defaults to active sheet.
No error handling guidance. Tools raise ExcelError but provide no recovery paths (e.g., 'File not found. Check workbook name or use manage_workbooks(action=list) to see available workbooks'). Error responses should tell LLMs what to do next, not just fail.
Descriptions lack context on when/why to use each tool vs. alternatives. For example, read_data and get_formulas both operate on Excel ranges, but the distinction is not clear. Descriptions should explain the use case: 'read_data for cell values and structure; get_formulas for formula inspection.'
Parameter descriptions in manage_workbooks and manage_sheets are duplicative and generic (e.g., 'Workbook name or path. Defaults to active workbook.' appears in 6+ tools). Consider centralizing this convention in server instructions or using more specific language per tool.
No confirmation or dry-run pattern for destructive operations. Tools like write_data, delete_sheets, and delete_rows can destroy data, but there is no way to preview results or confirm before execution. LLMs can make mistakes, a confirm_before_execute or dry-run mode is essential.
No pagination or result-limiting guidance for read_data. If a sheet has 100,000 rows and an LLM calls read_data with sheet='*', the response could exhaust the context window. Tool should enforce reasonable limits (e.g., max 1000 rows per sheet, max 10 sheets) and return pagination hints.
Enum values in action parameters are inline in the description, not formalized as JSON Schema enums. For example, manage_workbooks.action lists 'list', 'open', 'save', 'close', 'recalculate' in text, not as a formal enum constraint. This makes it harder for clients to validate and offer auto-complete.