ExceLLM - MCP server for Excel live automation with LLM safety guardrails
Project description
ExceLLM: Excel Live MCP Server
A Model Context Protocol (MCP) server for Excel automation with dual-engine support. Enables LLMs (Claude, ChatGPT, Cursor, etc.) to interact with Excel files through natural language - live on Windows or file-based cross-platform.
Features
- ✅ Dual-Engine Architecture: Live Excel (Windows COM) or file-based (cross-platform)
- ✅ 34 MCP Tools: Comprehensive Excel automation toolkit
- ✅ Real-Time Excel Operations: Work with files open in Excel (Windows)
- ✅ Cross-Platform File Mode: Work with .xlsx files on Windows, Mac, Linux
- ✅ Charts & Pivot Tables: Native Excel chart and pivot table creation
- ✅ VBA Execution: Execute custom macros (Windows only, disabled by default)
- ✅ Screen Capture: Visual verification of changes (Windows only)
- ✅ Excel Tables: Create, list, delete table objects
- ✅ Cell Merging: Merge, unmerge, and query merged cells
- ✅ Formula Validation: Validate syntax before applying
- ✅ Session Management: Process large datasets with chunking
- ✅ Advanced Search & Filtering: Find and filter data efficiently
- ✅ LLM-Optimized: Workflow guidance and structured responses
Prerequisites
For Live Excel Mode (Windows)
- Windows OS (required for COM automation)
- Microsoft Excel installed and running
- Python 3.10 or higher
pywin32library for Windows COM automation- At least one workbook open in Excel
For File Mode (Cross-Platform)
- Any OS: Windows, Mac, or Linux
- Python 3.10 or higher
openpyxllibrary for file operations- No Excel required
Installation
From PyPI (Recommended)
pip install excellm
From Source
cd ExceLLM
pip install -e .
Development Installation
cd ExceLLM
pip install -e ".[dev]"
Usage
Running the Server
python -m excellm
The server will start and listen for MCP client connections using stdio transport.
MCP Client Integration
Claude Desktop
Windows Configuration:
Create or edit %APPDATA%\Claude\claude_desktop_config.json:
{
"mcpServers": {
"ExceLLM": {
"command": "python",
"args": [
"-m",
"excellm"
],
"description": "Real-time Excel automation for open files"
}
}
}
macOS Configuration:
Create or edit ~/Library/Application Support/Claude/claude_desktop_config.json:
{
"mcpServers": {
"ExceLLM": {
"command": "python3",
"args": [
"-m",
"excellm"
],
"description": "Real-time Excel automation for open files"
}
}
}
Important:
- Replace python with full path if needed (e.g.,
C:\\Python311\\python.exe) - Use double backslashes
\\for Windows paths - Restart Claude Desktop after making changes
Cursor AI Editor
Open Cursor Settings → MCP and add:
{
"mcpServers": {
"ExceLLM": {
"command": "python",
"args": ["-m", "excellm"]
}
}
}
ChatGPT (with MCP support)
Configure in ChatGPT's MCP settings similarly to above.
Available Tools
🔍 Inspection (Start Here)
1. inspect_workbook()
Fast workbook-level radar. Returns sheet names, visibility, and "scent" of data without reading cells.
Usage: await inspect_workbook()
2. explore(scope, mode="quick")
Sheet-level analysis. Detects used range, labeled regions, and layout.
Usage: await explore({"sheet": "Sheet1"}, mode="deep")
📖 Reading & Navigation
3. list_open_workbooks()
List all open workbooks and their sheets.
Usage: await list_open_workbooks()
4. read(workbook_name, sheet_name, reference, batch, max_rows)
Read cells or ranges. Supports single range OR efficient batch reading.
Usage: await read("data.xlsx", "Sheet1", "A1:D10")
Batch: await read("data.xlsx", batch=[{"sheet": "S1", "range": "A1"}, {"range": "B2"}])
Pagination: await read("data.xlsx", "Sheet1", max_rows=100) — limits rows to prevent token explosion
5. search(workbook_name, filters, ..., max_rows)
Filter data server-side before returning to LLM.
Usage: await search("data.xlsx", {"Column": "Status", "Value": "Active"})
Pagination: await search("data.xlsx", "active", max_rows=50) — limits matching rows
6. get_unique_values(workbook_name, sheet_name, range)
Get unique values and counts from a column.
Usage: await get_unique_values("data.xlsx", "Sheet1", "A:A")
7. get_current_selection()
Get the currently selected cell/range in the active window.
Usage: await get_current_selection()
8. select_range(workbook_name, sheet_name, reference)
Visually select a range in the Excel UI.
Usage: await select_range("data.xlsx", "Sheet1", "A1:B10")
🕒 History & Changes
9. get_recent_changes(limit=10)
Get the history of recent user actions from both Undo and Redo stacks.
Usage: await get_recent_changes(limit=5)
Returns: {"undo_history": [...], "redo_history": [...]}
✍️ Writing & Editing
10. write(workbook_name, sheet_name, reference, data, ...)
Write values. Supports single cells or 2D arrays. Includes safety checks.
Usage: await write("data.xlsx", "Sheet1", "A1", "Hello")
11. copy_range(source_workbook, source_sheet, source_range, target_sheet, ...)
Copy data between locations, preserving formatting.
Usage: await copy_range("data.xlsx", "Sheet1", "A1:A10", target_sheet="Sheet2")
12. find_replace(workbook_name, find_value, replace_value, ...)
Find and replace text.
Usage: await find_replace("data.xlsx", "Old", "New")
13. sort_range(workbook_name, sheet_name, range, sort_by)
Sort data by multiple columns.
Usage: await sort_range("data.xlsx", "Sheet1", "A1:D50", [{"column": "A", "order": "asc"}])
🎨 Formatting
14. format(workbook_name, sheet_name, reference, style, format)
Apply styles (color, bold, number format) to ranges.
Usage: await format("data.xlsx", "Sheet1", "A1", style="header")
15. get_format(workbook_name, sheet_name, reference)
Read formatting properties of a range.
Usage: await get_format("data.xlsx", "Sheet1", "A1")
16. merge_cells(workbook_name, sheet_name, start_cell, end_cell)
Merge a range of cells.
Usage: await merge_cells("data.xlsx", "Sheet1", "A1", "D1")
17. unmerge_cells(workbook_name, sheet_name, start_cell, end_cell)
Unmerge previously merged cells.
Usage: await unmerge_cells("data.xlsx", "Sheet1", "A1", "D1")
18. get_merged_cells(workbook_name, sheet_name)
List all merged cell ranges in a sheet.
Usage: await get_merged_cells("data.xlsx", "Sheet1")
💡 Conditional Formatting: The
formattool now supportsconditional_formatparameter:
- ColorScale:
{type: "colorScale", min_color: "FF0000", max_color: "00FF00"}- DataBar:
{type: "dataBar", bar_color: "638EC6"}- IconSet:
{type: "iconSet", icon_style: "3trafficlights"}- CellIs:
{type: "cellIs", operator: "greaterThan", value: 100, fill_color: "FFEB9C"}
📋 Sheet & Structure Management
19. manage_sheet(workbook_name, action, sheet_name, ...)
Add, rename, delete, hide, copy, or move worksheets.
Usage: await manage_sheet("data.xlsx", action="add", sheet_name="NewSheet")
20. insert(workbook_name, sheet_name, insert_type, position, count)
Insert rows or columns.
Usage: await insert("data.xlsx", "Sheet1", "row", "5", count=2)
21. delete(workbook_name, sheet_name, delete_type, position, count)
Delete rows or columns.
Usage: await delete("data.xlsx", "Sheet1", "column", "C")
📊 Excel Tables
22. create_table(workbook_name, sheet_name, range_ref, table_name)
Convert a range into an official Excel Table (ListObject).
Usage: await create_table("data.xlsx", "Sheet1", "A1:D10", "SalesTable")
23. list_tables(workbook_name)
List all tables in the workbook.
Usage: await list_tables("data.xlsx")
24. delete_table(workbook_name, sheet_name, table_name, keep_data)
Remove table structure, optionally keeping data.
Usage: await delete_table("data.xlsx", "Sheet1", "SalesTable")
📈 Charts & Pivot Tables
25. create_chart(workbook_name, sheet_name, data_range, chart_type, target_cell, ...)
Create charts (line, bar, pie, scatter, area) from data.
- Live Mode: Native Excel chart automation.
- File Mode: Basic chart creation via openpyxl.
Usage:
await create_chart("data.xlsx", "Sheet1", "A1:D10", "bar", "F1", title="Sales")
26. create_pivot_table(workbook_name, sheet_name, data_range, rows, values, ...)
Create pivot tables with aggregation.
- Live Mode: Native interactive Excel pivot table.
- File Mode: Static summary table (calculated in Python).
Usage:
await create_pivot_table("data.xlsx", "Sheet1", "A1:D100", rows=["Category"], values=["Amount"], agg_func="sum")
⚙️ Advanced Features
27. execute_vba(workbook_name, vba_code)
Run custom VBA macros (Windows only).
🔒 Security: Disabled by default. Set EXCELLM_ENABLE_VBA=true to enable.
Usage: await execute_vba("data.xlsx", "Range('A1').Value = 'VBA'")
28. capture_sheet(workbook_name, sheet_name, range_ref)
Take a screenshot of a range (Windows only).
Usage: await capture_sheet("data.xlsx", "Sheet1", "A1:H10")
29. validate_cell_reference(cell)
Utility to check if a reference string is valid.
Usage: await validate_cell_reference("A1")
30. validate_formula(formula)
Validate Excel formula syntax, check for errors, and get correction suggestions.
Usage: await validate_formula("=SUM(A1:A10)")
🚀 Big Data Sessions (Stateful)
For handling large datasets (>50 rows) safely.
31. create_transform_session(...)
Start a session to process data in chunks.
Usage: await create_transform_session("data.xlsx", "Sheet1", "A", "B")
32. process_chunk(session_id, data)
Submit processed data for the current chunk.
Usage: await process_chunk("session_123", [[1, 2], [3, 4]])
33. get_session_status(session_id)
Check progress of a session.
Usage: await get_session_status("session_123")
34. create_parallel_sessions(...)
Split work for parallel sub-agents.
Usage: await create_parallel_sessions("data.xlsx", "Sheet1", "A", "B")
Example Usage:
User: Replace all "N/A" with "Not Available" in Sheet1
LLM: [Calls find_replace("data.xlsx", "N/A", "Not Available", sheet_name="Sheet1")]
✓ Found 15 matches, replaced 15 values
User: How many cells contain "error"? Don't replace yet.
LLM: [Calls find_replace("data.xlsx", "error", "", preview_only=True)]
Found 7 cells containing "error" (preview mode, no changes made)
Common Workflows
📊 Recommended Workflow Patterns
ExceLLM tools include workflow guidance markers (🔍, ✍️, ⚙️, 📸, 📊) to help LLMs use tools in the correct order.
Pattern 1: Data Analysis Workflow
Recommended Order:
- 🔍 Inspect → Understand workbook/sheet structure
- 📖 Read → Get data from identified regions
- 📊 Process → Analyze data
- ✍️ Write → Write results back
- 📸 Verify (optional) → Visual validation
Example:
User: Analyze sales data in data.xlsx and write summary
LLM Workflow:
1. inspect_workbook()
→ Identifies sheets, finds "Sales" sheet
2. explore({"sheet": "Sales"}, mode="quick")
→ Detects data in A1:D100, headers present
3. read("data.xlsx", "Sales", "A1:D100")
→ Reads all sales data
4. [Analysis] → Calculates totals, averages
5. write("data.xlsx", "Summary", "A1:C5", summary_data)
→ Writes analysis to Summary sheet
6. capture_sheet("data.xlsx", "Summary") [OPTIONAL]
→ Screenshots for validation
Pattern 2: Data Transformation (Large Datasets)
For datasets > 25 rows:
- 🔍 Explore → Understand data structure
- 🎯 Create Session → Start stateful processing
- 🔄 Process Chunks → Iterate through chunks
- ✅ Verify → Check session status
Example:
User: Extract PO numbers from 500 rows of messy text
LLM Workflow:
1. explore({"sheet": "Data"}, mode="deep")
→ Identifies 500 rows in column A
2. create_transform_session(
workbook_name="data.xlsx",
sheet_name="Data",
source_column="A",
output_columns="B:D",
start_row=2,
chunk_size=25
)
→ Session created, first chunk received
3. process_chunk(session_id, transformed_data)
→ Process chunk 1 (rows 2-26)
→ Server returns next chunk automatically
4. process_chunk(session_id, transformed_data)
→ Process chunk 2 (rows 27-51)
→ Continue until complete
5. get_session_status(session_id)
→ Verify all 500 rows processed
Pattern 3: Formatting & Styling
Recommended Order:
- 📖 Read/Explore → Identify target range
- ✍️ Write → Write data if needed
- 🎨 Format → Apply formatting
- 📊 Create Table (optional) → Convert to Excel table
- 📸 Capture (optional) → Visual verification
Example:
User: Create a formatted sales table with styling
LLM Workflow:
1. write("data.xlsx", "Sheet1", "A1:D100", sales_data)
→ Write raw data
2. format("data.xlsx", "Sheet1", "A1:D1", style="header")
→ Format header row
3. format("data.xlsx", "Sheet1", "B2:D100",
format={"numberFormat": "$#,##0.00"})
→ Currency formatting for amounts
4. create_table("data.xlsx", "Sheet1", "A1:D100",
"SalesData", table_style="medium9")
→ Convert to Excel table with filters
5. capture_sheet("data.xlsx", "Sheet1", "A1:D100")
→ Screenshot for validation
Pattern 4: Advanced Operations (VBA)
⚠️ USE WITH CAUTION - Only when standard tools are insufficient
Recommended Order:
- 🔍 Explore → Understand current state
- ⚙️ Execute VBA → Run custom macro
- 📸 Capture → Verify results visually
Example:
User: Apply complex conditional formatting that requires VBA
LLM Workflow:
1. explore({"sheet": "Data"})
→ Understand data layout
2. execute_vba("data.xlsx", '''
Dim ws As Worksheet
Set ws = ActiveSheet
' Complex conditional formatting
ws.Range("A1:D100").FormatConditions.Add ...
ws.Range("A1:D100").FormatConditions(1).Interior.Color = RGB(255,200,200)
''')
→ Execute VBA for complex operation
3. capture_sheet("data.xlsx", "Data", "A1:D100")
→ Verify formatting applied correctly
Workflow 1: Quick Data Update
1. List workbooks → identify target file
2. Read current cell value
3. Calculate/update value
4. Write new value back
5. Save workbook
Example:
User: Find all cells in column A that are empty in data.xlsx and fill them with "N/A"
LLM: [Chains multiple tool calls]
1. list_open_workbooks() - find data.xlsx
2. read_range("data.xlsx", "Sheet1", "A1:A100") - get values
3. [Processing] - identify empty cells
4. write_range() - write "N/A" to empty cells
5. save_workbook("data.xlsx") - save changes
✓ Filled 15 empty cells with "N/A"
Workflow 2: Data Analysis
1. Read range of data
2. Analyze data patterns
3. Calculate statistics
4. Write summary to Excel
Example:
User: Analyze the sales data in data.xlsx and write a summary to the Summary sheet
LLM: [Chains tools]
1. read_range("data.xlsx", "Sheet1", "A2:D100") - get sales
2. [Analysis] - calculates total, average, max/min
3. write_range("data.xlsx", "Summary", "A1:C5", [summary data])
4. save_workbook("data.xlsx")
✓ Analysis complete. Summary written to Summary sheet.
Workflow 3: Cell-by-Cell Validation
1. Read a cell
2. Validate format
3. Update status in another cell
Example:
User: Validate all email addresses in column B and mark invalid ones in column C
LLM: [Iterative workflow]
✓ Validated 50 email addresses
✓ Marked 3 invalid emails in column C
🌍 Cross-Platform Support
ExceLLM now supports two operation modes:
Live Excel Mode (Windows + COM)
- Platform: Windows only
- Requires: Excel running with workbook open
- Features: Full feature set (VBA, screen capture, tables, etc.)
- Use when: Working with open Excel files on Windows
File Mode (Cross-platform)
- Platform: Windows, Mac, Linux
- Requires: openpyxl library (no Excel needed)
- Features: Core operations + Charts + Pivot Summaries
- Use when: Working with closed .xlsx files, or on Mac/Linux
Auto-Detection:
- Provide file path (e.g.,
C:/data/file.xlsx) → File mode - Provide workbook name (e.g.,
data.xlsx) → Live mode (if Excel running)
Example:
# File mode (works anywhere)
await read(workbook_path="/Users/me/Documents/report.xlsx", ...)
# Live mode (Windows + Excel)
await read(workbook_name="report.xlsx", ...)
Tool Reference Guide
🔍 Inspection Tools (STEP 1 - Use First)
inspect_workbook()- Fast workbook overviewexplore()- Sheet-level analysis (quick/deep modes)
📖 Read Operations & Navigation
list_open_workbooks()- List all open workbooksread()- Read cells/ranges with filtering and paginationsearch()- Find and filter data with paginationget_unique_values()- Extract unique valuesget_current_selection()- Get active cellselect_range()- Visually select a rangeget_recent_changes()- Get Undo/Redo history
✍️ Write Operations
write()- Write with safety guardrailscopy_range()- Copy with formattingsort_range()- Multi-column sortingfind_replace()- Find and replace with preview
🎨 Formatting & Cells
format()- Apply predefined or custom formatsget_format()- Read formatting detailsmerge_cells()- Merge a range of cellsunmerge_cells()- Unmerge a range of cellsget_merged_cells()- List all merged cell ranges
📋 Sheet Management
manage_sheet()- Add, remove, hide, copy, renameinsert()- Insert rows/columnsdelete()- Delete rows/columns
📊 Tables & Charts
create_table()- Create Excel table objectslist_tables()- List all tablesdelete_table()- Remove tablescreate_chart()- Create native chartscreate_pivot_table()- Create interactive pivot tables
⚙️ Advanced & Utilities
execute_vba()- Execute VBA macros (Windows only)capture_sheet()- Screenshot capture (Windows only)validate_cell_reference()- Check reference syntaxvalidate_formula()- Validate formula syntax
🎯 Session Management (For Large Datasets)
create_transform_session()- Start stateful processingprocess_chunk()- Process data chunksget_session_status()- Check progresscreate_parallel_sessions()- Multi-threaded processing
💡 Best Practices
1. Always Inspect First
❌ DON'T: Immediately read/write without understanding structure
✅ DO: inspect_workbook() or explore() first
2. Use Safety Features
❌ DON'T: write() with force_overwrite=True by default
✅ DO: Use verify_source parameter for data transformations
3. Chunk Large Datasets
❌ DON'T: Process 500+ rows in one write() call
✅ DO: Use create_transform_session() for >25 rows
4. VBA as Last Resort
❌ DON'T: Use execute_vba() for simple operations
✅ DO: Try standard tools first, VBA only when necessary
5. Verify Visual Changes
❌ DON'T: Trust formatting changes blindly
✅ DO: Use capture_sheet() to verify complex formatting
6. Use Pagination for Large Reads
❌ DON'T: Read 10,000 rows without limits
✅ DO: Use max_rows parameter to limit token usage
await read("data.xlsx", "Sheet1", max_rows=100)
Audit Logging
All write operations are logged for debugging and accountability:
2026-01-05 11:40:00 | WRITE | write_range | data.xlsx | Sheet1 | A1:D10 | 40 cells
2026-01-05 11:40:01 | DRY_RUN | write_cell | data.xlsx | Sheet1 | A1 | 1 cells
Logs are written to stderr and include:
- Timestamp
- Operation type (WRITE or DRY_RUN)
- Tool name
- Workbook, sheet, and range
- Number of cells affected
Troubleshooting
"Could not connect to Excel. Is Excel running?"
Solution:
- Open Microsoft Excel
- Open at least one workbook
- Ensure Excel is not in a dialog/macro execution that blocks COM access
"Worksheet 'SheetName' is protected"
Solution:
- Unprotect the worksheet in Excel
- Go to: Review → Unprotect Sheet
- Remove password if prompted
"Workbook 'file.xlsx' is read-only"
Solution:
- Close the workbook
- Open it with write permissions
- Right-click file → Properties → Uncheck "Read-only"
"Invalid cell reference: 'A1B2'"
Solution:
- Use proper Excel format: A1, B5, Z100, AA123
- Valid: 1-3 letters + 1-7 digits
- Invalid: 1A, A, A1B2, AAA99999
"Server not showing up in Claude Desktop"
Solution:
- Verify
claude_desktop_config.jsonis valid JSON - Use absolute paths in configuration
- Use double backslashes
\\for Windows paths - Completely quit and restart Claude Desktop (close tray icon too)
- Check Claude logs:
~/Library/Logs/Claude/mcp.log(macOS) or%LOCALAPPDATA%\Claude\mcp.log(Windows)
MCP Server Won't Start
Possible Causes:
- Python not in PATH
- Dependencies not installed
- Excel not installed
Solutions:
# Check Python version
python --version # Should be 3.10+
# Install dependencies
pip install -r requirements.txt
# Test Excel connection manually
python -c "import win32com.client; win32com.client.Dispatch('Excel.Application')"
Architecture
ExceLLM/
├── src/
│ └── excellm/
│ ├── __init__.py # Package init
│ ├── __main__.py # Module entry point
│ ├── server.py # Main MCP server with 34 tools
│ ├── config.py # Configuration management
│ ├── excel_session.py # Excel COM session manager
│ ├── validators.py # Input validation utilities
│ ├── filters.py # Filter engine for search
│ ├── core/ # Shared foundation
│ │ ├── __init__.py
│ │ ├── connection.py # COM pooling, batch reads
│ │ ├── errors.py # ToolError, ErrorCodes
│ │ ├── audit.py # Operation logging and tracking
│ │ ├── utils.py # Consolidated utilities
│ │ ├── engine.py # Engine abstraction layer
│ │ ├── com_engine.py # COM engine implementation
│ │ └── file_engine.py # File-based engine implementation
│ ├── tools/ # Tool implementations
│ │ ├── readers.py # read operations
│ │ ├── writers.py # write operations
│ │ ├── formatters.py # format, get_format
│ │ ├── sheet_mgmt.py # manage_sheet, insert, delete
│ │ ├── range_ops.py # copy_range, sort_range, find_replace
│ │ ├── search.py # search with filters
│ │ ├── workbook.py # list_workbooks, select_range
│ │ ├── chart.py # chart creation
│ │ ├── pivot.py # pivot table operations
│ │ ├── history.py # undo/redo history
│ │ ├── session.py # transform sessions
│ │ ├── table_ops.py # Excel table operations
│ │ ├── screen_capture.py # screenshot capture
│ │ └── vba_execution.py # VBA macro execution
│ └── inspection/ # Sheet/workbook inspection
│ ├── __init__.py
│ ├── explore.py # Sheet-level radar
│ ├── inspect_workbook.py
│ ├── types.py # Pydantic schemas
│ └── utils.py
├── tests/ # Unit and integration tests
├── requirements.txt # Dependencies
├── pyproject.toml # Package configuration
└── README.md # This file
Key Components
-
FastMCP Server (
server.py):- Provides 34 MCP tools
- Handles tool registration and routing
- Manages server lifecycle
- Dual-engine architecture support (COM + File)
- Centralized error handling
-
Core Module (
core/):- connection.py: Thread-local COM connection pooling, batch range reads for performance
- errors.py: Centralized error handling (ToolError, ErrorCodes)
- audit.py: Operation logging and tracking for debugging
- utils.py: Consolidated utility functions
- engine.py: Engine abstraction layer for cross-platform support
- com_engine.py: Windows COM engine implementation for live Excel operations
- file_engine.py: Cross-platform file-based engine using openpyxl
-
Tools Module (
tools/):- readers.py: Read operations with filtering and batch support
- writers.py: Write operations with safety checks
- formatters.py: Format, get_format, merge/unmerge cells
- sheet_mgmt.py: manage_sheet, insert, delete operations
- range_ops.py: copy_range, sort_range, find_replace
- search.py: Server-side search with advanced filters
- workbook.py: list_workbooks, select_range operations
- chart.py: Chart creation (line, bar, pie, scatter, area)
- pivot.py: Pivot table operations with aggregation
- history.py: Undo/redo history tracking
- session.py: Transform sessions for large datasets
- table_ops.py: Excel table operations (create, list, delete)
- screen_capture.py: Screenshot capture (Windows only)
- vba_execution.py: VBA macro execution (Windows only)
-
Inspection Module (
inspection/):- explore.py: Sheet-level analysis with quick/deep modes
- inspect_workbook.py: Fast workbook-level radar
- types.py: Pydantic schemas for type safety
- utils.py: Inspection utilities
-
ExcelSessionManager (
excel_session.py):- Connects to running Excel instance (Windows)
- Wraps COM operations with async support
- Provides thread-safe access to Excel
- Handles Excel COM lifecycle
-
Configuration (
config.py):- Centralized configuration management
- Environment variable support
- Default settings and overrides
-
Validators (
validators.py):- Cell reference format validation
- Workbook/sheet name validation
- Range parsing and validation
- Value type checking
-
Filters (
filters.py):- Server-side filtering engine
- Advanced search capabilities
- Multiple filter types support
Development
Running Tests
# Install dev dependencies
pip install -e ".[dev]"
# Run tests
pytest
# Run with coverage
pytest --cov=src/excellm
Code Quality
# Format code
black src/
# Lint code
ruff check src/
# Type check
mypy src/
Limitations
Live Excel Mode (COM Engine)
- Windows Only: Requires Windows OS for COM automation
- Excel Must Be Running: Cannot open files directly, works with open files only
- Single Excel Instance: Connects to first running Excel instance
- VBA Access: Requires "Trust access to VBA project object model" enabled for VBA execution
File Mode (openpyxl Engine)
- Limited Formatting: Basic font, fill, and borders only
- No VBA: Cannot execute macros
- No Screen Capture: Cannot generate screenshots
- No Conditional Formatting: Not supported (COM only)
- Charts: Supported (5 types)
- Pivot Tables: Static summary tables only (no drill-down)
General
- Large Datasets: For best performance, use session management for >100 rows
- File Corruption: Always backup important files before automation
Security Considerations
- Tool calls require user approval in most MCP clients
- No remote API calls - local COM operations only
- Read/write operations limited to opened workbooks
- Cell validation prevents malicious input
VBA Execution Security
VBA is disabled by default for security. VBA code runs with full Excel/COM privileges and can:
- Modify files on disk
- Access system resources
- Execute arbitrary code
To enable VBA execution:
# Environment variable
set EXCELLM_ENABLE_VBA=true
# Or in .env file
EXCELLM_ENABLE_VBA=true
⚠️ Warning: Only enable VBA in trusted environments where you control the input.
Contributing
Contributions are welcome! Please:
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests if applicable
- Submit a pull request
License
MIT License - See LICENSE file for details
Support
For issues, questions, or contributions:
- GitHub Issues: Create an issue
- Documentation: Read the docs
Acknowledgments
- MCP Team: For the Model Context Protocol
- pywin32: For Windows COM automation
- openpyxl: For cross-platform Excel file operations
- FastMCP: For the excellent MCP server framework
Version History
1.1.0 (2026-01-05)
- New Features:
- Configuration management system (config.py)
- Audit logging for operation tracking (core/audit.py)
- Dual-engine architecture with COM and File engines
- Engine abstraction layer for cross-platform support
- Improvements:
- Enhanced error handling and validation
- Performance optimizations with batch reads and connection pooling
- Updated documentation with complete architecture
- All 34 MCP tools improved with better error messages
- Documentation:
- Complete Architecture section with all modules documented
- Updated Key Components with 8 comprehensive sections
1.0.0-alpha (2026-01-04)
- Initial alpha release
- 34 MCP tools for Excel automation
- Dual-engine architecture (COM + File-based)
- Cross-platform support (Windows, Mac, Linux)
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file excellm-1.2.0.tar.gz.
File metadata
- Download URL: excellm-1.2.0.tar.gz
- Upload date:
- Size: 121.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
889f0674098d582d51c7091d6b57cf6690c007cf9aa4bb0957ed8a36ca6c57aa
|
|
| MD5 |
7b0811856350ef9fd3b04927410ef216
|
|
| BLAKE2b-256 |
43804f2a80ccd8e94bfef385e68b2377e2ad6b43b1edc321aa4090afad2a61f7
|
Provenance
The following attestation bundles were made for excellm-1.2.0.tar.gz:
Publisher:
publish.yml on mroshdy91/Excellm
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
excellm-1.2.0.tar.gz -
Subject digest:
889f0674098d582d51c7091d6b57cf6690c007cf9aa4bb0957ed8a36ca6c57aa - Sigstore transparency entry: 797928977
- Sigstore integration time:
-
Permalink:
mroshdy91/Excellm@3a2e3ffa78c36991a07834d88e6f6367929386dc -
Branch / Tag:
refs/tags/v1.2.0 - Owner: https://github.com/mroshdy91
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@3a2e3ffa78c36991a07834d88e6f6367929386dc -
Trigger Event:
release
-
Statement type:
File details
Details for the file excellm-1.2.0-py3-none-any.whl.
File metadata
- Download URL: excellm-1.2.0-py3-none-any.whl
- Upload date:
- Size: 130.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
20509309b00a686286ce90b106b69f88364abeda4634ca62bbaa1913006800c2
|
|
| MD5 |
bffcdf035828a52b7f8e4b8637005d96
|
|
| BLAKE2b-256 |
81a4b519811d3394eabee9a1fec840d64aaf453bd02848b2ec0f525a55e0810a
|
Provenance
The following attestation bundles were made for excellm-1.2.0-py3-none-any.whl:
Publisher:
publish.yml on mroshdy91/Excellm
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
excellm-1.2.0-py3-none-any.whl -
Subject digest:
20509309b00a686286ce90b106b69f88364abeda4634ca62bbaa1913006800c2 - Sigstore transparency entry: 797928983
- Sigstore integration time:
-
Permalink:
mroshdy91/Excellm@3a2e3ffa78c36991a07834d88e6f6367929386dc -
Branch / Tag:
refs/tags/v1.2.0 - Owner: https://github.com/mroshdy91
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@3a2e3ffa78c36991a07834d88e6f6367929386dc -
Trigger Event:
release
-
Statement type: