Skip to main content
Glama
README.md
# LibreOffice MCP Tools

[![npm version](https://img.shields.io/npm/v/@passerbyflutter/libreoffice-mcp-tools.svg)](https://npmjs.org/package/@passerbyflutter/libreoffice-mcp-tools)

> [!WARNING]
> This project was **written by GitHub Copilot** and has not been fully reviewed by a human.
> Code may contain bugs, security issues, or unexpected behavior. **Use at your own risk.** Do not use in production without thorough review.

A [Model Context Protocol (MCP)](https://modelcontextprotocol.io) server that gives AI agents (Claude, Copilot, Gemini, Cursor, etc.) the ability to **read, write, and edit Office documents** via LibreOffice โ€” with a token-efficient design that minimizes LLM context usage.

Inspired by the architecture of [chrome-devtools-mcp](https://github.com/ChromeDevTools/chrome-devtools-mcp).

## โœจ Features

- **22 MCP tools** covering reading, writing, spreadsheets, and presentations
- **Token-efficient design**: outline-first navigation, range-based access, pagination
- **Broad format support**: DOCX, DOC, XLSX, XLS, PPTX, PPT, ODT, ODS, ODP, RTF, CSV, TXT, PDF
- **Legacy format bridge**: `.doc`, `.xls`, `.ppt` auto-converted via LibreOffice before parsing
- **No LibreOffice required for basic reads**: native parsers handle DOCX, XLSX, PPTX directly
- **LibreOffice required for**: legacy formats, PDF export, format conversion

## ๐Ÿ“‹ Supported Formats

| Format | Extensions | Read | Write | Method |
|---|---|---|---|---|
| Word 2007+ | `.docx`, `.dotx` | โœ… | โœ… | Native (mammoth read / JSZip OOXML write) |
| Word 97-2003 | `.doc`, `.dot` | โœ… | โœ… | LibreOffice bridge |
| Excel 2007+ | `.xlsx`, `.xlsm` | โœ… | โœ… | Native (ExcelJS) |
| Excel 97-2003 | `.xls` | โœ… | โœ… | LibreOffice bridge |
| PowerPoint 2007+ | `.pptx` | โœ… | โœ… | Native (JSZip OOXML) |
| PowerPoint 97-2003 | `.ppt` | โœ… | โœ… | LibreOffice bridge |
| OpenDocument Text | `.odt` | โœ… | โœ… | LibreOffice bridge |
| OpenDocument Spreadsheet | `.ods` | โœ… | โœ… | LibreOffice bridge |
| OpenDocument Presentation | `.odp` | โœ… | โœ… | LibreOffice bridge |
| Rich Text Format | `.rtf` | โœ… | โœ… | LibreOffice bridge |
| CSV | `.csv` | โœ… | โœ… | Native |
| PDF | `.pdf` | โœ… (text) | โŒ | LibreOffice CLI |
| Plain text | `.txt` | โœ… | โœ… | Native |

## ๐Ÿš€ Quick Start

### Prerequisites

- **Node.js 20+**
- **LibreOffice** (optional for basic DOCX/XLSX/PPTX reads; required for .doc/.xls/.ppt and format conversion)
  - Windows: [Download LibreOffice](https://www.libreoffice.org/download/download/)
  - macOS: `brew install --cask libreoffice`
  - Linux: `sudo apt install libreoffice` or `sudo dnf install libreoffice`

### Installation

**Using npx (recommended โ€” no install needed):**

```json
{
  "mcpServers": {
    "libreoffice": {
      "command": "npx",
      "args": ["-y", "@passerbyflutter/libreoffice-mcp-tools"]
    }
  }
}
```

**Global install:**

```bash
npm install -g @passerbyflutter/libreoffice-mcp-tools
```

**From source:**

```bash
git clone https://github.com/passerbyflutter/libreoffice-mcp-tools
cd libreoffice-mcp-tools
npm install
npm run build
```

### Configure your MCP client

Add to your MCP client configuration (e.g., Claude Desktop `claude_desktop_config.json`):

```json
{
  "mcpServers": {
    "libreoffice": {
      "command": "npx",
      "args": ["-y", "@passerbyflutter/libreoffice-mcp-tools"],
      "env": {
        "SOFFICE_PATH": "/path/to/soffice"
      }
    }
  }
}
```

Or use `.mcp.json` at your project root:

```json
{
  "mcpServers": {
    "libreoffice": {
      "command": "npx",
      "args": ["-y", "@passerbyflutter/libreoffice-mcp-tools"]
    }
  }
}
```

### CLI Options

```
node build/bin/libreoffice-mcp.js [options]

  --libreoffice-path <path>   Path to soffice executable
                              (default: auto-detected or SOFFICE_PATH env)
```

## ๐Ÿ›  Tool Reference

### Document Management

| Tool | Description |
|---|---|
| `document_open` | Open a file โ†’ returns `docId` handle. Auto-bridges legacy formats. |
| `document_close` | Release document handle and temp files |
| `document_list` | List all open documents |
| `document_create` | Create new empty document (writer/calc/impress) |
| `document_save` | Save to current or new path |
| `document_export` | Export via LibreOffice (PDF, HTML, CSV, etc.) |
| `document_convert` | Convert file format (DOCโ†’DOCX, XLSXโ†’CSV, etc.) |

### Reading (Token-Efficient)

| Tool | Description |
|---|---|
| `document_get_metadata` | Title, author, word/page count, dates |
| `document_get_outline` | Headings (Writer) / sheet names (Calc) / slide titles (Impress) |
| `document_read_text` | Paginated document text as Markdown |
| `document_read_range` | Specific paragraph or slide range |
| `document_search` | Find text with surrounding context |

### Writing (Writer)

| Tool | Description |
|---|---|
| `document_insert_text` | Insert at start/end/after heading |
| `document_replace_text` | Find & replace (first or all occurrences) |
| `document_insert_paragraph` | Insert paragraph at specific index |
| `document_apply_style` | Apply heading/paragraph style |

### Spreadsheet (Calc)

| Tool | Description |
|---|---|
| `spreadsheet_list_sheets` | Sheet names with row/col counts |
| `spreadsheet_get_range` | Cell range as JSON + markdown table |
| `spreadsheet_set_cell` | Set cell value or formula |
| `spreadsheet_set_range` | Set 2D range of values |
| `spreadsheet_add_sheet` | Add new sheet |
| `spreadsheet_get_formulas` | Get formula expressions in range |

### Presentation (Impress)

| Tool | Description |
|---|---|
| `presentation_list_slides` | Slide titles with index |
| `presentation_get_slide` | Full slide content (title, body, notes) |
| `presentation_get_notes` | Speaker notes |
| `presentation_add_slide` | Add new slide (requires LibreOffice) |
| `presentation_update_slide` | Update slide content |

## ๐Ÿ’ก Token-Saving Workflow

For maximum token efficiency, follow this pattern:

```
1. document_open(filePath) โ†’ get docId
2. document_get_metadata(docId) โ†’ understand size/type
3. document_get_outline(docId) โ†’ see structure
4. document_read_range(docId, startIndex=N, endIndex=M) โ†’ read specific section
```

Instead of dumping the entire document, you navigate to exactly what you need.

**Spreadsheet workflow:**
```
1. document_open(path) โ†’ docId
2. spreadsheet_list_sheets(docId) โ†’ see all sheets
3. spreadsheet_get_range(docId, sheetName="Sales", range="A1:D20") โ†’ targeted data
```

## ๐Ÿ— Architecture

```
src/
โ”œโ”€โ”€ index.ts                # createMcpServer() โ€” MCP server factory
โ”œโ”€โ”€ LibreOfficeAdapter.ts   # soffice subprocess manager
โ”œโ”€โ”€ DocumentContext.ts      # Open document registry
โ”œโ”€โ”€ DocumentSession.ts      # Per-document state + format bridge
โ”œโ”€โ”€ McpResponse.ts          # Response builder (text/JSON/markdown)
โ”œโ”€โ”€ Mutex.ts                # Serializes LibreOffice subprocess calls
โ”œโ”€โ”€ parsers/
โ”‚   โ”œโ”€โ”€ DocxParser.ts           # DOCX read โ†’ {paragraphs, outline, metadata} (mammoth)
โ”‚   โ”œโ”€โ”€ DocxOoxmlEditor.ts      # DOCX write โ†’ direct JSZip OOXML manipulation (format-preserving)
โ”‚   โ”œโ”€โ”€ XlsxParser.ts           # XLSX read/write via ExcelJS
โ”‚   โ”œโ”€โ”€ PptxParser.ts           # PPTX read โ†’ {slides[]} (JSZip XML)
โ”‚   โ””โ”€โ”€ PptxOoxmlEditor.ts      # PPTX write โ†’ add/update slides, create PPTX (JSZip OOXML)
โ”œโ”€โ”€ formatters/
โ”‚   โ”œโ”€โ”€ MarkdownFormatter.ts
โ”‚   โ”œโ”€โ”€ JsonFormatter.ts
โ”‚   โ””โ”€โ”€ TableFormatter.ts   # Spreadsheet โ†’ Markdown table
โ””โ”€โ”€ tools/
    โ”œโ”€โ”€ documents.ts         # open/close/list/create
    โ”œโ”€โ”€ reader.ts            # metadata/outline/read/search
    โ”œโ”€โ”€ writer.ts            # insert/replace/style
    โ”œโ”€โ”€ spreadsheet.ts       # get/set cells/ranges/sheets
    โ”œโ”€โ”€ presentation.ts      # slides/notes
    โ””โ”€โ”€ converter.ts         # save/export/convert
```

## ๐Ÿงช Testing

```bash
# Create sample fixtures
node tests/create-fixtures.mjs

# Run smoke tests
npm test
```

## ๐Ÿ“ Environment Variables

| Variable | Description |
|---|---|
| `SOFFICE_PATH` | Path to LibreOffice `soffice` executable |
| `DEBUG` | Set to `lo-mcp:*` for verbose logging |

## ๐Ÿ“„ License

MIT

TDQS

A3.6/5.0

Scored across 27 tools

Disambiguation4/5

Most tools have distinct purposes with clear boundaries, such as document operations versus presentation or spreadsheet tools. However, some overlap exists: document_read_text and document_read_range both handle reading content, and document_convert and document_export both involve format conversion, which could cause minor confusion in selection.

Naming Consistency5/5

Tool names follow a highly consistent verb_noun pattern with clear prefixes (document_, presentation_, spreadsheet_) that group related operations. All names use snake_case uniformly, making them predictable and easy to parse for agents.

Tool Count3/5

With 27 tools, the count is borderline high for a single server, potentially overwhelming for agents. While the tools cover a broad range of LibreOffice operations, the number feels heavy and could be streamlined by consolidating overlapping functions like reading or conversion tools.

Completeness5/5

The tool set provides comprehensive coverage for document, presentation, and spreadsheet workflows, including creation, reading, updating, conversion, and metadata operations. There are no obvious gaps; agents can perform full CRUD/lifecycle tasks across all supported file types without dead ends.

Maintenance

ActivityInactive
ResponsivenessNo issues