Skip to main content
Glama
Excel MCP Server

Excel MCP Server

by eschaq

Excel MCP Server

by DWS Build · GitHub · Claude Marketplace listing (coming soon)

Let Claude open, analyze and edit spreadsheets on your computer. This MCP server gives Claude ten tools for working with .xlsx, .xlsm, .xls and .csv files: reading sheets, filtering and searching rows, computing summary statistics, inspecting formulas, and writing values, formulas, sheets and new workbooks. Everything runs locally over stdio. It needs no Microsoft Office, and it only touches files inside the folders you allow. The server itself makes no network connections; the only downloads are the one-time install described in What gets downloaded.

Need batch work?

This plugin works on one file at a time. To consolidate or pivot across many workbooks, or to batch convert, rename or format them, DWS Spreadsheet Premium handles up to 50 files from URLs, and Claude can call it through Apify's MCP server.

Screenshots

Exploring a workbook. Claude calls read_spreadsheet to see sheets, ranges and contents:

Claude listing the sheets in sample.xlsx

Summary statistics. get_summary_stats returns min, max, mean, median, stdev and sum per column:

Claude giving summary stats for the Sales sheet

Filtering rows. apply_filter finds matching rows, returned with their Excel row numbers:

Claude finding all rows where revenue is over 4000


Related MCP server: csv-mcp-server

Requirements

  • uv. The plugin starts its server through uv, in frozen mode: on first launch uv installs exactly the dependency versions pinned in this repository's uv.lock (see What gets downloaded), so you don't install anything else yourself. To install uv, follow uv's installation guide, then open a new terminal and check that uv --version works.

Install

This repository is its own plugin marketplace. In your shell:

claude plugin marketplace add eschaq/excel-mcp-server
claude plugin install dws-spreadsheet@dws-build

Or inside a Claude Code session:

/plugin marketplace add eschaq/excel-mcp-server
/plugin install dws-spreadsheet@dws-build

Start a new session (or run /reload-plugins) and ask Claude about a spreadsheet. The first launch takes a few seconds while uv installs the dependencies; after that it starts quickly.

Settings

Installing doesn't prompt for these. Any option you haven't set uses its default, shown below. To change them, run /plugin configure dws-spreadsheet@dws-build in a Claude Code session:

Setting

Default

Effect

Allowed folder

your home folder

Claude can only open spreadsheets inside this folder and its subfolders

Read-only mode

off

Hides the write tools, so Claude can read and analyze files but never change them

Max file size (MB)

50

Larger files are refused

What gets downloaded

