Read and write Excel spreadsheets (XLSX) via @negokaz/excel-mcp-server (npx)
How do I read and write Excel (.xlsx) files via MCP? I need to: create sheets with tabular data, write Excel formulas (IF, SUM, etc.), read back computed values, inspect formulas, and list sheet metadata. The server should be credential-free and run locally via npx.
Recipe: Read & write Excel spreadsheets via @negokaz/excel-mcp-server
Setup
npx -y @negokaz/excel-mcp-serverTransport: stdio, newline-delimited JSON (NOT Content-Length framing — this server parses each \n-terminated line as a JSON-RPC message; Content-Length headers cause parse errors).
Quirk: the server cannot create .xlsx files from scratch. You must provide an existing .xlsx file. Create one with python3 -c "import openpyxl; openpyxl.Workbook().save('file.xlsx')" or any other method before calling write tools.
Server info
- Name: excel-mcp-server
- Version: 0.12.0
- Cold start: ~560–970ms (npx cache warm)
- Tool call latency: ~50ms per call
Tools (6 total)
| Tool | Description |
|---|---|
excel_write_to_sheet | Write a 2D array of values to a range; supports formulas starting with = |
excel_read_sheet | Read values from a sheet with pagination; showFormula: true returns raw formulas |
excel_describe_sheets | List all sheets with used ranges, tables, pivot tables, and paging ranges |
excel_format_range | Apply cell styles (font, fill, border, number format) to a range |
excel_copy_sheet | Duplicate a sheet under a new name |
excel_create_table | Define a named Excel table on a range |
Key parameter names
fileAbsolutePath(notfile_path) — absolute path to the .xlsx filesheetName— target sheet namenewSheet: true— creates the sheet;falsewrites to existingrange— e.g."A1:C4"values— 2D array:[["Name","Score"],[" Alice",95]]
Real execution trace
Write tabular data with headers + formulas to a new sheet, then read back computed values, inspect raw formulas, and describe sheet metadata — all on a single .xlsx file.
Formula =IF(C2>=90,"A","B") correctly evaluates: Alice (95) → "A", Bob (87) → "B", Carol (92) → "A".
Failure modes
- File does not exist: returns
{"code":-32603,"message":"open /path/to/file.xlsx: no such file or directory"}. Must pre-create the file. - Wrong tool name: returns
{"code":-32602,"message":"tool 'write_cell' not found: tool not found"}. Useexcel_write_to_sheetnotwrite_cell. - Content-Length framing: causes
{"code":-32700,"message":"Parse error"}— TWO parse errors per message (one for the header line, one for the empty separator). Use bare JSON +\ninstead. - newSheet: true on existing sheet: overwrites the sheet contents (destructive).
Total execution time
1,225ms for full round-trip (init + 2 writes + 2 reads + describe), all tool calls ~50ms each.
{ "server": "@negokaz/excel-mcp-server", "version": "0.12.0", "transport": "stdio", "framing": "newline-delimited JSON (NOT Content-Length)", "launcher": "npx -y @negokaz/excel-mcp-server", "prerequisite": "existing .xlsx file required (server cannot create from scratch)", "tools_count": 6, "tools": ["excel_write_to_sheet", "excel_read_sheet", "excel_describe_sheets", "excel_format_range", "excel_copy_sheet", "excel_create_table"], "init": { "request": { "jsonrpc": "2.0", "id": 1, "method": "initialize", "params": { "protocolVersion": "2024-11-05", "capabilities": {}, "clientInfo": { "name": "pathfinder", "version": "1.0.0" } } }, "response": { "protocolVersion": "2024-11-05", "capabilities": { "tools": { "listChanged": true } }, "serverInfo": { "name": "excel-mcp-server", "version": "0.12.0-SNAPSHOT-1ff4340" } }, "latency_ms": 968 }, "write_tabular_data": { "request": { "jsonrpc": "2.0", "id": 3, "method": "tools/call", "params": { "name": "excel_write_to_sheet", "arguments": { "fileAbsolutePath": "/tmp/pathfinder-excel/demo.xlsx", "sheetName": "Scores", "newSheet": true, "range": "A1:C4", "values": [ ["Name", "Subject", "Score"], ["Alice", "Math", 95], ["Bob", "Physics", 87], ["Carol", "Math", 92] ] } } }, "response_html": "<table><tr><th></th><th>A</th><th>B</th><th>C</th></tr><tr><th>1</th><td>Name</td><td>Subject</td><td>Score</td></tr><tr><th>2</th><td>Alice</td><td>Math</td><td>95</td></tr><tr><th>3</th><td>Bob</td><td>Physics</td><td>87</td></tr><tr><th>4</th><td>Carol</td><td>Math</td><td>92</td></tr></table>", "latency_ms": 52 }, "write_formulas": { "request": { "jsonrpc": "2.0", "id": 4, "method": "tools/call", "params": { "name": "excel_write_to_sheet", "arguments": { "fileAbsolutePath": "/tmp/pathfinder-excel/demo.xlsx", "sheetName": "Scores", "newSheet": false, "range": "D1:D4", "values": [ ["Grade"], ["=IF(C2>=90,"A","B")"], ["=IF(C3>=90,"A","B")"], ["=IF(C4>=90,"A","B")"] ] } } }, "response_confirms_formulas": true, "latency_ms": 51 }, "read_computed_values": { "request": { "jsonrpc": "2.0", "id": 5, "method": "tools/call", "params": { "name": "excel_read_sheet", "arguments": { "fileAbsolutePath": "/tmp/pathfinder-excel/demo.xlsx", "sheetName": "Scores" } } }, "response_html": "<table><tr><th></th><th>A</th><th>B</th><th>C</th><th>D</th></tr><tr><th>1</th><td>Name</td><td>Subject</td><td>Score</td><td>Grade</td></tr><tr><th>2</th><td>Alice</td><td>Math</td><td>95</td><td>A</td></tr><tr><th>3</th><td>Bob</td><td>Physics</td><td>87</td><td>B</td></tr><tr><th>4</th><td>Carol</td><td>Math</td><td>92</td><td>A</td></tr></table>", "note": "Formulas evaluated: IF(95>=90) → A, IF(87>=90) → B, IF(92>=90) → A", "latency_ms": 51 }, "read_raw_formulas": { "request": { "jsonrpc": "2.0", "id": 6, "method": "tools/call", "params": { "name": "excel_read_sheet", "arguments": { "fileAbsolutePath": "/tmp/pathfinder-excel/demo.xlsx", "sheetName": "Scores", "showFormula": true } } }, "response_shows_formulas": "=IF(C2>=90,"A","B") etc. in column D", "latency_ms": 51 }, "describe_sheets": { "request": { "jsonrpc": "2.0", "id": 7, "method": "tools/call", "params": { "name": "excel_describe_sheets", "arguments": { "fileAbsolutePath": "/tmp/pathfinder-excel/demo.xlsx" } } }, "response": { "backend": "excelize", "sheets": [ { "name": "Sheet", "usedRange": "A1:A1", "tables": [], "pivotTables": [], "pagingRanges": ["A1:A1"] }, { "name": "Scores", "usedRange": "A1:D4", "tables": [], "pivotTables": [], "pagingRanges": ["A1:D4"] } ] }, "latency_ms": 51 }, "total_latency_ms": 1225 }