# Apple Numbers Mcp

> MCP server for Apple Numbers - read, write, search, and format .numbers spreadsheets via Claude and other AI assistants

- **Type:** MCP server
- **Install:** `agentstack add mcp-sweetrb-apple-numbers-mcp`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [sweetrb](https://agentstack.voostack.com/s/sweetrb)
- **Installs:** 0
- **Category:** [Data & Analytics](https://agentstack.voostack.com/c/data-and-analytics)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [sweetrb](https://github.com/sweetrb)
- **Source:** https://github.com/sweetrb/apple-numbers-mcp

## Install

```sh
agentstack add mcp-sweetrb-apple-numbers-mcp
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# Apple Numbers MCP Server

A [Model Context Protocol (MCP)](https://modelcontextprotocol.io/) server that enables AI assistants like Claude to read, write, search, and modify Apple Numbers (`.numbers`) spreadsheet files. Backed by the [numbers-parser](https://pypi.org/project/numbers-parser/) Python library.

[](https://www.npmjs.com/package/apple-numbers-mcp)
[](https://www.npmjs.com/package/apple-numbers-mcp)
[](https://www.npmjs.com/package/apple-numbers-mcp)
[](https://github.com/sweetrb/apple-numbers-mcp/actions/workflows/ci.yml)
[](https://scorecard.dev/viewer/?uri=github.com/sweetrb/apple-numbers-mcp)
[](https://www.apple.com/macos/)
[](https://opensource.org/licenses/MIT)
[](https://modelcontextprotocol.io)

  

## What is This?

This server acts as a bridge between AI assistants and Apple Numbers spreadsheets. Once configured, you can ask Claude (or any MCP-compatible AI) to:

- "What's in this spreadsheet?" — inspect sheets, tables, dimensions
- "Find every row where the customer is Acme Corp"
- "Export the Q3 Results table to CSV"
- "Set cell B5 to =SUM(B2:B4)"
- "Append these three rows to the Inventory table"
- "Bold and center the header row"
- "Import this CSV into a new spreadsheet"

The AI assistant communicates with this server, which uses [numbers-parser](https://pypi.org/project/numbers-parser/) to read and write `.numbers` files directly (no Numbers.app required for most operations). All data stays local on your machine.

## Quick Start

### Using Claude Code (Easiest)

If you're using [Claude Code](https://claude.com/product/claude-code) (in Terminal or VS Code), just ask Claude to install it:

```
Install the sweetrb/apple-numbers-mcp MCP server so you can help me work with my Numbers spreadsheets
```

Claude will handle the installation and configuration automatically. After install, you'll need to install `numbers-parser` (Python) — see [Requirements](#requirements) below.

### Using the Plugin Marketplace

Install as a Claude Code plugin for automatic configuration and enhanced AI behavior:

```bash
/plugin marketplace add sweetrb/apple-numbers-mcp
/plugin install apple-numbers
```

This method also installs a **skill** that teaches Claude when and how to use Apple Numbers effectively.

### Using the Codex Marketplace

Install the same public marketplace in Codex:

```bash
codex plugin marketplace add sweetrb/apple-numbers-mcp
codex plugin add apple-numbers@apple-numbers-mcp
```

The Codex package registers the `apple-numbers` MCP server through
`npx -y apple-numbers-mcp` — the same published-package invocation documented for
Claude Desktop below — and bundles the Apple Numbers skill guidance. As with every
install path, the `numbers-parser` Python sidecar must be available (`pip3 install
numbers-parser`); see [Requirements](#requirements).

### Other Hosts (Hermes, Antigravity)

Configuration for two more hosts is included — each registers the same `apple-numbers` MCP server (`npx -y apple-numbers-mcp`). All paths still need the `numbers-parser` Python sidecar available; see [Requirements](#requirements).

- **[Hermes Agent](https://hermes-agent.nousresearch.com/)** (NousResearch) — Hermes has no plugin/marketplace drop-in. Add the server with `hermes mcp add apple-numbers --command npx --args -y apple-numbers-mcp`, or merge [`.hermes-plugin/config.yaml`](.hermes-plugin/config.yaml) into `~/.hermes/config.yaml`. Details: [`.hermes-plugin/README.md`](.hermes-plugin/README.md).
- **[Antigravity](https://antigravity.google/)** (Google) — add the server entry from [`.antigravity-plugin/mcp_config.json`](.antigravity-plugin/mcp_config.json) to `~/.gemini/config/mcp_config.json` (or via Antigravity's MCP settings).

### Manual Installation

**1. Install the server:**
```bash
npm install -g github:sweetrb/apple-numbers-mcp
```

**2. Install numbers-parser** (the Python library this server depends on):
```bash
pip3 install numbers-parser
```

Or, if you cloned the repo, run `pnpm run setup` to create a project-local Python venv with `numbers-parser` pre-installed.

**3. Add to Claude Desktop** (`~/Library/Application Support/Claude/claude_desktop_config.json`):
```json
{
  "mcpServers": {
    "apple-numbers": {
      "command": "npx",
      "args": ["apple-numbers-mcp"]
    }
  }
}
```

**4. Restart Claude Desktop** and start using natural language:
```
"What sheets are in ~/Documents/budget.numbers?"
```

#### Running from a clone in Claude Code (project-scope `.mcp.json`)

This repo ships a `.mcp.json` at its root so that, when you run `claude` from inside a clone, the server is registered automatically as a **project-scope** server — no manual config needed. Before launching, run **both**:

```bash
pnpm run build    # compile TypeScript to build/
pnpm run setup    # create the ./venv the Python sidecar needs
```

`pnpm run setup` is required because this is a Python-sidecar server: it shells out to `./venv/bin/python3` running `numbers-parser`. Without the venv, the server starts but every tool call fails. Then launch Claude Code from the repo directory and approve the server when prompted.

The entrypoint is written as:

```json
"args": ["${CLAUDE_PROJECT_DIR:-.}/build/index.js"]
```

`CLAUDE_PROJECT_DIR` is the variable Claude Code injects into a project/user-scoped server's environment, and it resolves to the repo root. **You must launch `claude` from inside the repo** for this to work — the bare `.` fallback is only a last resort and is *not* reliable, because it resolves against the launching process's working directory, not the repo.

> **Why not `${CLAUDE_PLUGIN_ROOT}`?** `CLAUDE_PLUGIN_ROOT` is set **only** for marketplace plugin installs, never for a project-scope clone, so it can't drive the clone workflow. Conversely, a plugin install can't use `CLAUDE_PROJECT_DIR` (in a plugin, that points at the *user's* project, not the plugin's own directory). Claude Code does **not** support nested defaults like `${CLAUDE_PLUGIN_ROOT:-${CLAUDE_PROJECT_DIR:-.}}`, so a single entrypoint string cannot serve both contexts. The two distribution paths are therefore decoupled: the **plugin** carries its own MCP config in `.claude-plugin/plugin.json` (using `${CLAUDE_PLUGIN_ROOT}`), while the root `.mcp.json` is dedicated to the **clone** workflow (using `${CLAUDE_PROJECT_DIR:-.}`). Because `plugin.json` declares its own `mcpServers`, the plugin does not also auto-load the root `.mcp.json`, so there is no double-registration.

> **Heads-up on scope precedence:** project-scope (`.mcp.json`) outranks user-scope. If you *also* have an `apple-numbers` entry registered at user scope (e.g. an absolute path in `~/.claude.json`), the project-scope entry wins and the user-scope one is ignored entirely. Pick one — for local development on this repo, the project-scope `.mcp.json` is the intended source. To pin a specific local build instead, register it at **local** scope (`claude mcp add apple-numbers -s local -- node /abs/path/build/index.js`), which outranks project scope.

## Requirements

- **macOS or Linux** — `numbers-parser` reads the file format directly, so most tools work anywhere. **Formatting and formula tools require macOS with Numbers.app.**
- **Node.js 20+** — Required for the MCP server
- **Python 3.11+** — the `numbers-parser` library installs automatically into a project-local venv on first use (or pre-warm with `pnpm run setup`). numbers-parser requires Python ≥ 3.10; macOS ships 3.9, so install a newer Python first (e.g. `brew install python@3.12`).
- **Automation permission (writes only)** — Reads and exports need no special permission, but write/format tools drive Numbers.app via AppleScript and require the host app to have Automation permission for Numbers, granted on first use. See the [Automation Permission guide](docs/AUTOMATION-PERMISSION.md). Run the **`doctor`** tool to verify your setup.

## Features

### Read

| Feature | Description |
|---------|-------------|
| **File Inspection** | List sheets, tables, dimensions, and header rows |
| **Table Read** | Read data with optional row range and column filtering |
| **Cell Read** | Single cells by 0-based index, with optional formula/format/merge metadata |
| **Search** | Case-insensitive text search across every cell, optionally scoped to one sheet |
| **Export** | Export a table to CSV, TSV, or JSON |

### Write

| Feature | Description |
|---------|-------------|
| **Create Spreadsheet** | New `.numbers` file with headers and optional initial rows |
| **Set Cell** | Write a value to a single cell, with optional type coercion |
| **Set Cells Batch** | Write many cells in one operation (more efficient than multiple set-cell calls) |
| **Add / Update / Delete Rows** | Append, replace, or remove rows by index |
| **Sheets and Tables** | Add new sheets or tables to an existing file; rename either |

### Formulas (requires Numbers.app)

| Feature | Description |
|---------|-------------|
| **Set Formula** | Write a formula like `=SUM(B2:B10)` to a cell |
| **Set Formulas Batch** | Write many formulas at once |

### Formatting (requires Numbers.app)

| Feature | Description |
|---------|-------------|
| **Cell Styles** | Font, size, colors, number format, alignment |
| **Cell Styles Batch** | Style many cells at once |
| **Column Width / Row Height** | Set dimensions in pixels |
| **Merge / Unmerge** | Merge a range of cells, or undo a merge |

### Import / Diagnostics

| Feature | Description |
|---------|-------------|
| **Import CSV/TSV/JSON** | Convert a tabular file into a new `.numbers` spreadsheet |
| **Health Check** | Verify Python 3 and numbers-parser are installed |
| **Doctor** | Richer setup diagnostic — read sidecar, Numbers.app, and Automation permission, each reported ok / warn / fail with actionable advice |

All tools also return **structured JSON** (`structuredContent`) alongside the human-readable text, so agents can consume results without parsing prose.

### MCP resources & prompts

Resources expose read-only context the client can attach without a tool call:
the `numbers://file/{path}` template (file structure — sheets, tables, dimensions,
headers) and the `numbers://table/{path}` template (the default table's data).
Both are templated by a URL-encoded `.numbers` file path. Prompts package common
workflows: `analyze-spreadsheet`, `bulk-edit`, `import-csv-guide`.

---

## Tool Reference

This section documents all available tools. AI agents should use these tool names and parameters exactly as specified.

### Read

#### `health-check`

Verify Python 3 and `numbers-parser` are installed and reachable from the server.

**Parameters:** None
**Returns:** `numbers-parser` version, or an error explaining how to install.

---

#### `doctor`

Run a full setup diagnostic with three separate checks: `numbers_parser` (the read sidecar — required for all reads/exports), `numbers_app` (Numbers.app present — required for write/format tools), and `automation_permission` (an informational reminder that write tools need Automation permission for Numbers.app). Each is reported as ok / warn / fail with actionable advice. This is the richer counterpart to `health-check`; reach for it first when a tool returns a permission or setup error.

**Parameters:** None

**Returns:** A per-check report. The `structuredContent` carries the raw `{ healthy, checks[] }`, where each check has `name`, `status` (`ok`/`warn`/`fail`), and `detail`. Reads don't need Automation permission, but writes do — see [docs/AUTOMATION-PERMISSION.md](docs/AUTOMATION-PERMISSION.md).

---

#### `get-file-info`

Get the structure of a `.numbers` file: sheets, tables, dimensions, header rows.

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `path` | string | Yes | Absolute or `~`-relative path to the `.numbers` file |

**Returns:** Default sheet name, plus each sheet with its tables (name, dimensions, header row).

---

#### `read-table`

Read data from a table. Returns headers and rows. Defaults to the first sheet and first table if not specified.

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `path` | string | Yes | Path to the `.numbers` file |
| `sheet` | string | No | Sheet name (default: first sheet) |
| `table` | string | No | Table name (default: first table) |
| `startRow` | number | No | 0-based start row, inclusive (default: 1, after header) |
| `endRow` | number | No | 0-based end row, inclusive (default: last row) |
| `columns` | (string \| number)[] | No | Column filter: header names or 0-based indices |

---

#### `get-cell`

Read a single cell value by row and column index (0-based).

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `path` | string | Yes | Path to the `.numbers` file |
| `sheet` | string | Yes | Sheet name |
| `table` | string | Yes | Table name |
| `row` | number | Yes | Row index (0-based) |
| `col` | number | Yes | Column index (0-based) |
| `verbose` | boolean | No | Include formula, formatted value, and merge info |

---

#### `search`

Case-insensitive partial match across every cell in a `.numbers` file.

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `path` | string | Yes | Path to the `.numbers` file |
| `query` | string | Yes | Text to search for |
| `sheet` | string | No | Limit search to one sheet |

**Returns:** Each match with sheet, table, row, column header, and value.

---

#### `export-table`

Export a table to CSV, TSV, or JSON.

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `path` | string | Yes | Path to the `.numbers` file |
| `format` | `"csv" \| "tsv" \| "json"` | Yes | Output format |
| `outputPath` | string | Yes | Path for the output file |
| `sheet` | string | No | Sheet name (default: first sheet) |
| `table` | string | No | Table name (default: first table) |

---

### Write

#### `create-spreadsheet`

Create a new `.numbers` file with one sheet and table.

**⚠️ Safety:** Overwrites the file at `path` if it already exists — confirm the destination first.

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `path` | string | Yes | Path for the new file |
| `headers` | string[] | Yes | Column header names |
| `rows` | (string \| number \| boolean \| null)[][] | No | Initial data rows |
| `sheetName` | string | No | Default: `"Sheet 1"` |
| `tableName` | string | No | Default: `"Table 1"` |

---

#### `set-cell`

Write a value to a single cell.

**⚠️ Safety:** Overwrites the existing cell value in place in the `.numbers` file.

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `path` | string | Yes | Path to the `.numbers` file |
| `row` | number | Yes | Row index (0-based) |
| `col` | number | Yes | Column index (0-based) |
| `value` | string \| number \| boolean \| null | Yes | Value to write |
| `sheet` | string | No | Sheet name (default: first sheet) |
| `table` | string | No | Table name (default: first table) |
| `type` | `"string" \| "number" \| "boolean" \| "date"` | No | Force value type (default: auto-detect) |

---

#### `set-cells-batch`

Write multiple cells in a single operation. Much more efficient than multiple `set-cell` calls.

**⚠️ Safety:** Overwrites the existing cell values in place in the `.numbers` file.

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `path` | string | Yes | Path to the `.numbers` file |
| `updates` | array | Yes | Array of `{row, col, value, type?}` objects |
| `sheet` | string | No | Sheet name |
| `table` | string | No | Table name |

---

#### `add-rows`

Append rows of data after the last existing row.

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `path` | string | Yes | Path to the `.numbers` file |
| `rows` | array[] | Yes | Rows to a

…

## Source & license

This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [sweetrb](https://github.com/sweetrb)
- **Source:** [sweetrb/apple-numbers-mcp](https://github.com/sweetrb/apple-numbers-mcp)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** yes
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/mcp-sweetrb-apple-numbers-mcp
- Seller: https://agentstack.voostack.com/s/sweetrb
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