The server never connects to the network. Installing and starting it downloads the following, once:

  • Python packages from PyPI (https://pypi.org/simple, with files served from files.pythonhosted.org): the packages pinned, with their hashes, in uv.lock, about 30 in all (32 on Windows; the exact set varies slightly by platform). They are mcp 2.2.0, openpyxl 3.1.5 and xlrd 2.0.2, plus their dependencies (for example pydantic, anyio, starlette, cryptography and et-xmlfile; pywin32 on Windows only). --frozen makes uv install exactly those versions and never re-resolve them, and uv checks each file against its hash in the lockfile. No registry or index is configured anywhere in the plugin, so uv uses its default, PyPI.

  • Python itself, only if needed. If you don't have Python 3.11 or newer, uv downloads a standalone CPython build from GitHub (astral-sh/python-build-standalone).

uv keeps the downloads in its cache (~/.cache/uv on macOS/Linux, %LOCALAPPDATA%\uv\cache on Windows) and installs them into a .venv folder inside the installed plugin's folder. The plugin's own code (run_server.py and src/excel_mcp/) runs straight from the plugin folder and isn't downloaded or built. Later launches reuse the installed environment and download nothing. Installing uv itself is a separate step you run yourself (see Requirements).

Update or remove

claude plugin update dws-spreadsheet@dws-build
claude plugin uninstall dws-spreadsheet@dws-build

Install for Claude Desktop

Requires Python 3.11+. Install from source:

git clone https://github.com/eschaq/excel-mcp-server
cd excel-mcp-server
python -m venv .venv
.venv\Scripts\activate          # macOS/Linux: source .venv/bin/activate
pip install -e .

Claude Desktop configuration

Open Settings → Developer → Edit Config in Claude Desktop and add:

{
  "mcpServers": {
    "excel": {
      "command": "C:\\path\\to\\excel-mcp-server\\.venv\\Scripts\\python.exe",
      "args": [
        "-m", "excel_mcp.server",
        "--allow-dir", "C:\\Users\\you\\Documents",
        "--allow-dir", "C:\\Users\\you\\Downloads"
      ]
    }
  }
}

On macOS/Linux use the venv's bin/python instead. Point command at the Python interpreter where the package is installed, since a bare "python" may resolve to a different interpreter (or, on Windows, to the Microsoft Store stub). Restart Claude Desktop after saving.

Server options

Flag

Default

Effect

--allow-dir DIR (repeatable)

your home folder

Only files inside these folders can be read or written

--read-only

off

Write tools are removed entirely

--max-file-mb N

50

Files larger than this are refused

--log-file PATH

~/.excel-mcp/excel-mcp.log

Audit log of every file operation

Settings come only from these flags; the server reads no environment variables. Relative paths passed to tools resolve against the first allowed folder.

Tools

Tool

What it does

Parameters

read_spreadsheet

List sheets with row/column counts, used range and a preview

path, preview_rows=5

get_sheet_data

Return rows as JSON records, with paging and column selection

path, sheet, header_row=1, columns, offset=0, limit=500

get_summary_stats

Count, missing, min, max, mean, median, sample stdev (like STDEV.S) and sum for numeric columns; unique/top values for text; earliest/latest for dates

path, sheet, header_row=1, columns

apply_filter

Return rows matching column conditions

path, conditions, sheet, header_row=1, match=all|any, columns, limit=500

search

Find cells matching text, a number or a regex, across one or all sheets

path, query, sheet, mode=contains|exact|regex, case_sensitive, limit=100

get_formulas

List formulas in a range with their cached results (.xlsx/.xlsm)

path, cell_range, sheet

write_cell ✏️

Write a value or formula to one cell; returns the old value

path, cell, value, sheet

write_range ✏️

Write a 2D block of values starting at a cell

path, start_cell, values, sheet

create_sheet ✏️

Add a sheet, optionally with a header row

path, name, headers, index

create_workbook ✏️

Create a new .xlsx with an optional bold, frozen header row

path, sheet_name=Sheet1, headers, overwrite=false

✏️ = write tool: .xlsx/.xlsm only, and hidden in --read-only mode.

Filter operators: eq, ne, gt, gte, lt, lte, between ([low, high]), contains, not_contains, startswith, endswith, regex, in, not_in (list), is_null, not_null. Text comparisons ignore case unless case_sensitive is set; dates compare against ISO strings such as "2026-01-31".

{
  "path": "sales.xlsx",
  "conditions": [
    { "column": "Region", "op": "in", "value": ["West", "North"] },
    { "column": "Date", "op": "gte", "value": "2026-02-01" }
  ],
  "columns": ["Rep", "Units", "Date"]
}

Every data row comes back with a _row key holding its Excel row number, so Claude can write results back to the right cell.

Example prompts

  • "What's in Q3-budget.xlsx? Summarize each sheet."

  • "In sales.xlsx, which reps sold more than 100 units in the West region since March?"

  • "Give me summary stats for the Revenue and Margin columns."

  • "Find every cell mentioning 'Acme Corp' across all sheets."

  • "Show me the formulas in the Totals sheet and check whether any reference the wrong rows."

  • "Add a Summary sheet with total units per region, using SUMIF formulas."

  • "Create contacts.xlsx with columns Name, Email and Company, then add these 20 people: …"

  • "Convert export.csv into a formatted Excel workbook."

Security

  • Sandboxed paths. Every path is fully resolved (.. collapsed, symlinks followed) and must fall inside an allowed folder. Anything else is refused.

  • File types. Only .xlsx, .xlsm, .xls and .csv can be opened; writes are limited to .xlsx/.xlsm.

  • Size limit. Files over --max-file-mb are refused before they are loaded.

  • Read-only mode. --read-only removes the write tools from the server entirely, so Claude never sees them.

  • Local only. stdio transport, and the server makes no network calls. The one-time dependency install is listed under What gets downloaded.

  • No credentials. The plugin needs no API keys, tokens or passwords, and reads none. It reads no environment variables either: its three settings (allowed folder, read-only mode, max file size) are ordinary userConfig options, passed to the server as command-line arguments through ${user_config.KEY}.

  • Audit log. Each operation is logged with its resolved path to stderr and to the log file.

  • Safe saves. Writes go to a temp file that then replaces the original, so an interrupted save can't leave a half-written workbook.

Limitations

  • Dates are written the way Excel types them. An ISO string such as "2026-07-01" becomes a real date; start it with an apostrophe ("'2026-07-01") to keep it as text.

  • Formulas aren't recalculated. The server stores formulas but doesn't compute them. Files saved by Excel carry cached results, which the read tools return. A formula written by this server (or any other openpyxl-based tool) reads back as empty until the file is opened and saved in Excel or LibreOffice. get_formulas always shows the formula text.

  • Editing can drop some features. Writes use openpyxl, which preserves values, formulas, styles, merged cells and VBA (for .xlsm), but drops charts, images and shapes from the edited workbook. Keep a copy of complex workbooks, or use --read-only for them.

  • Close the file in Excel before writing. On Windows, Excel locks open files; the server reports a clear error if it can't save.

  • .xls and .csv files are read-only. To edit one, ask Claude to copy it into a new .xlsx.

Development

pip install -e ".[dev]"
pytest                                  # unit tests plus in-process MCP protocol tests
                                        # (pytest builds its test workbooks each run; none are committed)
claude plugin validate . --strict       # check the marketplace manifest
claude plugin validate .claude-plugin/plugin.json --strict   # check the plugin manifest

Layout: excel_ops.py holds all spreadsheet logic with no MCP dependency, tools.py defines the MCP tools, and server.py is the CLI entry point. run_server.py at the root is the file the plugin runs; it imports the server from src/. .claude-plugin/ holds the plugin manifest, the marketplace manifest and the icon.

Evals

evals/ holds 20 claude plugin eval cases: every tool, edge cases (an empty sheet, a missing file, text/number/date writes), and security checks (a path outside the allowed folder, a file over 50 MB, read-only mode, a non-spreadsheet file). They run real Claude sessions against the real server, so they cost money: about $9 for the full suite at 3 runs per case. They need uv and bash on your PATH.

python evals/prepare.py    # once, with the dev environment active: generates the eval workbook and the read-only test plugin (gitignored)
claude plugin eval . --scaffold --allow-real-servers \
  --allow-tools "mcp__plugin_dws-spreadsheet_excel__*" "mcp__plugin_dws-spreadsheet-readonly_excel__*" \
  --ablation none --judge-model sonnet --max-cost-usd 15
  • --scaffold runs each case's setup.sh, which copies evals/fixtures/eval_workbook.xlsx (or generates a test file) into the run's workspace.

  • --allow-real-servers starts the real server instead of mocks.

  • The read-only case loads a test copy of the plugin whose server runs with --read-only.

  • evals/prepare.py generates both the eval workbook (from evals/fixtures/make_eval_workbook.py) and that test plugin. Both are gitignored, so the repository ships no binary files and holds only one plugin.json.

License

MIT © DWS Build

Available Tools

10 tools
apply_filterB
Read-onlyIdempotent

Filter rows by column conditions (eq, ne, gt, gte, lt, lte, between, contains, not_contains, startswith, endswith, regex, in, not_in, is_null, not_null) and return the matching rows.

Inputs: path (required), conditions (required), limit, match, +3 more.

create_sheetA
DestructiveIdempotent

Add a new sheet to an existing .xlsx/.xlsm workbook.

Inputs: name (required), path (required), index, headers.

create_workbookC
DestructiveIdempotent

Create a new .xlsx workbook, optionally with a header row.

Inputs: path (required), headers, overwrite, sheet_name.

get_formulasA
Read-onlyIdempotent

List the formulas (not values) in a range, with each cell's last cached result. .xlsx/.xlsm only.

Inputs: path (required), sheet, cell_range.

get_sheet_dataB
Read-onlyIdempotent

Return a sheet's rows as JSON records, optionally limited to some columns and paged.

Inputs: path (required), limit, sheet, offset, +2 more.

get_summary_statsB
Read-onlyIdempotent

Summary statistics per column: count, missing, min, max, mean, median, stdev and sum for numeric columns; count, unique and most common value for text columns.

Inputs: path (required), sheet, columns, header_row.

read_spreadsheetA
Read-onlyIdempotent

Open a spreadsheet and list its sheets with dimensions and a preview of the first rows.

Inputs: path (required), preview_rows.

write_cellA
DestructiveIdempotent

Write one value or formula to a cell in an .xlsx/.xlsm file. Returns the previous value.

Inputs: cell (required), path (required), value (required), sheet.

write_rangeB
DestructiveIdempotent

Write a 2D block of values (rows of cells) starting at a cell in an .xlsx/.xlsm file.

Inputs: path (required), values (required), start_cell (required), sheet.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A3.7/5.0

    Scored across 10 tools

    Disambiguation5/5

    Each tool has a clearly distinct purpose: opening/previewing workbooks, retrieving sheet data, extracting formulas, searching cells, computing summary statistics, filtering rows, writing cells/ranges, and creating sheets/workbooks. The boundaries between read, write, search, filter, and stats operations are unambiguous.

    Naming Consistency4/5

    Almost all tools follow a consistent snake_case verb_noun pattern (read_spreadsheet, get_sheet_data, write_cell, create_workbook). The lone exception is 'search', which lacks an explicit object noun, but the overall convention remains predictable.

    Tool Count5/5

    Ten tools is well-scoped for an Excel server, covering the main read, write, create, search, filter, and analysis operations without excessive redundancy or thin coverage.

    Completeness4/5

    Core lifecycle operations are present: create workbook/sheet, read data/formulas, write cells/ranges, search, filter, and summarize. Minor gaps exist for sheet/row deletion, renaming, or formatting operations, but the main data workflows are covered.

    Maintenance

    ActivityMaintained
    ResponsivenessOutdated data

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      B
      quality
      D
      maintenance
      Enables users to analyze local Excel and CSV files through natural language queries and a web dashboard while keeping data local. It supports saving specific analyses as reusable tools and building a custom analytics toolkit within Claude Desktop.
      10
      MIT
    • F
      license
      B
      quality
      D
      maintenance
      Enables Claude to directly access, query, and analyze local CSV files using natural language, keeping data private and local.
      4
      1
      -
    • A
      license
      Not graded
      quality
      C
      maintenance
      Enables Claude to search and read the user's local document collection (PDF, Word, Excel, Markdown, plain text) during a conversation by subject, by file name/path, or by exact word, and to retrieve file contents page by page. It also supports finding folders relevant to a topic and checking indexing status, with everything running locally on the user's machine.
      MIT