# https://github.com/haris-musa/excel-mcp-server Project Manual

Generated at: 2026-06-21 06:16:35 UTC

## Table of Contents

- [Overview and Installation](#page-1)
- [Tools and API Reference](#page-2)
- [Architecture and Module Structure](#page-3)
- [Security, Deployment, and Troubleshooting](#page-4)

<a id='page-1'></a>

## Overview and Installation

### Related Pages

Related topics: [Tools and API Reference](#page-2), [Security, Deployment, and Troubleshooting](#page-4)

<details>
<summary>Related Source Files</summary>

The following source files were used to generate this page:

- [README.md](https://github.com/haris-musa/excel-mcp-server/blob/main/README.md)
- [manifest.json](https://github.com/haris-musa/excel-mcp-server/blob/main/manifest.json)
- [TOOLS.md](https://github.com/haris-musa/excel-mcp-server/blob/main/TOOLS.md)
- [src/excel_mcp/server.py](https://github.com/haris-musa/excel-mcp-server/blob/main/src/excel_mcp/server.py)
- [src/excel_mcp/workbook.py](https://github.com/haris-musa/excel-mcp-server/blob/main/src/excel_mcp/workbook.py)
- [src/excel_mcp/data.py](https://github.com/haris-musa/excel-mcp-server/blob/main/src/excel_mcp/data.py)
- [src/excel_mcp/calculations.py](https://github.com/haris-musa/excel-mcp-server/blob/main/src/excel_mcp/calculations.py)
- [src/excel_mcp/validation.py](https://github.com/haris-musa/excel-mcp-server/blob/main/src/excel_mcp/validation.py)
</details>

# Overview and Installation

## Purpose and Scope

**excel-mcp-server** is a Model Context Protocol (MCP) server that lets an AI agent create, read, and modify Excel workbooks without requiring Microsoft Excel to be installed on the host. It is built on top of the `openpyxl` library and exposes approximately twenty MCP tools covering workbook lifecycle, cell data I/O, formatting, formulas, charts, pivot tables, native Excel tables, and sheet management.

Source: [README.md](https://github.com/haris-musa/excel-mcp-server/blob/main/README.md) declares the project as "A Model Context Protocol (MCP) server that lets you manipulate Excel files without needing Microsoft Excel installed."

The server is distributed as a Python package on PyPI, packaged with the MCP Bundle (`.mcpb`) format for one-click installation in Claude Desktop (added in v0.1.8), and consumable via `uvx`, `pip`, or Docker. Source: [manifest.json](https://github.com/haris-musa/excel-mcp-server/blob/main/manifest.json) lists the canonical `mcp_config` invocation as `uvx excel-mcp-server stdio`.

## Core Capabilities at a Glance

The MCP server surface is declared statically in [manifest.json](https://github.com/haris-musa/excel-mcp-server/blob/main/manifest.json) under the `tools` array. Each entry maps a function name (e.g. `create_workbook`, `write_data_to_excel`, `apply_formula`) to a short description and is implemented as a decorated `@mcp.tool` in [src/excel_mcp/server.py](https://github.com/haris-musa/excel-mcp-server/blob/main/src/excel_mcp/server.py).

The tool layer is composed of focused implementation modules:

| Domain | Source Module | Responsibility |
|---|---|---|
| Workbook lifecycle | `src/excel_mcp/workbook.py` | Create/open workbooks, sheet creation, metadata |
| Cell data I/O | `src/excel_mcp/data.py` | Read/write ranges, validation metadata |
| Formulas | `src/excel_mcp/calculations.py` | Apply formulas with safety checks |
| Sheet structure | `src/excel_mcp/sheet.py` | Copy/rename/delete sheets, merge, row/column ops |
| Formatting | `src/excel_mcp/formatting.py` | Fonts, borders, fills, conditional formatting |
| Validation | `src/excel_mcp/validation.py` | Range bounds and unsafe-function blocklist |
| Pivot tables | `src/excel_mcp/pivot.py` | Build pivot summaries from source ranges |

Tool annotations (`destructiveHint`, `readOnlyHint`) are set on every tool in [src/excel_mcp/server.py](https://github.com/haris-musa/excel-mcp-server/blob/main/src/excel_mcp/server.py) so LLM clients can reason about side effects before invocation (introduced in v0.1.8 per [PR #110](https://github.com/haris-musa/excel-mcp-server/pull/110)).

## Installation

### Option 1 — `uvx` (recommended, zero-install)

`uvx` runs the latest published version in an ephemeral environment. Per [README.md](https://github.com/haris-musa/excel-mcp-server/blob/main/README.md), the canonical local invocation is:

```bash
uvx excel-mcp-server stdio
```

The same pattern is recorded in [manifest.json](https://github.com/haris-musa/excel-mcp-server/blob/main/manifest.json) under `server.mcp_config`. `uvx` was the focus of the v0.1.3 patch that fixed uvx execution paths (see [v0.1.3 release notes](https://github.com/haris-musa/excel-mcp-server/releases/tag/v0.1.3)).

### Option 2 — `pip`

```bash
pip install excel-mcp-server
python -m excel_mcp stdio
```

The package ships a `__main__.py` entry point (`src/excel_mcp/__main__.py`) which is what `manifest.json` points at under `server.entry_point`.

### Option 3 — MCPB bundle for Claude Desktop

v0.1.8 introduced a packaged MCPB bundle so users can install the server through Claude Desktop's GUI without touching JSON configuration (added in [PR #110](https://github.com/haris-musa/excel-mcp-server/pull/110) per the v0.1.8 release notes).

### Option 4 — Docker

Community request [#10](https://github.com/haris-musa/excel-mcp-server/issues/10) asks for a portable Docker image; until upstream publishes one, the project README documents local Python-based transports only. Self-hosting in Docker is achievable by wrapping the same `uvx`/`pip` invocation.

## Transport Modes and Client Configuration

The server implements three transports, all selected via positional CLI argument (`stdio`, `sse`, `streamable-http`). Source: [README.md](https://github.com/haris-musa/excel-mcp-server/blob/main/README.md) § Usage.

```mermaid
flowchart LR
    Client[MCP Client<br/>Claude Desktop, Cursor, etc.]
    Client -->|stdio| Stdio[Local stdio process<br/>uvx excel-mcp-server stdio]
    Client -->|SSE| SSE[SSE HTTP server<br/>deprecated in v0.1.5]
    Client -->|HTTP| HTTP[streamable-http server<br/>added in v0.1.5]
    Stdio --> Tools[20+ MCP tools<br/>defined in server.py]
    SSE --> Tools
    HTTP --> Tools
    Tools --> FS[(Local Excel files)]
```

**stdio** — the default for desktop clients. Each tool call spawns or reuses the local process. Path handling uses the client working directory; log files are written to the package root directory to avoid permission errors when the client runs from an arbitrary cwd (see [src/excel_mcp/server.py](https://github.com/haris-musa/excel-mcp-server/blob/main/src/excel_mcp/server.py) `ROOT_DIR`/`LOG_FILE` constants).

**SSE (Server-Sent Events)** — marked **deprecated** in the README. v0.1.8 ([release notes](https://github.com/haris-musa/excel-mcp-server/releases/tag/v0.1.8)) explicitly fixed a path-traversal vulnerability in SSE/streamable-http transports reported by `@hits313`. Users still on SSE should upgrade immediately.

**streamable-http** — added in v0.1.5 ([release notes](https://github.com/haris-musa/excel-mcp-server/releases/tag/v0.1.5)) and now the recommended HTTP transport. v0.1.7 fixed host/port configuration issues ([PR #85](https://github.com/haris-musa/excel-mcp-server/pull/85)).

A typical `claude_desktop_config.json` (or equivalent client config) using stdio:

```json
{
  "mcpServers": {
    "excel": {
      "command": "uvx",
      "args": ["excel-mcp-server", "stdio"]
    }
  }
}
```

This block is reproduced directly in [README.md](https://github.com/haris-musa/excel-mcp-server/blob/main/README.md) under § "1. Stdio Transport".

## Known Installation Footguns

A small number of issues recur in user reports and are worth checking before deployment:

- **macOS + Codex + `uvx`** ([issue #100](https://github.com/haris-musa/excel-mcp-server/issues/100)) — fails with `No such file or directory (os error 2)` because `uvx` is not on `PATH`. Install `uv` first or switch to `pip`+`python -m excel_mcp stdio`.
- **FastMCP version mismatch** ([issue #76](https://github.com/haris-musa/excel-mcp-server/issues/76)) — passing an unsupported `version=` kwarg into `FastMCP.__init__` raises `TypeError`. Resolved by aligning with the pinned MCP dependency range; users should upgrade rather than monkey-patch.
- **Security perimeter** ([issues #120](https://github.com/haris-musa/excel-mcp-server/issues/120), [#128](https://github.com/haris-musa/excel-mcp-server/issues/128), [#131](https://github.com/haris-musa/excel-mcp-server/issues/131), [#134](https://github.com/haris-musa/excel-mcp-server/issues/134), [#138](https://github.com/haris-musa/excel-mcp-server/issues/138)) — in stdio mode the server has unrestricted filesystem write access and the unsafe-formula blocklist in [src/excel_mcp/validation.py](https://github.com/haris-musa/excel-mcp-server/blob/main/src/excel_mcp/validation.py) can be bypassed when raw cell values are written via `write_data_to_excel`. For untrusted or multi-tenant deployments, gate the process behind filesystem ACLs or a wrapper that sanitizes `filepath` arguments and applies caller-level policy. Formula validation happens in `validate_formula_in_cell_operation` ([src/excel_mcp/validation.py](https://github.com/haris-musa/excel-mcp-server/blob/main/src/excel_mcp/validation.py)) before [src/excel_mcp/calculations.py](https://github.com/haris-musa/excel-mcp-server/blob/main/src/excel_mcp/calculations.py) writes to the cell.

## Verifying the Install

After install, the server should respond to MCP `initialize` and list the tools declared in [manifest.json](https://github.com/haris-musa/excel-mcp-server/blob/main/manifest.json). A smoke-test invocation is `get_workbook_metadata` against a known file — implementation in [src/excel_mcp/workbook.py](https://github.com/haris-musa/excel-mcp-server/blob/main/src/excel_mcp/workbook.py) `get_workbook_info`, returning `{filename, sheets, size, modified}` and, with `include_ranges=True`, the used `A1:Xn` range per sheet.

## See Also

- Tools Reference (`TOOLS.md`)
- Validation and Formula Safety
- Transport Modes In Depth (stdio vs streamable-http)

---

<a id='page-2'></a>

## Tools and API Reference

### Related Pages

Related topics: [Architecture and Module Structure](#page-3)

<details>
<summary>Related Source Files</summary>

The following source files were used to generate this page:

- [TOOLS.md](https://github.com/haris-musa/excel-mcp-server/blob/main/TOOLS.md)
- [manifest.json](https://github.com/haris-musa/excel-mcp-server/blob/main/manifest.json)
- [src/excel_mcp/server.py](https://github.com/haris-musa/excel-mcp-server/blob/main/src/excel_mcp/server.py)
- [src/excel_mcp/data.py](https://github.com/haris-musa/excel-mcp-server/blob/main/src/excel_mcp/data.py)
- [src/excel_mcp/validation.py](https://github.com/haris-musa/excel-mcp-server/blob/main/src/excel_mcp/validation.py)
- [src/excel_mcp/calculations.py](https://github.com/haris-musa/excel-mcp-server/blob/main/src/excel_mcp/calculations.py)
- [src/excel_mcp/formatting.py](https://github.com/haris-musa/excel-mcp-server/blob/main/src/excel_mcp/formatting.py)
- [src/excel_mcp/sheet.py](https://github.com/haris-musa/excel-mcp-server/blob/main/src/excel_mcp/sheet.py)
- [src/excel_mcp/pivot.py](https://github.com/haris-musa/excel-mcp-server/blob/main/src/excel_mcp/pivot.py)
- [src/excel_mcp/workbook.py](https://github.com/haris-musa/excel-mcp-server/blob/main/src/excel_mcp/workbook.py)
- [README.md](https://github.com/haris-musa/excel-mcp-server/blob/main/README.md)
</details>

# Tools and API Reference

The **excel-mcp-server** exposes a set of Model Context Protocol (MCP) tools that let an AI agent create, read, and modify Excel workbooks without requiring Microsoft Excel. Every tool is registered on a single `FastMCP` instance in [src/excel_mcp/server.py](https://github.com/haris-musa/excel-mcp-server/blob/main/src/excel_mcp/server.py) and is surfaced as MCP tool metadata in [manifest.json](https://github.com/haris-musa/excel-mcp-server/blob/main/manifest.json). This page documents the surface area of those tools, their annotations, and the implementation modules they delegate to.

## Tool Registration and Annotations

Each tool is registered via the `@mcp.tool(...)` decorator on a thin wrapper in `src/excel_mcp/server.py`. The wrappers resolve a relative or absolute `filepath` argument using `get_excel_path()`, then dispatch to an `_impl` function in a dedicated module such as `excel_mcp.workbook`, `excel_mcp.data`, `excel_mcp.sheet`, or `excel_mcp.pivot`. Source: [src/excel_mcp/server.py:1-50]().

The wrappers attach `ToolAnnotations` to give clients hints about side effects:

- `destructiveHint=True` — tools that mutate the filesystem (e.g. `create_workbook`, `create_worksheet`, `merge_cells`, `unmerge_cells`, `create_chart`, `create_pivot_table`, `apply_formula`). Source: [src/excel_mcp/server.py:73-180]().
- `readOnlyHint=True` — read-only inspectors such as `get_workbook_metadata`, `get_merged_cells`, and `validate_formula_syntax`. Source: [src/excel_mcp/server.py:200-230]().

Errors raised by the underlying modules are caught uniformly: domain-specific exceptions (`ValidationError`, `WorkbookError`, `SheetError`, `DataError`, `FormattingError`, `CalculationError`, `PivotError`, `ChartError`) are converted into `Error: <message>` strings returned to the caller, while unexpected exceptions are re-raised and logged. Source: [src/excel_mcp/server.py:11-22]().

## Tool Categories

The full list of exposed tools is enumerated in [manifest.json](https://github.com/haris-musa/excel-mcp-server/blob/main/manifest.json) under the `"tools"` array and described in detail in [TOOLS.md](https://github.com/haris-musa/excel-mcp-server/blob/main/TOOLS.md). The table below groups them by responsibility, showing the signature shape, the primary implementation module, and whether the tool is destructive.

| Category | Tool | Signature highlights | Implementation | Destructive |
|----------|------|----------------------|----------------|-------------|
| Workbook | `create_workbook` | `(filepath)` | `excel_mcp.workbook.create_workbook` | Yes |
| Workbook | `create_worksheet` | `(filepath, sheet_name)` | `excel_mcp.workbook.create_sheet` | Yes |
| Workbook | `get_workbook_metadata` | `(filepath, include_ranges=False)` | `excel_mcp.workbook.get_workbook_info` | No |
| Data | `read_data_from_excel` | `(filepath, sheet_name, start_cell, end_cell, ...)` | `excel_mcp.data.read_excel_range` | No |
| Data | `write_data_to_excel` | `(filepath, sheet_name, data, start_cell)` | `excel_mcp.data.write_data` | Yes |
| Sheet | `copy_worksheet` / `delete_worksheet` / `rename_worksheet` | `(filepath, sheet, ...)` | `excel_mcp.sheet.copy_sheet` etc. | Yes |
| Sheet | `merge_cells` / `unmerge_cells` / `get_merged_cells` | `(filepath, sheet, start, end)` | `excel_mcp.sheet.merge_range` etc. | Yes / No |
| Sheet | `insert_rows` / `insert_columns` / `delete_sheet_rows` / `delete_sheet_columns` | `(filepath, sheet, start, count)` | `excel_mcp.sheet.insert_row` etc. | Yes |
| Range | `copy_range` / `delete_range` | `(filepath, sheet, range)` | `excel_mcp.sheet` | Yes |
| Range | `validate_excel_range` | `(filepath, sheet, range)` | `excel_mcp.validation.validate_range_bounds` | No |
| Formula | `apply_formula` | `(filepath, sheet, cell, formula)` | `excel_mcp.calculations.apply_formula` | Yes |
| Formula | `validate_formula_syntax` | `(filepath, sheet, cell, formula)` | `excel_mcp.validation.validate_formula_in_cell_operation` | No |
| Format | `format_range` | `(filepath, sheet, start, end, ...)` | `excel_mcp.formatting.format_range` | Yes |
| Chart | `create_chart` | `(filepath, sheet, data_range, chart_type, target_cell, ...)` | `excel_mcp.chart.create_chart_in_sheet` | Yes |
| Pivot / Table | `create_pivot_table` | `(filepath, sheet, data_range, rows, values, columns, agg_func)` | `excel_mcp.pivot.create_pivot_table` | Yes |
| Pivot / Table | `create_table` | `(filepath, sheet, ...)` | `excel_mcp.tables.create_excel_table` | Yes |

## Module Wiring and Data Flow

The following diagram shows how a tool call flows from the MCP client through the server wrapper into the implementation module and back.

```mermaid
flowchart LR
    A[MCP Client] -->|tool name + args| B[server.py wrapper]
    B -->|get_excel_path| C[Resolved filepath]
    B -->|dispatch| D[Implementation module]
    D -->|openpyxl I/O| E[.xlsx file]
    D -->|dict result| B
    B -->|Error: msg or success| A
```

Each implementation module owns a narrow concern: `workbook.py` handles file creation and metadata, `data.py` handles read/write of cell ranges, `validation.py` and `calculations.py` handle formula safety and application, `formatting.py` handles styling, `sheet.py` handles worksheet-level operations, and `pivot.py` / `chart.py` handle analytical artifacts. Source: [src/excel_mcp/data.py:1-20](), [src/excel_mcp/calculations.py:1-15](), [src/excel_mcp/formatting.py:1-12]().

### Formula Safety Path

`apply_formula` in [src/excel_mcp/server.py](https://github.com/haris-musa/excel-mcp-server/blob/main/src/excel_mcp/server.py) first calls `validate_formula_in_cell_operation` to reject unsafe functions and bad cell references, then dispatches to `calculations.apply_formula` which writes the formula and saves the workbook. Source: [src/excel_mcp/validation.py:17-60](), [src/excel_mcp/calculations.py:8-55](). Community issue [#134](https://github.com/haris-musa/excel-mcp-server/issues/134) notes that `write_data_to_excel` does not route through this same validator, which is an acknowledged validation gap.

### Transport Modes

The same tool surface is available across three transports — `stdio` (default local use), `sse` (deprecated), and `streamable-http` — selected by the command-line argument in [README.md](https://github.com/haris-musa/excel-mcp-server/blob/main/README.md). Release v0.1.8 patched a path-traversal vulnerability in the HTTP transports ([v0.1.8 release notes](https://github.com/haris-musa/excel-mcp-server/releases/tag/v0.1.8)).

## Common Error and Edge Cases

- **Missing sheet**: `load_workbook` followed by an `if sheet_name not in wb.sheetnames` check raises `ValidationError`/`WorkbookError`, which the wrapper formats as `Error: Sheet '<name>' not found`. Source: [src/excel_mcp/sheet.py:11-30](), [src/excel_mcp/data.py:15-25]().
- **Invalid cell reference**: `validate_cell_reference` in `excel_mcp.cell_utils` is invoked before any write, producing a `ValidationError`. Source: [src/excel_mcp/calculations.py:13-15]().
- **Unsafe formula**: Functions like `HYPERLINK`, `WEBSERVICE`, `DGET`, and `RTD` are rejected by `validate_formula` in [src/excel_mcp/validation.py](https://github.com/haris-musa/excel-mcp-server/blob/main/src/excel_mcp/validation.py) and surfaced as `Error: Invalid formula syntax: ...`.
- **macOS launcher failures**: Community issue [#100](https://github.com/haris-musa/excel-mcp-server/issues/100) reports `uvx excel-mcp-server stdio` failing with `No such file or directory` on macOS Codex; using `pipx` or the explicit Python entry point `python -m excel_mcp` typically resolves it.

## See Also

- [README.md](https://github.com/haris-musa/excel-mcp-server/blob/main/README.md) — installation and transport configuration.
- [TOOLS.md](https://github.com/haris-musa/excel-mcp-server/blob/main/TOOLS.md) — full parameter-by-parameter tool documentation.
- [manifest.json](https://github.com/haris-musa/excel-mcp-server/blob/main/manifest.json) — Claude Desktop / MCPB bundle metadata.
- [src/excel_mcp/server.py](https://github.com/haris-musa/excel-mcp-server/blob/main/src/excel_mcp/server.py) — authoritative tool registration source.
- [Releases](https://github.com/haris-musa/excel-mcp-server/releases) — version history, including the v0.1.8 path-traversal fix.

---

<a id='page-3'></a>

## Architecture and Module Structure

### Related Pages

Related topics: [Tools and API Reference](#page-2), [Security, Deployment, and Troubleshooting](#page-4)

<details>
<summary>Related Source Files</summary>

The following source files were used to generate this page:

- [src/excel_mcp/server.py](https://github.com/haris-musa/excel-mcp-server/blob/main/src/excel_mcp/server.py)
- [src/excel_mcp/__main__.py](https://github.com/haris-musa/excel-mcp-server/blob/main/src/excel_mcp/__main__.py)
- [src/excel_mcp/exceptions.py](https://github.com/haris-musa/excel-mcp-server/blob/main/src/excel_mcp/exceptions.py)
- [src/excel_mcp/cell_utils.py](https://github.com/haris-musa/excel-mcp-server/blob/main/src/excel_mcp/cell_utils.py)
- [src/excel_mcp/cell_validation.py](https://github.com/haris-musa/excel-mcp-server/blob/main/src/excel_mcp/cell_validation.py)
- [src/excel_mcp/validation.py](https://github.com/haris-musa/excel-mcp-server/blob/main/src/excel_mcp/validation.py)
- [src/excel_mcp/workbook.py](https://github.com/haris-musa/excel-mcp-server/blob/main/src/excel_mcp/workbook.py)
- [src/excel_mcp/data.py](https://github.com/haris-musa/excel-mcp-server/blob/main/src/excel_mcp/data.py)
- [src/excel_mcp/sheet.py](https://github.com/haris-musa/excel-mcp-server/blob/main/src/excel_mcp/sheet.py)
- [src/excel_mcp/calculations.py](https://github.com/haris-musa/excel-mcp-server/blob/main/src/excel_mcp/calculations.py)
- [src/excel_mcp/formatting.py](https://github.com/haris-musa/excel-mcp-server/blob/main/src/excel_mcp/formatting.py)
- [src/excel_mcp/pivot.py](https://github.com/haris-musa/excel-mcp-server/blob/main/src/excel_mcp/pivot.py)
- [README.md](https://github.com/haris-musa/excel-mcp-server/blob/main/README.md)
- [manifest.json](https://github.com/haris-musa/excel-mcp-server/blob/main/manifest.json)
</details>

# Architecture and Module Structure

## Overview

`excel-mcp-server` is a Model Context Protocol (MCP) server that exposes Excel file manipulation as a set of discoverable tools consumable by AI agents such as Claude Desktop, Cursor, and other MCP-compatible clients. The project follows a layered architecture: a thin **transport layer** that speaks the MCP protocol, a **tool registration layer** that maps MCP tool calls onto Python functions, and a **domain layer** of feature modules that operate on `openpyxl` workbook objects on disk.

The package entry point is configured in `manifest.json` as `src/excel_mcp/__main__.py`, and is launched with `uvx excel-mcp-server stdio` ([manifest.json](manifest.json)). Internally, `server.py` constructs a `FastMCP` instance and decorates each domain function with `@mcp.tool(...)`, registering every Excel operation as a separate MCP tool ([server.py](src/excel_mcp/server.py)).

## High-Level Architecture

```mermaid
flowchart TD
    Client[MCP Client<br/>Claude Desktop / Cursor] -->|stdio / SSE / HTTP| Transport[Transport Layer<br/>FastMCP]
    Transport -->|tool invocation| Registry[Tool Registry<br/>server.py @mcp.tool]
    Registry --> Workbook[workbook.py]
    Registry --> Sheet[sheet.py]
    Registry --> Data[data.py]
    Registry --> Formatting[formatting.py]
    Registry --> Calculations[calculations.py]
    Registry --> Pivot[pivot.py]
    Registry --> Validation[validation.py]
    Workbook --> openpyxl[(openpyxl Workbook)]
    Sheet --> openpyxl
    Data --> openpyxl
    Formatting --> openpyxl
    Calculations --> openpyxl
    Pivot --> openpyxl
    Validation --> openpyxl
    CellUtils[cell_utils.py] --> Workbook
    CellUtils --> Sheet
    CellUtils --> Data
    CellUtils --> Formatting
    CellUtils --> Calculations
    CellUtils --> Pivot
    Exceptions[exceptions.py] --> Workbook
    Exceptions --> Sheet
    Exceptions --> Data
    Exceptions --> Formatting
    Exceptions --> Calculations
    Exceptions --> Pivot
```

The architecture deliberately keeps **file I/O localized** to the domain modules. The tool layer in `server.py` is responsible only for path normalization, exception translation, and structured tool annotation (`destructiveHint`, `readOnlyHint`); all business logic resides in the per-feature modules.

## Module Breakdown

### Tool Registration Layer (`server.py`)

`server.py` instantiates a single `FastMCP` server and registers each Excel operation through the `@mcp.tool(annotations=ToolAnnotations(...))` decorator ([server.py](src/excel_mcp/server.py)). Tools are grouped by intent:

- **Destructive tools** — those that mutate files — carry `destructiveHint=True`, including `create_workbook`, `create_worksheet`, `apply_formula`, `create_chart`, `create_pivot_table`, and the merge/unmerge/copy/delete operations.
- **Read-only tools** — such as `get_merged_cells` and `validate_formula_syntax` — carry `readOnlyHint=True`.

The server also computes a stable log file path at startup, `LOG_FILE = os.path.join(ROOT_DIR, "excel-mcp.log")`, to avoid permission failures when running under stdio from arbitrary client working directories ([server.py](src/excel_mcp/server.py)).

### Domain Modules

| Module | Responsibility | Key Functions |
| --- | --- | --- |
| `workbook.py` | Workbook lifecycle | `create_workbook`, `create_sheet`, `get_workbook_info`, `get_or_create_workbook` |
| `sheet.py` | Sheet-level operations | `copy_sheet`, `delete_sheet`, `rename_sheet`, `merge_range`, `unmerge_range`, `get_merged_ranges`, `insert_row`, `insert_cols`, `delete_rows`, `delete_cols` |
| `data.py` | Cell range read/write | `read_excel_range`, `write_data` |
| `formatting.py` | Cell styling | `format_range` (font, fill, border, alignment, conditional formatting, protection) |
| `calculations.py` | Formula application | `apply_formula` (writes after syntax validation) |
| `pivot.py` | Pivot tables | `create_pivot_table` |
| `validation.py` | Formula/range validation | `validate_formula_in_cell_operation`, `validate_range_in_sheet_operation` |
| `cell_validation.py` | Data validation metadata | Cell-level validation rule introspection |

Source: [workbook.py](src/excel_mcp/workbook.py), [sheet.py](src/excel_mcp/sheet.py), [data.py](src/excel_mcp/data.py), [formatting.py](src/excel_mcp/formatting.py), [calculations.py](src/excel_mcp/calculations.py), [pivot.py](src/excel_mcp/pivot.py).

### Shared Utilities

Two utility modules are reused across the domain layer:

- **`cell_utils.py`** provides `parse_cell_range` and `validate_cell_reference`, which translate A1-style cell references into `(row, col)` tuples. Every domain module that accepts cell coordinates imports these helpers, ensuring consistent parsing semantics across tools ([validation.py](src/excel_mcp/validation.py)).
- **`exceptions.py`** defines a typed exception hierarchy — `ValidationError`, `WorkbookError`, `SheetError`, `DataError`, `FormattingError`, `CalculationError`, `PivotError`, `ChartError` — that `server.py` catches and converts into structured error strings returned to the MCP client ([server.py](src/excel_mcp/server.py)).

### Transport Layer

The README documents three transports: `stdio` (default), `sse` (deprecated), and `streamable-http` ([README.md](README.md)). The package entry point `__main__.py` reads CLI arguments and dispatches to the appropriate `FastMCP` runner. v0.1.5 introduced streamable-HTTP support, and v0.1.7 fixed host/port configuration issues for the network transports ([v0.1.7 release notes](https://github.com/haris-musa/excel-mcp-server/releases/tag/v0.1.7)).

## Cross-Cutting Concerns

### Validation Pipeline

Formula and range validation is centralized in `validation.py`. The module maintains an `UNSAFE_FUNCS` denylist (including `WEBSERVICE`, `DGET`, `RTD`, and various hyperlink/RTD functions) used by `validate_formula` to reject dangerous formulas before they reach `openpyxl` ([validation.py](src/excel_mcp/validation.py)). The MCP-facing tool `apply_formula` first invokes `validate_formula_in_cell_operation` and only writes the formula to the workbook if validation succeeds ([server.py](src/excel_mcp/server.py)).

### Logging and Error Handling

Each tool in `server.py` follows a consistent try/except pattern: domain-specific exceptions (`ValidationError`, `WorkbookError`, etc.) are converted to `f"Error: {str(e)}"` strings returned to the client, while unexpected exceptions are logged via `logger.error(...)` and re-raised so the MCP transport can report them ([server.py](src/excel_mcp/server.py)). Log output is written to `excel-mcp.log` next to the package root to survive stdio client restarts ([server.py](src/excel_mcp/server.py)).

### Security Boundaries

The current architecture has no per-user or per-session identity layer; any client connected to the transport can invoke any tool against any reachable file path. Community issues have flagged this gap, including a request to identify which user triggered each call ([issue #138](https://github.com/haris-musa/excel-mcp-server/issues/138)) and a request to add policy enforcement for the ~20 filesystem-writing tools ([issue #131](https://github.com/haris-musa/excel-mcp-server/issues/131)). v0.1.8 addressed one related concern by fixing a path-traversal vulnerability in the SSE and streamable-HTTP transports ([v0.1.8 release notes](https://github.com/haris-musa/excel-mcp-server/releases/tag/v0.1.8)).

## Common Failure Modes

- **macOS stdio startup failure** — Issue #100 reports `MCP client for excel failed to start: No such file or directory (os error 2)` when launched via `uvx excel-mcp-server stdio`. The root cause is typically that `uvx` cannot locate the package on `PATH`; reinstalling via `uv tool install excel-mcp-server` or running from the project root resolves it.
- **`FastMCP.__init__() got an unexpected keyword argument 'version'`** — Issue #76 shows that mismatched `mcp`/`fastmcp` dependency versions break the server. Pinning compatible versions per `pyproject.toml` (v0.1.6 fixed the FastMCP compatibility regression) resolves this ([v0.1.6 release notes](https://github.com/haris-musa/excel-mcp-server/releases/tag/v0.1.6)).
- **Bypassed formula validation via `write_data_to_excel`** — Issue #134 notes that formulas can reach a cell via the data-writing tool without going through `validate_formula`. Operators deploying the server should restrict which tools are exposed to untrusted agents or front the server with a policy layer.

## See Also

- [Tools Reference](TOOLS.md) — complete parameter and return-value documentation for every MCP tool
- [README.md](README.md) — installation and client configuration examples
- [v0.1.8 release notes](https://github.com/haris-musa/excel-mcp-server/releases/tag/v0.1.8) — path-traversal fix and tool annotations

---

<a id='page-4'></a>

## Security, Deployment, and Troubleshooting

### Related Pages

Related topics: [Overview and Installation](#page-1), [Architecture and Module Structure](#page-3)

<details>
<summary>Related Source Files</summary>

The following source files were used to generate this page:

- [README.md](https://github.com/haris-musa/excel-mcp-server/blob/main/README.md)
- [TOOLS.md](https://github.com/haris-musa/excel-mcp-server/blob/main/TOOLS.md)
- [manifest.json](https://github.com/haris-musa/excel-mcp-server/blob/main/manifest.json)
- [src/excel_mcp/server.py](https://github.com/haris-musa/excel-mcp-server/blob/main/src/excel_mcp/server.py)
- [src/excel_mcp/validation.py](https://github.com/haris-musa/excel-mcp-server/blob/main/src/excel_mcp/validation.py)
- [src/excel_mcp/calculations.py](https://github.com/haris-musa/excel-mcp-server/blob/main/src/excel_mcp/calculations.py)
- [src/excel_mcp/workbook.py](https://github.com/haris-musa/excel-mcp-server/blob/main/src/excel_mcp/workbook.py)
- [src/excel_mcp/formatting.py](https://github.com/haris-musa/excel-mcp-server/blob/main/src/excel_mcp/formatting.py)
- [src/excel_mcp/sheet.py](https://github.com/haris-musa/excel-mcp-server/blob/main/src/excel_mcp/sheet.py)
</details>

# Security, Deployment, and Troubleshooting

The `excel-mcp-server` is a Model Context Protocol (MCP) server that exposes approximately 24 tools for reading, writing, formatting, and analyzing Excel `.xlsx` files via the `openpyxl` library. Because the server interacts with the local filesystem and accepts formula input, understanding its security boundaries, deployment surface, and common failure modes is essential before integrating it with an MCP client such as Claude Desktop, Cursor, or Codex. This page documents the security model that the code actually enforces, the three supported transports, and the recurring failure patterns reported by the community.

## Security Model and Tool Surface

### What the server enforces today

The server uses `FastMCP` from the official MCP Python SDK and decorates each tool with `ToolAnnotations` to declare its behavior to the LLM client. Most write-oriented tools carry `destructiveHint=True`, while purely read-only tools such as `validate_formula_syntax`, `get_workbook_metadata`, and `get_merged_cells` carry `readOnlyHint=True` (see `src/excel_mcp/server.py:81-95` and surrounding tool definitions). These hints are advisory metadata for the LLM; the server itself does not implement an authorization layer — every tool runs with the privileges of the user that launched the MCP process.

Formula input is the only place where the server actively rejects unsafe content. The validator maintains a denylist of functions that can exfiltrate data or reach the network. Source: [src/excel_mcp/validation.py]() (the `HYPERLINK`, `WEBSERVICE`, `DGET`, and `RTD` entries near the top of `validate_formula`). Cell-reference syntax is also checked with a regex that accepts the pattern `[A-Z]+[0-9]+(?::[A-Z]+[0-9]+)?`, and any reference that fails `validate_cell_reference` is rejected (Source: [src/excel_mcp/validation.py]()). The validator is invoked from `apply_formula` in `server.py`, which first calls `validate_formula_impl` and only then delegates to `excel_mcp.calculations.apply_formula` (Source: [src/excel_mcp/server.py]() and [src/excel_mcp/calculations.py]()).

### Known gaps documented by the community

Several issues in the issue tracker describe attack vectors that the source code does **not** close:

- **Path traversal in `create_workbook` and friends.** Issue #120 (Arbitrary file path access) and #128 (Command Injection via unsanitized file path) show that tool arguments like `filepath` are not constrained to a working directory; the server will write or read at any path the calling agent supplies. The release notes for v0.1.8 credit a fix for path traversal in the SSE and streamable-HTTP transports (Source: [v0.1.8 release notes]()), but stdio mode still resolves paths against the process working directory without sandboxing.
- **Formula injection via `write_data_to_excel`.** Issue #134 reports that `write_data_to_excel` can write a string that starts with `=` into a cell, bypassing the `apply_formula` validator. The denylist in `validation.py` only runs on the `apply_formula` code path, not on the generic data-write path.
- **No per-user identity.** Issue #138 notes there is no built-in way for a deployed server to identify which Claude Desktop user initiated a call, because the stdio transport runs in a single process context and the HTTP transports do not propagate end-user identity.
- **No policy layer for write operations.** Issue #131 points out that all 20+ write tools have unrestricted filesystem access when running under stdio.

Operators deploying the server in a shared or multi-tenant environment should therefore add an outer sandbox (a container, a read-only bind mount for inputs, or a chroot) and restrict the working directory the server is launched from.

## Deployment Options and Transports

The package manifest declares the entry point as `python -m excel_mcp` with arguments `["excel-mcp-server", "stdio"]` (Source: [manifest.json]()). The README documents three transports:

| Transport | Command | Typical use |
|-----------|---------|-------------|
| stdio | `uvx excel-mcp-server stdio` | Local clients such as Claude Desktop and Cursor |
| SSE (deprecated) | `uvx excel-mcp-server sse` | Legacy remote clients |
| streamable HTTP | `uvx excel-mcp-server streamable-http` | Modern remote clients |

For stdio, the MCP client configuration is a JSON block of the form `{"command": "uvx", "args": ["excel-mcp-server", "stdio"]}` (Source: [README.md]()). Release v0.1.7 added fixes for host/port configuration issues in the HTTP transports (Source: [v0.1.7 release notes]()), and v0.1.8 added an MCPB bundle for one-click Claude Desktop installation (Source: [v0.1.8 release notes]()).

When launched, the server writes its log file to a project-root-relative path computed as `os.path.join(ROOT_DIR, "excel-mcp.log")` so that stdio clients running from arbitrary working directories can still create the log (Source: [src/excel_mcp/server.py]()).

```mermaid
flowchart LR
    Client[MCP Client<br/>Claude Desktop / Cursor / Ontheia] -->|stdio| Server[excel-mcp-server]
    Client -->|SSE / streamable-http| Server
    Server -->|openpyxl| XLSX[(.xlsx files)]
    Server -->|denylist check| Validator[Formula Validator]
    Server -->|LogFile| Log[(excel-mcp.log)]
```

## Path Handling, Errors, and Logging

`workbook.create_workbook` uses `pathlib.Path` to create parent directories on demand (`path.parent.mkdir(parents=True, exist_ok=True)`) and then calls `wb.save(str(path))` (Source: [src/excel_mcp/workbook.py]()). This means the server will create missing directories and overwrite existing files without prompting. The wrapper tool `create_workbook` in `server.py` calls `get_excel_path(filepath)` to resolve the argument before invoking the implementation, but the resolution function does not enforce that the path is inside a permitted root (Source: [src/excel_mcp/server.py]()).

Errors are surfaced through a dedicated exception hierarchy imported at the top of `server.py`: `ValidationError`, `WorkbookError`, `SheetError`, `DataError`, `FormattingError`, `CalculationError`, `PivotError`, and `ChartError` (Source: [src/excel_mcp/server.py:18-26]()). Each tool catches its expected exception types and returns `"Error: {str(e)}"` as a plain string to the MCP client, while unexpected exceptions are logged via the module-level `logger` and re-raised so the transport layer can surface the failure.

## Common Errors and Troubleshooting

The following patterns recur in the issue tracker and in the source code:

- **`No such file or directory` on macOS with Codex (issue #100).** When launched via `uvx` from a shell that does not resolve `uvx` on `PATH`, the client receives `os error 2`. The fix is to invoke the absolute path to `uvx` (for example the result of `which uvx`) in the `command` field of the MCP config.
- **`FastMCP.__init__() got an unexpected keyword argument 'version'` (issue #76).** A pinned version of the `mcp` SDK older than the one the server targets causes this. The v0.1.6 release notes describe the FastMCP compatibility fix that closes this regression (Source: [v0.1.6 release notes]()).
- **`Sheet not found` / `File not found`.** These are produced by `WorkbookError` and `SheetError`. The Python tool implementations check `sheet_name in wb.sheetnames` before mutating (for example, in `create_sheet` and `delete_sheet` in [src/excel_mcp/workbook.py]() and [src/excel_mcp/sheet.py]()) and raise a typed error that the tool wrapper turns into an `Error:` string.
- **Formatting and border errors.** `format_range` catches `ValueError` from the openpyxl style constructors and re-raises as `FormattingError` with the original message (Source: [src/excel_mcp/formatting.py]()). If a caller passes an invalid color code, the returned message identifies the offending field.
- **Docker packaging.** Issue #10 requests a portable Docker image; as of v0.1.8 no official image is published, so the recommended approach is to run the published PyPI package inside a `python:3.12-slim` container with the working directory mounted read-write and no network egress.

The most reliable first step for any failure is to inspect `excel-mcp.log` at the location computed in `server.py`; transport-level errors and any uncaught exceptions from the tool implementations are written there with the standard `logger.error` format.

## See Also

- README — [README.md](https://github.com/haris-musa/excel-mcp-server/blob/main/README.md)
- Tool reference — [TOOLS.md](https://github.com/haris-musa/excel-mcp-server/blob/main/TOOLS.md)
- Package manifest — [manifest.json](https://github.com/haris-musa/excel-mcp-server/blob/main/manifest.json)
- Server entry point — [src/excel_mcp/server.py](https://github.com/haris-musa/excel-mcp-server/blob/main/src/excel_mcp/server.py)
- Formula validation — [src/excel_mcp/validation.py](https://github.com/haris-musa/excel-mcp-server/blob/main/src/excel_mcp/validation.py)
- Workbook operations — [src/excel_mcp/workbook.py](https://github.com/haris-musa/excel-mcp-server/blob/main/src/excel_mcp/workbook.py)
- Sheet operations — [src/excel_mcp/sheet.py](https://github.com/haris-musa/excel-mcp-server/blob/main/src/excel_mcp/sheet.py)
- Formatting — [src/excel_mcp/formatting.py](https://github.com/haris-musa/excel-mcp-server/blob/main/src/excel_mcp/formatting.py)
- Calculation engine — [src/excel_mcp/calculations.py](https://github.com/haris-musa/excel-mcp-server/blob/main/src/excel_mcp/calculations.py)

---

<!-- evidence_pipeline_checked: true -->
<!-- evidence_injected: true -->

---

## Pitfall Log

Project: haris-musa/excel-mcp-server

Summary: Found 15 structured pitfall item(s), including 1 high/blocking item(s). Top priority: Security or permission risk - Security or permission risk requires verification.

## 1. Security or permission risk - Security or permission risk requires verification

- Severity: high
- Evidence strength: source_linked
- Finding: Project evidence flags a security or permission risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: community_evidence:github | https://github.com/haris-musa/excel-mcp-server/issues/120

## 2. Installation risk - Installation risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Project evidence flags a installation risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: community_evidence:github | https://github.com/haris-musa/excel-mcp-server/issues/132

## 3. Installation risk - Installation risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Project evidence flags a installation risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: community_evidence:github | https://github.com/haris-musa/excel-mcp-server/issues/129

## 4. Installation risk - Installation risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Project evidence flags a installation risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: community_evidence:github | https://github.com/haris-musa/excel-mcp-server/issues/123

## 5. Configuration risk - Configuration risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Project evidence flags a configuration risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: capability.host_targets | https://github.com/haris-musa/excel-mcp-server

## 6. Configuration risk - Configuration risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Project evidence flags a configuration risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: community_evidence:github | https://github.com/haris-musa/excel-mcp-server/issues/131

## 7. Capability evidence risk - Capability evidence risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: README/documentation is current enough for a first validation pass.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: capability.assumptions | https://github.com/haris-musa/excel-mcp-server

## 8. Maintenance risk - Maintenance risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Project evidence flags a maintenance risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: evidence.maintainer_signals | https://github.com/haris-musa/excel-mcp-server

## 9. Security or permission risk - Security or permission risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: no_demo
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: downstream_validation.risk_items | https://github.com/haris-musa/excel-mcp-server

## 10. Security or permission risk - Security or permission risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: no_demo
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: risks.scoring_risks | https://github.com/haris-musa/excel-mcp-server

## 11. Security or permission risk - Security or permission risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Project evidence flags a security or permission risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: community_evidence:github | https://github.com/haris-musa/excel-mcp-server/issues/128

## 12. Security or permission risk - Security or permission risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Project evidence flags a security or permission risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: community_evidence:github | https://github.com/haris-musa/excel-mcp-server/issues/138

## 13. Security or permission risk - Security or permission risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Project evidence flags a security or permission risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: community_evidence:github | https://github.com/haris-musa/excel-mcp-server/issues/134

## 14. Maintenance risk - Maintenance risk requires verification

- Severity: low
- Evidence strength: source_linked
- Finding: issue_or_pr_quality=unknown。
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: evidence.maintainer_signals | https://github.com/haris-musa/excel-mcp-server

## 15. Maintenance risk - Maintenance risk requires verification

- Severity: low
- Evidence strength: source_linked
- Finding: release_recency=unknown。
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: evidence.maintainer_signals | https://github.com/haris-musa/excel-mcp-server

<!-- canonical_name: haris-musa/excel-mcp-server; human_manual_source: deepwiki_human_wiki -->
