npx skills add ...
npx skills add sbroenne/mcp-server-excel --skill excel-cli
Excel CLI automation skill for Windows workbooks. Use when a coding agent needs token-efficient, scriptable, or unattended Excel automation via excelcli commands. Best for CI/CD, scheduled jobs, batch processing, PowerShell workflows, and bulk workbook edits. Supports Power Query, DAX, PivotTables, Tables, Ranges, Charts, VBA, Data Models, screenshots, and formatting. Triggers: excelcli, Excel CLI, command line, batch, script, automation, CI/CD, scheduled, PowerShell, unattended, coding agent, workbook processing.
npx skills add sbroenne/mcp-server-excel --skill excel-cli
excelcli directly, so it must resolve on PATH.
Installing the excel-cli plugin does not put it there — the global shim is opt-in. Run
com.github.copilot\bin\install-global.ps1 from the installed plugin folder once (it writes
excelcli.cmd / excelcli.ps1 into ~\.copilot\bin and adds that to your user PATH), or
install the runtime independently via the standalone release zip or
dotnet tool install --global Sbroenne.ExcelMcp.CLI.
If excelcli is not found, report that and stop — do not guess at a path.PLUGIN_DATA\runtime; release freshness is checked once per Copilot session. The optional
global shim falls back to ~\.copilot\plugin-runtime\mcp-server-excel\excel-cli and checks
for updates at most once every 24 hours.| Step | Command | When |
|---|---|---|
| 1. Session | session create/open | Always first |
| 2. Sheets | sheet create/rename | If needed |
| 3. Write data | See below | If writing values |
| 4. Save & close | session close --save | Always last |
10+ commands? Use
excelcli -q batch --input commands.json— sends all commands in one process with automatic session management. See Rule 8.
Writing Data (Step 3):
--values takes a JSON 2D array string: --values '[["Header1","Header2"],[1,2]]'--range A1:B1 --values '[["Name","Age"]]'"text". Numbers are bare: 42⚡ Building dashboards or bulk operations? Skip to Rule 8: Batch Mode — it eliminates per-command process overhead and auto-manages session IDs.
Execute commands to discover the answer instead:
| DON'T ASK | DO THIS INSTEAD |
|---|---|
| "Which file should I use?" | excelcli -q session list |
| "What table should I use?" | excelcli -q table list --session <id> |
| "Which sheet has the data?" | excelcli -q sheet list --session <id> |
You have commands to answer your own questions. USE THEM.
NEVER end your turn with only a command execution. After completing all operations, always provide a brief text message confirming what was done. Silent command-only responses are incomplete.
Creating vs Opening Files:
CRITICAL: Use session create for new files. session open on non-existent files will fail!
CRITICAL: ALWAYS use the session ID returned by session create or session open in subsequent commands. NEVER guess or hardcode session IDs. The session ID is in the JSON output (e.g., {"sessionId":"abc123"}). Parse it and use it.
Unclosed sessions leave Excel processes running, locking files.
DAX operations require tables in the Data Model:
BEST PRACTICE: Test M code before creating permanent queries
If you see "File not found" or "Path not found" - STOP and report to user. Don't retry.
When writing many values/formulas (10+ cells), disable auto-recalc for performance:
When executing 10+ commands on the same file, use excelcli batch to send all commands in a single process launch. This avoids per-process startup overhead and terminal buffer saturation.
Key features:
session.open/create result sessionId auto-injected into subsequent commands — no need to parse and pass session IDs{"index": 0, "command": "...", "success": true, "result": {...}}--stop-on-error: Exit on first failure (default: continue all)--session <id>: Pre-set session ID for all commands (skip session.open)Input formats:
excelcli -q batch --input commands.jsonGet-Content commands.ndjson | excelcli -q batchFull reference: See CLI command reference and common pitfalls, or run excelcli <command> --help for live help from the installed runtime.
Syntax rule: CLI commands use excelcli -q <command> <action> --session <id> --kebab-case-flags .... Do not use MCP call syntax such as range(action: ...), snake_case parameters, or underscore tool names. The CLI command names remove MCP underscores: calculation_mode becomes calculationmode, range_format becomes rangeformat, chart_config becomes chartconfig, and data_model becomes datamodel.
Available command groups:
session, batch, service, analysis, calculationmode, chart, chartconfig, conditionalformat, connection, datamodel, datamodelrelationship, drawing, namedrange, pivottable, pivottablecalc, pivottablefield, powerquery, pythoninexcel, querytable, range, rangeedit, rangeformat, rangelink, screenshot, sheet, worksheetstyle, slicer, table, tablecolumn, vba, window, workbook, xmlmap
See CLI command reference and common pitfalls for examples. Key issues:
--values-file expects a path to an existing file; use --values for inline JSON.--timeout ranges are action-specific: session open/create accepts 10-3600; Power Query refresh/refresh-all accepts 0-2147483 (0 keeps the default); other generated timeout actions accept 1-2147483.--values takes a 2D JSON array such as '[["Name","Age"],["Alice",30]]'.--selected-items require JSON arrays.# Example: capture session ID from output, then use it
excelcli -q session create C:\path\file.xlsx # Returns JSON with sessionId
excelcli -q range set-values --session <returned-session-id> ...
excelcli -q session close --session <returned-session-id> --saveexcelcli -q table add-to-data-model --session <id> --table-name Sales # Step 1
excelcli -q datamodel create-measure --session <id> ... # Step 2 - NOW works# Step 1: Create/open a session and capture the session ID
$session = excelcli -q session create C:\path\file.xlsx | ConvertFrom-Json
$sessionId = $session.sessionId
# Step 2: Test M code without persisting (catches errors early)
excelcli -q powerquery evaluate --session $sessionId --m-code-file query.m
# Step 3: Create permanent query with validated code
excelcli -q powerquery create --session $sessionId --query-name Q1 --m-code-file query.m
# Step 4: Load data to destination
excelcli -q powerquery refresh --session $sessionId --query-name Q1
# Step 5: Close session
excelcli -q session close --session $sessionId --save# 1. Create/open a session and capture the session ID
$session = excelcli -q session create C:\path\file.xlsx | ConvertFrom-Json
$sessionId = $session.sessionId
# 2. Set manual mode
excelcli -q calculationmode set-mode --session $sessionId --mode manual
# 3. Write data row by row for reliability
excelcli -q range set-values --session $sessionId --sheet Sheet1 --range A1:B1 --values '[["Name","Amount"]]'
excelcli -q range set-values --session $sessionId --sheet Sheet1 --range A2:B2 --values '[["Salary",5000]]'
# 4. Recalculate once at end
excelcli -q calculationmode calculate --session $sessionId --scope workbook
# 5. Restore automatic mode
excelcli -q calculationmode set-mode --session $sessionId --mode automatic
# 6. Close session
excelcli -q session close --session $sessionId --save# Create a JSON file with all commands
@'
[
{"command": "session.open", "args": {"filePath": "C:\\path\\file.xlsx"}},
{"command": "range.set-values", "args": {"sheetName": "Sheet1", "rangeAddress": "A1", "values": [["Hello"]]}},
{"command": "range.set-values", "args": {"sheetName": "Sheet1", "rangeAddress": "A2", "values": [["World"]]}},
{"command": "session.close", "args": {"save": true}}
]
'@ | Set-Content commands.json
# Execute all commands at once
excelcli -q batch --input commands.json