Skip to content

Behavioral Rules

These rules ensure efficient and reliable Excel automation. AI assistants should follow these guidelines when executing Excel operations.

System Prompt Rules (LLM-Validated)

These rules are validated by automated LLM tests and MUST be followed:

  • Execute tasks immediately without asking for confirmation
  • Never ask clarifying questions - make reasonable assumptions and proceed
  • Ask the user whether they want Excel visible or hidden when starting multi-step tasks
  • When the user asks to "show Excel" or "watch" the work, use window(show) + window(arrange) to position it
  • Format Excel files professionally (proper column widths, headers, number formats)
  • Always format data ranges as Excel Tables (not plain ranges)
  • Always end with a text summary - never end on just a tool call or command

CRITICAL: No Clarification Questions

STOP. If you are about to ask "Which file?", "What table?", "Where should I put this?" - DON'T.

Instead, discover the information yourself:

Bad (Asking) Good (Discovering)
"Which Excel file should I use?" file(list) → use the open session
"What's the table name?" table(list) → discover tables
"Which sheet has the data?" worksheet(list) → check all sheets
"Should I create a PivotTable?" YES - create it on a new sheet
"What values should I filter?" Read the data first, then filter appropriately

You have tools to answer your own questions. USE THEM.

Core Execution Rules

Execute Immediately

Do NOT ask clarifying questions for standard operations. Proceed with reasonable defaults:

  • File creation: Create the file and report the path
  • Data operations: Execute the operation and report results
  • Formatting: Apply formatting and confirm completion

When to ask: Only when the request is genuinely ambiguous (e.g., "update the data" without specifying what data or which file).

Ask About Excel Visibility

When starting a multi-step task, ask the user whether they want Excel visible or hidden. Present two clear action card choices:

Watch me work — Show Excel side-by-side so you see every change live. Operations run slightly slower because Excel renders each update on screen.

Work in background — Keep Excel hidden for maximum speed. You won't see changes until the task is done, but operations complete faster.

Skip asking when the user has already stated a preference: - User says "show me Excel", "let me watch", "I want to see it" → Show immediately - User says "just do it", "work in background" → Keep hidden - Simple one-shot operations (e.g., "what's in A1?") → Keep hidden, no need to ask

If the user doesn't respond, keep Excel hidden.

How to show Excel:

1. window(action: 'show')                         → Make visible
2. window(action: 'arrange', preset: 'left-half') → Position for side-by-side

Do NOT: - Show Excel without the user choosing to see it - Tell users to look at Excel windows unless Excel is visible - Reference Excel UI elements when Excel is hidden - Suggest manual Excel interactions

Format Professionally

When creating or modifying Excel files:

  • Set appropriate column widths for content
  • Apply header formatting (bold, filters)
  • Use proper number formats (currency, dates, percentages) with range set-number-format
  • Auto-fit variable-width data with range_format auto-fit-columns or range_format auto-fit-rows
  • Format data as Excel Tables (not plain ranges)
  • When the same visual styling applies to multiple disjoint ranges on one sheet, use range_format format-ranges

Tool split to remember: - range owns number display formats such as dates, currency, percentages, and text display - range_format owns visual styling, validation, auto-fit, and explicit width/height changes

Use set-style for semantic status labels and document structure: - Good / Bad / Neutral — colour-coded status cells (green/red/yellow fills, theme-aware) - Heading 1 / Heading 2 / Title — document hierarchy - Normal — reset all formatting

Use format-range for visual layout (header rows, custom colours) — ALL properties in ONE call: - set-style('Heading 1') does NOT apply a fill colour; if you want a coloured header row use format-range - Pass bold, fill_color, font_color, and alignment together in a single call — do not call format-range multiple times for the same range - If the same formatting payload repeats across multiple non-contiguous ranges, prefer one format-ranges call over repeated format-range calls

Apply each formatting operation once — do not reapply the same properties to the same range unless a later step explicitly changes them.

Format Cells by Data Type (CRITICAL)

Always apply number formats after setting values. Without formatting: - Dates appear as serial numbers (45678 instead of 2025-01-22) - Currency appears as plain numbers (1234.56 instead of $1,234.56) - Percentages appear as decimals (0.15 instead of 15%)

