Skip to main content

Excel MCP Server for manipulating Excel files

Project description

Excel MCP Server Logo

PyPI version Total Downloads License: MIT Install MCP Server

A Model Context Protocol (MCP) server that lets you manipulate Excel files without needing Microsoft Excel installed. Create, read, and modify Excel workbooks with your AI agent.

Features

  • 📊 Excel Operations: Create, read, update workbooks and worksheets
  • 📈 Data Manipulation: Formulas, formatting, charts, pivot tables, and Excel tables
  • 🔍 Data Validation: Built-in validation for ranges, formulas, and data integrity
  • 🎨 Formatting: Font styling, colors, borders, alignment, and conditional formatting
  • 📋 Table Operations: Create and manage Excel tables with custom styling
  • 📊 Chart Creation: Generate various chart types (line, bar, pie, scatter, etc.)
  • 🔄 Pivot Tables: Create dynamic pivot tables for data analysis
  • 🔧 Sheet Management: Copy, rename, delete worksheets with ease
  • 🔌 Triple transport support: stdio, SSE (deprecated), and streamable HTTP
  • 🌐 Remote & Local: Works both locally and as a remote service

Development and CI parity

Install dev extras so local runs match PR and release gates (docs/architecture/ci-cd-packaging-governance.md):

pip install -e ".[dev]"
python -m pytest
hatch build
python -m twine check dist/*

From the repository root with uv (uses uv.lock if present):

uv sync --extra dev
uv run python -m pytest
uv run hatch build
uv run python -m twine check dist/*

The PyPI distribution name is excel-com-mcp (same as [project].name in pyproject.toml). A legacy console entrypoint excel-mcp-server is also installed. Examples below use excel-com-mcp for uvx and MCP JSON so they stay aligned with manifest.jsonserver.mcp_config (command / args).

Usage

The server supports three transport methods:

1. Stdio Transport (for local use)

uvx excel-com-mcp stdio
{
   "mcpServers": {
      "excel": {
         "command": "uvx",
         "args": ["excel-com-mcp", "stdio"]
      }
   }
}

Local clone in Cursor (this repo): MCP often starts uv with no project working directory, so uv run --extra com … fails with *“--extra com has no effect when used outside of a project* and *program not found*. Pass the project explicitly with **--project** (absolute path to the folder that contains pyproject.toml`):

{
   "mcpServers": {
      "excel-mcp-local": {
         "command": "uv",
         "args": [
            "run",
            "--project",
            "C:/Users/YOU/mcp/excel-mcp-server",
            "--extra",
            "com",
            "excel-com-mcp",
            "stdio"
         ]
      }
   }
}

On Windows you can use C:\\\\Users\\\\YOU\\\\... instead of forward slashes. Omit "com" on non-Windows installs. You can add "cwd" with the same path as a hint for other tools, but --project is what fixes uv run.

2. SSE Transport (Server-Sent Events - Deprecated)

uvx excel-com-mcp sse

SSE transport connection:

{
   "mcpServers": {
      "excel": {
         "url": "http://localhost:8000/sse",
      }
   }
}

3. Streamable HTTP Transport (Recommended for remote connections)

uvx excel-com-mcp streamable-http

Streamable HTTP transport connection:

{
   "mcpServers": {
      "excel": {
         "url": "http://localhost:8000/mcp",
      }
   }
}

Environment Variables & File Path Handling

SSE and Streamable HTTP Transports

When running the server with the SSE or Streamable HTTP protocols, you must set the EXCEL_FILES_PATH environment variable on the server side. This variable tells the server where to read and write Excel files.

  • If not set, it defaults to ./excel_files.
  • With these transports, tool filepath values must be relative to that directory (e.g. reports/q1.xlsx); absolute paths and directory traversal are rejected.

You can also set the FASTMCP_PORT environment variable to control the port the server listens on (default is 8017 if not set).

  • Example (Windows PowerShell):
    $env:EXCEL_FILES_PATH="E:\MyExcelFiles"
    $env:FASTMCP_PORT="8007"
    uvx excel-com-mcp streamable-http
    
  • Example (Linux/macOS):
    EXCEL_FILES_PATH=/path/to/excel_files FASTMCP_PORT=8007 uvx excel-com-mcp streamable-http
    

Stdio Transport

When using the stdio protocol, the file path is provided with each tool call, so you do not need to set EXCEL_FILES_PATH on the server. The server will use the path sent by the client for each operation.

Path normalization (resolve_target)

Internally, workbook targets are normalized with resolve_target in excel_mcp.path_resolution (single entry point for FR-1 / future COM path comparison). It uses os.path.realpath for stable absolute paths; relative resolution order (search_roots, then cwd) is documented in that module.

  • stdio, allowlist off: tool paths must still be absolute; the server returns os.path.normpath only (legacy behavior for existing clients).
  • stdio, allowlist on and SSE / streamable HTTP: paths are finalized with resolve_target before jail and allowlist checks.

Integrators can reuse path_is_allowed / assert_path_allowed from excel_mcp.path_policy so file and future COM backends share the same policy.

Optional path allowlist (EXCEL_MCP_ALLOWED_PATHS)

For tighter control (aligned with FR-11), set EXCEL_MCP_ALLOWED_PATHS to one or more allowed directory roots, separated by os.pathsep (semicolon on Windows, colon on macOS/Linux—the same rule as the PATH environment variable). Whitespace around each entry is trimmed; ~ is expanded per entry.

When unset or blank, behavior matches the pre-fork defaults: stdio accepts any absolute path (subject to existing validation), and SSE/HTTP use only the EXCEL_FILES_PATH jail.

When set:

  • stdio: each workbook path is resolved with resolve_target, then must lie inside at least one listed root (directory containment, same idea as the remote jail).
  • SSE / streamable HTTP: the resolved path must be inside EXCEL_FILES_PATH and inside at least one allowlist root (intersection).

If the variable is non-empty but no root path resolves (typos, missing drive letters, unreadable paths), the allowlist is treated as active with zero valid roots and paths are rejected until the environment is corrected (fail-closed).

Examples:

# Windows: two roots (note the semicolon)
$env:EXCEL_MCP_ALLOWED_PATHS = "E:\Workbooks;E:\SharedTemplates"
uvx excel-com-mcp stdio
# Linux / macOS: colon-separated
EXCEL_MCP_ALLOWED_PATHS=/var/excel-in:/var/excel-out uvx excel-com-mcp stdio

Workbook transport and COM policy (not MCP wire transport)

These environment variables control workbook routing (file-backed openpyxl path vs COM automation when wired in later stories). They do not select the MCP client↔server wire transport (stdio, SSE, or streamable HTTP); that is configured by how you launch the server (see above). See ADR 0001 for the vocabulary split.

Variable Meaning
EXCEL_MCP_TRANSPORT Workbook mode: auto, file, or com (case-insensitive). Default auto when unset or empty. Invalid values raise at read time. Parsed by excel_mcp.routing.read_workbook_transport.
EXCEL_MCP_COM_STRICT When 1 / true / yes (case-insensitive): strict COM policy. When 0 / false / no, or explicitly relaxed: non-strict. Unset or empty defaults to strict (True). Parsed by read_com_strict.
EXCEL_MCP_COM_ALLOW_FILE_FALLBACK When 1 / true / yes: operators allow documented file fallback in scenarios where non-strict routing would apply (ADR 0005). Unset or empty: False. Parsed by read_com_allow_file_fallback.
EXCEL_MCP_SAVE_AFTER_WRITE_DEFAULT Default for optional tool parameter save_after_write when omitted on mutating tools. 1 / true / yes → default true (extra save_workbook after file-backed writes). Unset or empty defaults to false (FR-8: no extra flush until requested). Parsed by read_save_after_write_default.

Effective strictness for the router is effective_com_strict(): False if file fallback is allowed or EXCEL_MCP_COM_STRICT is explicitly falsy; otherwise True. Allowing file fallback forces non-strict effective behavior whenever that flag is on.

Optional MCP tool parameters (workbook routing)

Every workbook tool accepts optional workbook_transport (auto | file | com) and save_after_write (boolean). When omitted, transport defaults to EXCEL_MCP_TRANSPORT and the save flag defaults per EXCEL_MCP_SAVE_AFTER_WRITE_DEFAULT. Read-only tools ignore save_after_write (no extra save). These names refer to workbook execution routing (ADR 0001), not MCP wire transport.

Routing observability

Routed workbook operations (via execute_routed_workbook_operation in excel_mcp.routing.routed_dispatch) emit one JSON object per dispatch on logger excel-mcp.routing at INFO (no stdout). Fields follow ADR 0001 vocabulary:

  • workbook_transport — requested mode: auto, file, or com.
  • workbook_backend — resolved backend after the selection matrix: file or com.
  • routing_reason — stable reason string from RoutingBackend (e.g. forced_file, read_class_file_backed, full_name_match).
  • duration_ms — wall time for resolve plus executed file I/O (when applicable).
  • workbook_path — redacted path (basename only by default; set EXCEL_MCP_LOG_FULL_PATHS=1 for full path in break-glass scenarios).
  • operation_name — routed contract method name (e.g. read_range_with_metadata).
  • mcp_tool_name — optional registered MCP tool name when supplied by the caller.
  • v1_file_forcedtrue when ADR 0004 forces the file backend for a tool (chart / pivot v1) regardless of auto→COM for other writes.

ADR 0003 — file-backed reads vs Excel host state

Read-class tools (read_data_from_excel, get_workbook_metadata, validation reads, etc.) stay file-backed: they read the on-disk workbook through openpyxl, not live Excel grid memory. If you mutate via COM without saving on every write, disk can lag Excel. Agent pattern: call save_workbook before read_data_from_excel (or other reads) when you need file reads to reflect what Excel has in memory. See docs/architecture/adr/0003-read-path-com-parity.md.

FR-9 — Protected View, read-only, duplicate instances

COM operations return clear, fail-closed errors when Excel blocks writes (e.g. Protected View, read-only). If multiple open workbooks resolve to the same path across Excel instances, routing fails closed with an error asking the operator to close duplicates or use a single Excel instance.

NFR-2 — routing latency

p95 routing overhead is not continuously benchmarked in CI. See docs/performance/routing-nfr2-note.md for an honest scope note and an optional local micro-benchmark idea.

NFR-4 — elevation

The server does not request administrator elevation by default (COM automation targets the user’s normal Excel session; see also the blueprint §5 “do not start Excel as admin without explicit user opt-in”).

Planning / delivery status: workbook transport epics and stories are tracked in docs/plan/transport-routing/IMPLEMENTATION-ROADMAP.md. Phases 1–6 are done in epic/story frontmatter (including optional [com], ComThreadExecutor, and ComWorkbookService skeleton). Epic 7 is delivered in code: COM write-class parity per the inventory matrix, MCP save_workbook (ADR 0003), FR-9 actionable errors (Protected View, read-only, duplicates), and ADR 0004 v1 tool-forced file routing for create_chart / create_pivot_table (see logs: routing_reason v1_file_forced, field v1_file_forced: true when applicable).

Optional Windows COM ([com]): to install pywin32 for COM-backed workbook routing, use pip install excel-com-mcp[com] (or the equivalent for your installer). pywin32 is distributed under the PSF License Agreement (same terms as CPython).

COM execution threading (Windows)

COM apartment rules require Excel automation from a consistent thread. The server uses excel_mcp.com_executor.ComThreadExecutor: a single worker thread pulls jobs from a queue; submit(fn, *args, **kwargs) runs fn on that thread and blocks the caller until the result is ready (or an exception is propagated), so synchronous MCP tool handlers stay compatible without turning every tool async. On Windows, that worker thread calls pythoncom.CoInitialize() before processing jobs and CoUninitialize() on shutdown so COM APIs such as GetActiveObject("Excel.Application") behave like a normal main-thread script (without this, automation from a plain background thread often fails even when Excel is running). The executor does not start Excel by itself. For tests or clean process teardown, call shutdown(wait=True); abrupt exit may still cut off in-flight work—see the module docstring on com_executor for limitations (including no reentrant submit from inside a job on the worker).

Windows manual smoke (COM write path)

  • Install the optional stack: pip install "excel-com-mcp[com]" (or your package equivalent) so pywin32 is available.
  • Start Microsoft Excel manually and open the target .xlsx using File → Open (a running instance with the workbook loaded is required; the server does not launch Excel).
  • Run the MCP server (e.g. stdio) on the same Windows machine with routing env vars as needed (defaults: EXCEL_MCP_TRANSPORT=auto when unset).
  • Call write_data_to_excel with an absolute path to that file, workbook_transport=com or auto, and a small data grid; with auto, the workbook must be detected as open in Excel for COM to win on write tools.
  • Read-class tools (e.g. read_data_from_excel, get_workbook_metadata) stay file-backed per ADR 0003 even when workbook_transport=com; after COM writes, call save_workbook (or use save_after_write=true on mutating tools) before reads so on-disk content matches Excel.
  • Optional: set save_after_write=true on the write so the server persists via COM Save when the executed backend was com, or via openpyxl when it was file.
  • Confirm routing in excel-mcp.log: one JSON line per dispatch with workbook_backend com and a stable routing_reason (e.g. full_name_match / forced_com) for writes routed to COM.
  • For release-style sign-off, follow docs/plan/transport-routing/MANUAL-WINDOWS-RC-CHECKLIST.md (Protected View, read-only, duplicate instance, save-then-read, chart/pivot v1_file_forced rows).

CI locally (contributors)

GitHub Actions runs the same gates as PR CI via .github/workflows/reusable-validate-and-test.yml: editable install with dev extras, pytest, hatch build, and twine check dist/*.

python -m pip install --upgrade pip
pip install -e ".[dev]"
pytest
hatch build
twine check dist/*

No Excel or Windows COM is required for this default path (Linux CI).

Available Tools

The server provides a comprehensive set of Excel manipulation tools. See TOOLS.md for complete documentation of all available tools.

Star History

Star History Chart

License

MIT License - see LICENSE for details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

excel_com_mcp-0.1.9.tar.gz (52.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

excel_com_mcp-0.1.9-py3-none-any.whl (67.3 kB view details)

Uploaded Python 3

File details

Details for the file excel_com_mcp-0.1.9.tar.gz.

File metadata

  • Download URL: excel_com_mcp-0.1.9.tar.gz
  • Upload date:
  • Size: 52.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for excel_com_mcp-0.1.9.tar.gz
Algorithm Hash digest
SHA256 52670a332877fc937d730db988f19c0b7410771a4769aa7c5278550c3fa51814
MD5 95458e7bf1c079cdcf110d11cc20f58e
BLAKE2b-256 9048cd988e6cfbf5c372fc4c7ebbb9fa6129ae1f6dfe73fa49c5483872ca9665

See more details on using hashes here.

Provenance

The following attestation bundles were made for excel_com_mcp-0.1.9.tar.gz:

Publisher: release-pypi-publish.yml on benvdbergh/excel-mcp-server

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file excel_com_mcp-0.1.9-py3-none-any.whl.

File metadata

  • Download URL: excel_com_mcp-0.1.9-py3-none-any.whl
  • Upload date:
  • Size: 67.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for excel_com_mcp-0.1.9-py3-none-any.whl
Algorithm Hash digest
SHA256 83a6c3199f8a846381a659df503325449cddf02a2da1cbdc9db7f07de6c5d06d
MD5 569a13022cdeecbb271e2e35cca9f06e
BLAKE2b-256 2dea26c5684f3df3bee54f8b526aa1222dd6d337a4807e11963f36124fd18363

See more details on using hashes here.

Provenance

The following attestation bundles were made for excel_com_mcp-0.1.9-py3-none-any.whl:

Publisher: release-pypi-publish.yml on benvdbergh/excel-mcp-server

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page