# How to Read an Excel File (.xlsx, .xls, .xlsm) Using Desktop Commander MCP

> Learn to read Excel files (.xlsx, .xls, .xlsm) with Desktop Commander MCP. Convert sheet data to JSON using the ExcelFileHandler class and xlsx-populate library.

- Repository: [Eduard Ruzga/DesktopCommanderMCP](https://github.com/wonderwhy-er/DesktopCommanderMCP)
- Tags: how-to-guide
- Published: 2026-07-15

---

**Desktop Commander MCP reads Excel workbooks through the `ExcelFileHandler` class, converting sheet data into JSON arrays via the `xlsx-populate` library when you call `readFile()` with optional sheet, range, offset, and length parameters.**

Desktop Commander MCP provides native support for ingesting Microsoft Excel workbooks directly into LLM workflows. When you need to read an Excel file using Desktop Commander MCP, the system automatically routes requests through a specialized handler that parses `.xlsx`, `.xls`, and `.xlsm` files and returns structured JSON data.

## How Desktop Commander MCP Handles Excel Files

The file-handling architecture relies on a factory pattern implemented in [`src/utils/files/factory.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/utils/files/factory.ts). When `readFile()` detects an Excel extension, `getFileHandler()` returns a singleton instance of the **`ExcelFileHandler`** class defined in [`src/utils/files/excel.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/utils/files/excel.ts). This handler utilizes the **`xlsx-populate`** package (declared in [`package.json`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/package.json)) to parse workbook contents without requiring Microsoft Excel to be installed.

The `ExcelFileHandler.read()` method extracts the requested data and wraps it in a **`ReadResult`** object containing:

- `content`: A `Buffer` holding the JSON string representation
- `mimeType`: Always set to `application/json` for Excel operations
- Metadata including the sheet name that was processed

## Reading Excel Files with `readFile()`

The public API exposed in [`src/tools/filesystem.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/tools/filesystem.ts) provides the `readFile()` function for all file operations.

### Basic Syntax

```typescript
import { readFile } from './dist/tools/filesystem.js';

const result = await readFile('/path/to/workbook.xlsx');
const data = JSON.parse(result.content.toString());

```

### Configuration Options

Pass an options object as the second argument to control which data is returned:

- **`sheet`**: Specify a sheet by name (`"Employees"`) or zero-based index (`1`). Defaults to the first sheet if omitted.
- **`range`**: An Excel-style range string such as `"A1:B2"`, `"C3"`, or a sheet-prefixed range like `"Sheet1!A1:B2"`. Supports spaces in sheet names using the quoted form (`"'My Sheet'!A1:B2"`).
- **`offset`**: Number of rows to skip before reading. Negative values count from the end of the sheet for tail reads.
- **`length`**: Maximum number of rows to return after applying the offset.

These options are fully demonstrated in the repository's test suite at [`test/test-excel-files.js`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/test/test-excel-files.js).

## Practical Code Examples

**Reading the entire first sheet:**

```typescript
const whole = await readFile('report.xlsx');
// result.mimeType === 'application/json'
// result.content contains Buffer with full sheet data

```

**Selecting a specific sheet and range:**

```typescript
const sales = await readFile('sales.xlsx', {
  sheet: '2024_Q1',
  range: 'A2:D20'
});
const data = JSON.parse(sales.content.toString());

```

**Skipping headers with offset and length:**

```typescript
const body = await readFile('log.xlsx', {
  offset: 1,    // Skip header row
  length: 2     // Return only next 2 rows
});

```

**Using sheet-prefixed ranges:**

```typescript
const subset = await readFile('data.xlsx', {
  range: `'My Sheet'!B3:C5`
});

```

## Error Handling Behavior

The `ExcelFileHandler` normalizes error messages to guide users toward correct syntax. If you supply a malformed range string, the error response includes a hint showing the supported `"SheetName!A1:B2"` format, as verified in the *"Invalid range must throw"* test case within [`test/test-excel-files.js`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/test/test-excel-files.js).

## Core Implementation Files

Understanding the source architecture helps when debugging or extending functionality:

- **[`src/utils/files/excel.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/utils/files/excel.ts)**: Implements `ExcelFileHandler` including read, write, edit, and metadata extraction logic.
- **[`src/utils/files/factory.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/utils/files/factory.ts)**: Contains `getFileHandler()` which routes Excel extensions to the appropriate singleton handler.
- **[`src/tools/filesystem.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/tools/filesystem.ts)**: Exposes the public `readFile()` API that forwards calls to the handler layer.
- **[`test/test-excel-files.js`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/test/test-excel-files.js)**: Comprehensive test suite covering all read options and edge cases.
- **[`package.json`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/package.json)**: Declares the `xlsx-populate` dependency used for workbook parsing.

## Summary

Reading an Excel file using Desktop Commander MCP involves these key points:

- The system automatically detects Excel extensions (`.xlsx`, `.xls`, `.xlsm`) and routes them through `ExcelFileHandler` via the factory in [`src/utils/files/factory.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/utils/files/factory.ts).
- The **`xlsx-populate`** library parses workbooks server-side without requiring Microsoft Excel installation.
- Output is always returned as **`application/json`** in a `ReadResult` object containing a `Buffer`.
- You can filter data using **`sheet`**, **`range`**, **`offset`**, and **`length`** options.
- Sheet names with spaces require quoted range syntax (`"'Sheet Name'!A1:B2"`).

## Frequently Asked Questions

### What Excel file formats does Desktop Commander MCP support?

Desktop Commander MCP supports `.xlsx`, `.xls`, and `.xlsm` extensions. The `ExcelFileHandler` class in [`src/utils/files/excel.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/utils/files/excel.ts) processes these formats using the `xlsx-populate` library, enabling read operations without native Excel dependencies.

### How do I read a specific sheet from an Excel workbook?

Use the `sheet` option in your `readFile()` call. You can reference the sheet by its name (string) or zero-based index (number). If you omit this option, Desktop Commander MCP defaults to reading the first sheet in the workbook.

### Can I read only a portion of a sheet, like a specific cell range?

Yes. Pass a `range` option using standard Excel notation such as `"A1:B10"` or `"Sheet1!C3:D5"`. For sheet names containing spaces, use the quoted form: `"'My Sheet'!A1:B2"`. This is processed directly by the `ExcelFileHandler` to extract only the requested cells.

### Why is the returned content a Buffer instead of a plain object?

The `ReadResult` object returns a `Buffer` in the `content` field to maintain consistency across all file types in Desktop Commander MCP. For Excel files, this Buffer contains a UTF-8 JSON string representation of the two-dimensional array. Convert it using `JSON.parse(result.content.toString())` to access the array data.