Common format codes (US locale, auto-translated):

Data Type Format Code Result (en-US)
USD $#,##0.00 $1,234.56
EUR €#,##0.00 €1,234.56
Number #,##0.00 1,234.56
Percent 0.00% 15.00%
Date (ISO) yyyy-mm-dd 2025-01-22
Date (US) mm/dd/yyyy 01/22/2025

Rendered output is locale-dependent. The Result column assumes en-US regional settings. Excel interprets , and . in a format code according to the user's locale, so $#,##0.00 displays as $1,234.56 on en-US but $1.234,56 on de-DE — same code, different separators. Always write the US form (it is auto-translated), never promise a literal rendering, and never "correct" a format code because a screenshot shows swapped separators.

Workflow:

1. range set-values (data is now in cells)
2. range set-number-format (apply format to range)
3. range_format auto-fit-columns (widen columns to fit — formatted dates and
   long numbers render as ##### at the default column width)

Format Tabular Data as Excel Tables

Always convert tabular data to Excel Tables (ListObjects):

1. range set-values (write data including headers)
2. table(action: 'create', table_name: 'SalesData', range_address: 'A1:D100')

Why Tables over plain ranges: - Structured references: =SUM(Sales[Amount]) instead of =SUM(B2:B100) - Auto-expand when rows are added - Built-in filtering, sorting, and banded rows - Required for add-to-data-model action (Data Model/DAX) - Named reference for Power Query: Excel.CurrentWorkbook(){[Name="SalesData"]}

When NOT to use Tables: - Single-cell parameters (use named ranges instead) - Layout areas with merged cells - Print-formatted reports with specific spacing

Named range listing: namedrange list returns visible user-defined names. Hidden/internal Excel names, including Power Query ExternalData_* and AutoFilter names, are omitted before value inspection. Large named ranges return metadata without a value preview; use namedrange read or range get-values when the actual value is needed.

Report Results

After completing operations, report:

  • What was created/modified
  • File path (for new files)
  • Any relevant statistics (row counts, etc.)

CRITICAL: Always End With a Text Response

NEVER end your turn with only a tool call or command execution. After all operations are complete, you MUST provide a text message summarizing what was accomplished.

Bad (Silent completion) Good (Text summary)
(tool call with no text) "Created PivotTable 'SalesPivot' with tabular layout on the Analysis sheet."
(just runs a command) "Set the PivotTable to compact layout (row fields in a single indented column)."

Why: Users and automation expect a text confirmation. A silent tool call or command with no follow-up text is an incomplete response.

Session Lifecycle

Use file(action: 'test') or excelcli -q session test <path> before opening when access or information protection is uncertain. The shared result reports canOpen, isIrmProtected, willOpenReadOnly, and requiresVisibleSession. IRM/AIP files report canOpen:false until the required interactive Excel authentication occurs; open them with a visible session.

Always close sessions when done:

1. file(action: 'open', path: '...')  → sessionId
2. All operations use `session_id`
3. file(action: 'close', session_id: '...', save: true)  → saves and closes

Why: Unclosed sessions leave Excel processes running, consuming memory and locking files.

Format Results as Tables

When presenting data to users, format as Markdown tables:

| Column A | Column B | Column C |
|----------|----------|----------|
| Value 1  | Value 2  | Value 3  |

NOT as raw JSON arrays: [["Column A","Column B"],["Value 1","Value 2"]]

Data Model Output Rules

Choose the Right Display Method

When displaying Data Model data:

Scenario Use NOT
Show DAX query results table create-from-dax PivotTable
Static report/snapshot table create-from-dax PivotTable
Data needed in formulas table create-from-dax PivotTable
User needs interactive filtering pivottable DAX table
Cross-tabulation layout pivottable DAX table

Why: PivotTables add UI complexity (field panes, refresh prompts) that's unnecessary for simple data display. DAX-backed tables are cleaner for presenting query results.

Chart Data Model Data Directly

When creating charts from Data Model:

  • Use: chart create-from-pivottable (creates and verifies a live PivotChart)
  • NOT: Create a regular chart from the PivotTable's displayed cell range

Why: The verified PivotLayout link keeps field changes and refreshes live.

Data Modification Rules

Verify Before Delete

Before deleting tables, worksheets, or named ranges:

  1. List existing items first
  2. Confirm the exact name exists
  3. Delete the specified item

Why: Delete operations cannot be undone. Verification prevents accidental data loss.

Targeted Updates Over Wholesale Replace

When updating data:

  • Prefer: set-values on specific range (e.g., A5:C5 for row 5)
  • Avoid: Deleting and recreating entire structures

Why: Targeted updates preserve formatting, formulas, and references that wholesale replacement destroys.

Save Explicitly

Call file(action: 'close', save: true) to persist changes:

  • Operations modify the in-memory workbook
  • Changes are NOT automatically saved to disk
  • Session termination WITHOUT save loses all changes

Workflow Sequencing Rules

Data Model Prerequisites

DAX operations require tables in the Data Model:

Step 1: Create or import data → Table exists
Step 2: table(action: 'add-to-data-model') → Table in Data Model
Step 3: datamodel(action: 'create-measure') → NOW this works

Skipping Step 2 causes DAX operations to fail with "table not found".

Power Query Load Destinations

Choose load destination based on workflow:

Destination When to Use
worksheet / load-to-table View data, simple analysis
data-model / load-to-data-model DAX measures, PivotTables, relationships
both / load-to-both View data AND use in DAX
connection-only Data staging, intermediate queries

Values are case-insensitive. Unknown enum values and parameters that do not belong to the selected action are rejected instead of being defaulted or ignored.

Canonical Public Inputs

  • Public timeouts are integer seconds: MCP uses timeout_seconds, CLI uses --timeout, and batch JSON uses timeout. Do not send TimeSpan strings or numeric strings.
  • Session open/create accepts 10-3600 seconds. Its operation timeout controls workbook startup and operations that do not provide a dedicated data-operation timeout.
  • Power Query refresh/refresh-all accepts 0-2147483; omitted or 0 uses the 30-minute data-operation default. Connection, Data Model, PivotTable, and VBA timeouts accept 1-2147483.
  • Power Query refresh/refresh-all use their data-operation timeout instead of layering the session operation timeout. load-to has no caller timeout and uses the fixed 30-minute data-operation timeout; create/update/evaluate use the session operation timeout.
  • For required generated inline/file pairs, supply exactly one form. Optional pairs may omit both, but inline and file forms are always mutually exclusive. Batch aliases are mCodeFile, vbaCodeFile, daxFormulaFile, daxQueryFile, dmvQueryFile, schemaFile, and xmlDataFile; MCP uses snake_case and CLI uses kebab-case. The file must exist and be readable.

Refresh After Create

powerquery(action: 'create') imports the M code but does NOT execute it:

Step 1: powerquery(action: 'create', ...) → Query created
Step 2: powerquery(action: 'refresh', query_name: '...') → Data loaded

Without refresh, the query exists but contains no data.

Error Handling Rules

Interpret Error Messages

Excel MCP errors include actionable context:

{
  "success": false,
  "errorMessage": "Table 'Sales' not found in Data Model",
  "suggestedNextActions": ["table(action: 'add-to-data-model', table_name: 'Sales')"]
}

Follow suggestedNextActions when provided.

Use the structured errorCategory when it is present. For InvalidInput, NotFound, or Conflict, correct the named input or workbook state before retrying. For SessionNotFound, reopen the workbook once and continue with the new session ID. A timeout, cancellation, or dead Excel process can invalidate and close the session; reopen it instead of retrying against the old session.

Retry with Corrections

If an operation fails:

  1. Read the error message carefully
  2. Check prerequisites (session, table in Data Model, etc.)
  3. Retry with corrected parameters

Do NOT immediately re-run the same failing command.

Report Failures Clearly

When operations fail:

  • State what was attempted
  • Explain what went wrong
  • Suggest the corrective action

Good: "Failed to add DAX measure: Table 'Sales' is not in the Data Model. Use table(action: 'add-to-data-model') first."

Bad: "An error occurred."