apple-numbers-mcp 1.1.5 → 1.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +29 -17
- package/build/index.js +41 -5
- package/docs/AUTOMATION-PERMISSION.md +147 -0
- package/docs/LIMITATIONS.md +145 -0
- package/docs/NODE-RUNTIME-AND-TCC-PERMISSIONS.md +109 -0
- package/package.json +2 -1
- package/scripts/setup.sh +2 -2
- package/src/utils/numbers_reader.py +6 -1
package/README.md
CHANGED
|
@@ -12,7 +12,7 @@ A [Model Context Protocol (MCP)](https://modelcontextprotocol.io/) server that e
|
|
|
12
12
|
[](https://modelcontextprotocol.io)
|
|
13
13
|
|
|
14
14
|
<p align="center">
|
|
15
|
-
<img src="codex/assets/screenshot.png" alt="Apple Numbers MCP — read, write, search, and format spreadsheets from Codex, Claude, and other AI assistants" width="680">
|
|
15
|
+
<img src="https://raw.githubusercontent.com/sweetrb/apple-numbers-mcp/main/codex/assets/screenshot.png" alt="Apple Numbers MCP — read, write, search, and format spreadsheets from Codex, Claude, and other AI assistants" width="680">
|
|
16
16
|
</p>
|
|
17
17
|
|
|
18
18
|
## What is This?
|
|
@@ -41,6 +41,12 @@ Install the sweetrb/apple-numbers-mcp MCP server so you can help me work with my
|
|
|
41
41
|
|
|
42
42
|
Claude will handle the installation and configuration automatically. After install, you'll need to install `numbers-parser` (Python) — see [Requirements](#requirements) below.
|
|
43
43
|
|
|
44
|
+
Or register it yourself in one deterministic line (no clone needed):
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
claude mcp add apple-numbers -s user -- npx -y apple-numbers-mcp
|
|
48
|
+
```
|
|
49
|
+
|
|
44
50
|
### Using the Plugin Marketplace
|
|
45
51
|
|
|
46
52
|
Install as a Claude Code plugin for automatic configuration and enhanced AI behavior:
|
|
@@ -52,6 +58,8 @@ Install as a Claude Code plugin for automatic configuration and enhanced AI beha
|
|
|
52
58
|
|
|
53
59
|
This method also installs a **skill** that teaches Claude when and how to use Apple Numbers effectively.
|
|
54
60
|
|
|
61
|
+
The plugin runs straight from its marketplace clone under `~/.claude/plugins/` (the clone lives at `~/.claude/plugins/marketplaces/apple-numbers-mcp/`). On the **first tool call** the server auto-bootstraps a project-local Python venv inside that directory with `numbers-parser` — a one-time setup that takes about a minute and **requires Python >= 3.11 on PATH** (stock macOS ships 3.9 — `brew install python@3.12` first). To pre-warm it instead of waiting on the first call, run `scripts/setup.sh` inside that install directory.
|
|
62
|
+
|
|
55
63
|
### Using the Codex Marketplace
|
|
56
64
|
|
|
57
65
|
Install the same public marketplace in Codex:
|
|
@@ -71,14 +79,14 @@ numbers-parser`); see [Requirements](#requirements).
|
|
|
71
79
|
|
|
72
80
|
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).
|
|
73
81
|
|
|
74
|
-
- **[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).
|
|
75
|
-
- **[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).
|
|
82
|
+
- **[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`](https://github.com/sweetrb/apple-numbers-mcp/blob/main/.hermes-plugin/config.yaml) into `~/.hermes/config.yaml`. Details: [`.hermes-plugin/README.md`](https://github.com/sweetrb/apple-numbers-mcp/blob/main/.hermes-plugin/README.md).
|
|
83
|
+
- **[Antigravity](https://antigravity.google/)** (Google) — add the server entry from [`.antigravity-plugin/mcp_config.json`](https://github.com/sweetrb/apple-numbers-mcp/blob/main/.antigravity-plugin/mcp_config.json) to `~/.gemini/config/mcp_config.json` (or via Antigravity's MCP settings).
|
|
76
84
|
|
|
77
85
|
### Manual Installation
|
|
78
86
|
|
|
79
|
-
**1. Install the server
|
|
87
|
+
**1. Install the server** (from the npm registry):
|
|
80
88
|
```bash
|
|
81
|
-
npm install -g
|
|
89
|
+
npm install -g apple-numbers-mcp
|
|
82
90
|
```
|
|
83
91
|
|
|
84
92
|
**2. Install numbers-parser** (the Python library this server depends on):
|
|
@@ -130,10 +138,10 @@ The entrypoint is written as:
|
|
|
130
138
|
|
|
131
139
|
## Requirements
|
|
132
140
|
|
|
133
|
-
- **macOS
|
|
141
|
+
- **macOS** — the npm package is macOS-only (it declares `os: ["darwin"]`). Reads go through `numbers-parser` directly (no Numbers.app needed); **formatting and formula tools additionally require Numbers.app.**
|
|
134
142
|
- **Node.js 20+** — Required for the MCP server
|
|
135
143
|
- **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`).
|
|
136
|
-
- **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.
|
|
144
|
+
- **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](https://github.com/sweetrb/apple-numbers-mcp/blob/main/docs/AUTOMATION-PERMISSION.md). Run the **`doctor`** tool to verify your setup.
|
|
137
145
|
|
|
138
146
|
## Features
|
|
139
147
|
|
|
@@ -179,7 +187,7 @@ The entrypoint is written as:
|
|
|
179
187
|
|---------|-------------|
|
|
180
188
|
| **Import CSV/TSV/JSON** | Convert a tabular file into a new `.numbers` spreadsheet |
|
|
181
189
|
| **Health Check** | Verify Python 3 and numbers-parser are installed |
|
|
182
|
-
| **Doctor** | Richer setup diagnostic — read sidecar, Numbers.app, and Automation permission, each reported ok / warn / fail with actionable advice |
|
|
190
|
+
| **Doctor** | Richer setup diagnostic — Python interpreter (path + version), read sidecar, Numbers.app, and Automation permission, each reported ok / warn / fail with actionable advice |
|
|
183
191
|
|
|
184
192
|
All tools also return **structured JSON** (`structuredContent`) alongside the human-readable text, so agents can consume results without parsing prose.
|
|
185
193
|
|
|
@@ -210,11 +218,11 @@ Verify Python 3 and `numbers-parser` are installed and reachable from the server
|
|
|
210
218
|
|
|
211
219
|
#### `doctor`
|
|
212
220
|
|
|
213
|
-
Run a full setup diagnostic with
|
|
221
|
+
Run a full setup diagnostic with four separate checks: `python_interpreter` (the resolved Python's path and version — warns when it's older than 3.11, the most common setup failure since stock macOS ships 3.9), `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.
|
|
214
222
|
|
|
215
223
|
**Parameters:** None
|
|
216
224
|
|
|
217
|
-
**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).
|
|
225
|
+
**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](https://github.com/sweetrb/apple-numbers-mcp/blob/main/docs/AUTOMATION-PERMISSION.md).
|
|
218
226
|
|
|
219
227
|
---
|
|
220
228
|
|
|
@@ -595,7 +603,7 @@ AI: [calls import-csv with inputPath, outputPath]
|
|
|
595
603
|
### npm (Recommended)
|
|
596
604
|
|
|
597
605
|
```bash
|
|
598
|
-
npm install -g
|
|
606
|
+
npm install -g apple-numbers-mcp
|
|
599
607
|
pip3 install numbers-parser
|
|
600
608
|
```
|
|
601
609
|
|
|
@@ -609,6 +617,8 @@ pnpm run setup # creates ./venv and installs numbers-parser
|
|
|
609
617
|
pnpm run build
|
|
610
618
|
```
|
|
611
619
|
|
|
620
|
+
Installing the repo directly from GitHub (`npm install -g github:sweetrb/apple-numbers-mcp`) also counts as a from-source install: it runs the repo's build on your machine and **requires pnpm**. Prefer the published npm package above unless you specifically want unreleased code.
|
|
621
|
+
|
|
612
622
|
If installed from source, use this configuration:
|
|
613
623
|
```json
|
|
614
624
|
{
|
|
@@ -683,7 +693,7 @@ This is the same Python-sidecar pattern used by [apple-photos-mcp](https://githu
|
|
|
683
693
|
## Known Limitations
|
|
684
694
|
|
|
685
695
|
For the full rundown — the read-vs-write split, AppleScript-only formulas/styles,
|
|
686
|
-
indexing, dates, format lag, and concurrent edits — see **[docs/LIMITATIONS.md](docs/LIMITATIONS.md)**.
|
|
696
|
+
indexing, dates, format lag, and concurrent edits — see **[docs/LIMITATIONS.md](https://github.com/sweetrb/apple-numbers-mcp/blob/main/docs/LIMITATIONS.md)**.
|
|
687
697
|
The summary below is the quick version.
|
|
688
698
|
|
|
689
699
|
| Limitation | Reason |
|
|
@@ -702,8 +712,10 @@ These are tracked for future releases. The underlying `numbers-parser` library h
|
|
|
702
712
|
|
|
703
713
|
## Troubleshooting
|
|
704
714
|
|
|
705
|
-
### "numbers-parser not installed
|
|
706
|
-
-
|
|
715
|
+
### "numbers-parser not installed"
|
|
716
|
+
- **Most common cause: your `python3` is older than 3.11** — stock macOS ships Python 3.9, which `numbers-parser` can't run on. Install a newer Python (`brew install python@3.12`), then simply retry the tool call: the venv rebuilds automatically.
|
|
717
|
+
- Otherwise, install the library directly: `pip3 install numbers-parser` (global Python), or run `scripts/setup.sh` from a repo checkout (`pnpm run setup`) to build the project-local venv.
|
|
718
|
+
- Run the **`doctor`** tool — it reports the resolved Python interpreter path and version, so a too-old stock Python is visible at a glance.
|
|
707
719
|
- If you used a virtualenv, make sure it's the one at `./venv/` in the project directory.
|
|
708
720
|
|
|
709
721
|
### `apple-numbers` server fails to connect when run from a clone
|
|
@@ -719,7 +731,7 @@ These are tracked for future releases. The underlying `numbers-parser` library h
|
|
|
719
731
|
### Formatting / formula tools fail with "Numbers.app not running" or "Not authorized to send Apple events to Numbers"
|
|
720
732
|
- Open Numbers.app at least once. macOS will prompt for automation permission — accept it.
|
|
721
733
|
- Verify in **System Settings → Privacy & Security → Automation**, or reset with `tccutil reset AppleEvents`.
|
|
722
|
-
- Run the **`doctor`** tool to confirm your setup — it reports the Numbers.app and Automation-permission checks separately. See the [Automation Permission guide](docs/AUTOMATION-PERMISSION.md). Reads don't need this permission; only writes do.
|
|
734
|
+
- Run the **`doctor`** tool to confirm your setup — it reports the Numbers.app and Automation-permission checks separately. See the [Automation Permission guide](https://github.com/sweetrb/apple-numbers-mcp/blob/main/docs/AUTOMATION-PERMISSION.md). Reads don't need this permission; only writes do.
|
|
723
735
|
|
|
724
736
|
### Output looks wrong (dates as ISO, floats with decimals)
|
|
725
737
|
- The server normalizes dates to ISO 8601 and rounds floats that are within `1e-9` of an integer. If you want raw values, file an issue.
|
|
@@ -766,7 +778,7 @@ A software consulting, contracting, and development company.
|
|
|
766
778
|
|
|
767
779
|
## License
|
|
768
780
|
|
|
769
|
-
MIT License - see [LICENSE](LICENSE) for details. This project is not affiliated with Apple Inc. or the [numbers-parser](https://pypi.org/project/numbers-parser/) project.
|
|
781
|
+
MIT License - see [LICENSE](https://github.com/sweetrb/apple-numbers-mcp/blob/main/LICENSE) for details. This project is not affiliated with Apple Inc. or the [numbers-parser](https://pypi.org/project/numbers-parser/) project.
|
|
770
782
|
|
|
771
783
|
## Contributing
|
|
772
784
|
|
|
@@ -783,4 +795,4 @@ Part of a family of macOS MCP servers:
|
|
|
783
795
|
|
|
784
796
|
## Recurring macOS permission prompts
|
|
785
797
|
|
|
786
|
-
If macOS keeps re-prompting for Full Disk Access or Automation for `node` (often after a `brew upgrade`), see [docs/NODE-RUNTIME-AND-TCC-PERMISSIONS.md](docs/NODE-RUNTIME-AND-TCC-PERMISSIONS.md) — the fix is to run this server under the official, Developer-ID-signed Node so the grant survives Node updates.
|
|
798
|
+
If macOS keeps re-prompting for Full Disk Access or Automation for `node` (often after a `brew upgrade`), see [docs/NODE-RUNTIME-AND-TCC-PERMISSIONS.md](https://github.com/sweetrb/apple-numbers-mcp/blob/main/docs/NODE-RUNTIME-AND-TCC-PERMISSIONS.md) — the fix is to run this server under the official, Developer-ID-signed Node so the grant survives Node updates.
|
package/build/index.js
CHANGED
|
@@ -21421,7 +21421,7 @@ function findSystemPython() {
|
|
|
21421
21421
|
}
|
|
21422
21422
|
}
|
|
21423
21423
|
throw new Error(
|
|
21424
|
-
|
|
21424
|
+
"Python 3 not found on PATH. Install Python >= 3.11 (stock macOS ships 3.9 - brew install python@3.12), or run scripts/setup.sh from a repo checkout. See https://github.com/sweetrb/apple-numbers-mcp#troubleshooting"
|
|
21425
21425
|
);
|
|
21426
21426
|
}
|
|
21427
21427
|
function resolvePython() {
|
|
@@ -21496,7 +21496,7 @@ function looksLikeMissingDep(message) {
|
|
|
21496
21496
|
return /not installed|No module named|ModuleNotFoundError/i.test(message);
|
|
21497
21497
|
}
|
|
21498
21498
|
function setupHint() {
|
|
21499
|
-
return `
|
|
21499
|
+
return `Install it with: pip3 install numbers-parser (requires Python >= 3.11; stock macOS ships 3.9 - brew install python@3.12), or run scripts/setup.sh from a repo checkout. Run the doctor tool to diagnose, and see https://github.com/sweetrb/apple-numbers-mcp#troubleshooting (set ${ENV_PREFIX}_NO_AUTO_SETUP=0 to allow automatic setup).`;
|
|
21500
21500
|
}
|
|
21501
21501
|
var DEFAULT_MAX_BUFFER_BYTES = 50 * 1024 * 1024;
|
|
21502
21502
|
function getMaxBuffer() {
|
|
@@ -21551,6 +21551,18 @@ function runNumbersReader(command, args, timeoutMs = 3e4) {
|
|
|
21551
21551
|
}
|
|
21552
21552
|
return result;
|
|
21553
21553
|
}
|
|
21554
|
+
function getPythonInfo() {
|
|
21555
|
+
try {
|
|
21556
|
+
const python = resolvePython();
|
|
21557
|
+
const version3 = execFileSync(python, ["--version"], {
|
|
21558
|
+
encoding: "utf-8",
|
|
21559
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
21560
|
+
}).trim();
|
|
21561
|
+
return { path: python, version: version3 };
|
|
21562
|
+
} catch {
|
|
21563
|
+
return null;
|
|
21564
|
+
}
|
|
21565
|
+
}
|
|
21554
21566
|
function checkDependencies() {
|
|
21555
21567
|
ensureReady();
|
|
21556
21568
|
try {
|
|
@@ -22067,18 +22079,42 @@ import { existsSync as existsSync3 } from "node:fs";
|
|
|
22067
22079
|
var NUMBERS_APP_PATHS = ["/Applications/Numbers.app", "/System/Applications/Numbers.app"];
|
|
22068
22080
|
function runDoctor(_manager) {
|
|
22069
22081
|
const checks = [];
|
|
22082
|
+
try {
|
|
22083
|
+
const info = getPythonInfo();
|
|
22084
|
+
if (info) {
|
|
22085
|
+
const m = /Python (\d+)\.(\d+)/.exec(info.version);
|
|
22086
|
+
const tooOld = m !== null && (Number(m[1]) < 3 || Number(m[1]) === 3 && Number(m[2]) < 11);
|
|
22087
|
+
checks.push({
|
|
22088
|
+
name: "python_interpreter",
|
|
22089
|
+
status: tooOld ? "warn" : "ok",
|
|
22090
|
+
detail: tooOld ? `${info.version} at ${info.path} \u2014 numbers-parser requires Python >= 3.11 (stock macOS ships 3.9). Install a newer Python (brew install python@3.12) and retry \u2014 the venv rebuilds automatically. See https://github.com/sweetrb/apple-numbers-mcp#troubleshooting` : `${info.version} (${info.path})`
|
|
22091
|
+
});
|
|
22092
|
+
} else {
|
|
22093
|
+
checks.push({
|
|
22094
|
+
name: "python_interpreter",
|
|
22095
|
+
status: "fail",
|
|
22096
|
+
detail: "Python 3 not found on PATH. Install Python >= 3.11 (e.g. brew install python@3.12). See https://github.com/sweetrb/apple-numbers-mcp#troubleshooting"
|
|
22097
|
+
});
|
|
22098
|
+
}
|
|
22099
|
+
} catch (e) {
|
|
22100
|
+
checks.push({
|
|
22101
|
+
name: "python_interpreter",
|
|
22102
|
+
status: "warn",
|
|
22103
|
+
detail: `could not resolve the Python interpreter: ${String(e)}`
|
|
22104
|
+
});
|
|
22105
|
+
}
|
|
22070
22106
|
try {
|
|
22071
22107
|
const dep = checkDependencies();
|
|
22072
22108
|
checks.push({
|
|
22073
22109
|
name: "numbers_parser",
|
|
22074
22110
|
status: dep.ok ? "ok" : "fail",
|
|
22075
|
-
detail: dep.
|
|
22111
|
+
detail: dep.message
|
|
22076
22112
|
});
|
|
22077
22113
|
} catch (e) {
|
|
22078
22114
|
checks.push({
|
|
22079
22115
|
name: "numbers_parser",
|
|
22080
22116
|
status: "fail",
|
|
22081
|
-
detail: `could not verify numbers-parser: ${String(e)}.
|
|
22117
|
+
detail: `could not verify numbers-parser: ${String(e)}. ${setupHint()}`
|
|
22082
22118
|
});
|
|
22083
22119
|
}
|
|
22084
22120
|
try {
|
|
@@ -22279,7 +22315,7 @@ server.registerTool(
|
|
|
22279
22315
|
server.registerTool(
|
|
22280
22316
|
"doctor",
|
|
22281
22317
|
{
|
|
22282
|
-
description: "Use when: a tool returns a permission or setup error, or you want the full setup diagnostic before writing/formatting.\nReturns:
|
|
22318
|
+
description: "Use when: a tool returns a permission or setup error, or you want the full setup diagnostic before writing/formatting.\nReturns: four checks \u2014 the resolved Python interpreter (path + version), numbers-parser (read sidecar), Numbers.app (needed for writes), and Automation permission \u2014 each as ok/warn/fail with actionable advice.\nDo not use when: you only need the lightweight read-sidecar version check \u2014 use health-check instead.",
|
|
22283
22319
|
inputSchema: {},
|
|
22284
22320
|
outputSchema: {
|
|
22285
22321
|
healthy: external_exports.boolean().optional(),
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
# Automation Permission for Write & Format Operations
|
|
2
|
+
|
|
3
|
+
Apple Numbers MCP has **two distinct backends**, and only one of them needs a
|
|
4
|
+
special macOS permission:
|
|
5
|
+
|
|
6
|
+
- **Reads** go through [numbers-parser](https://pypi.org/project/numbers-parser/)
|
|
7
|
+
(Python). They open the `.numbers` file **directly** off disk and need **no**
|
|
8
|
+
special permission — just normal file access.
|
|
9
|
+
- **Writes and formatting** go through **AppleScript driving Numbers.app**.
|
|
10
|
+
numbers-parser can't write styles or formulas, so the server scripts Numbers.app
|
|
11
|
+
to do it. macOS gates one app controlling another behind the **Automation**
|
|
12
|
+
permission, so these tools require it.
|
|
13
|
+
|
|
14
|
+
This page explains which tools need Automation permission, how the prompt appears,
|
|
15
|
+
how to grant or reset it, what failure looks like, and how to verify.
|
|
16
|
+
|
|
17
|
+
## Which tools need Automation permission
|
|
18
|
+
|
|
19
|
+
**Need it** (AppleScript → Numbers.app — writes, formulas, formatting, structure
|
|
20
|
+
changes, CSV import, file creation):
|
|
21
|
+
|
|
22
|
+
- `set-cell`, `set-cells-batch`
|
|
23
|
+
- `add-rows`, `update-rows`, `delete-rows`
|
|
24
|
+
- `add-sheet`, `add-table`, `rename-sheet`, `rename-table`
|
|
25
|
+
- `set-formula`, `set-formulas-batch`
|
|
26
|
+
- `set-cell-style`, `set-cells-style-batch`
|
|
27
|
+
- `set-column-width`, `set-row-height`
|
|
28
|
+
- `merge-cells`, `unmerge-cells`
|
|
29
|
+
- `create-spreadsheet`
|
|
30
|
+
- `import-csv`
|
|
31
|
+
|
|
32
|
+
**Do NOT need it** (pure numbers-parser, file read directly off disk):
|
|
33
|
+
|
|
34
|
+
- `get-file-info`
|
|
35
|
+
- `read-table`
|
|
36
|
+
- `get-cell`
|
|
37
|
+
- `search`
|
|
38
|
+
- `export-table`
|
|
39
|
+
- `health-check` / `doctor` (these only probe the environment)
|
|
40
|
+
|
|
41
|
+
So you can fully inspect, search, and export a spreadsheet with no Automation
|
|
42
|
+
permission at all. The permission only matters the moment you try to **change or
|
|
43
|
+
format** a file.
|
|
44
|
+
|
|
45
|
+
> **Numbers.app must be installed.** The write/format path scripts Numbers.app, so
|
|
46
|
+
> the app has to be present at `/Applications/Numbers.app` (or
|
|
47
|
+
> `/System/Applications/Numbers.app`). Reads don't need it. If Numbers.app is
|
|
48
|
+
> missing, `doctor` reports `numbers_app: warn` and the write tools fail.
|
|
49
|
+
|
|
50
|
+
## How the permission prompt appears
|
|
51
|
+
|
|
52
|
+
The **first time** a write/format tool runs, macOS shows a one-time dialog:
|
|
53
|
+
|
|
54
|
+
> **"<Host App>" wants access to control "Numbers". Allowing control will provide
|
|
55
|
+
> access to documents and data in "Numbers", and to perform actions within that
|
|
56
|
+
> app.**
|
|
57
|
+
|
|
58
|
+
Click **OK / Allow**. The grant is remembered, so subsequent writes don't prompt
|
|
59
|
+
again. The "host app" is whatever process launched the MCP server — Claude
|
|
60
|
+
Desktop, Terminal, iTerm, or VS Code — **not** `node` and **not** Numbers.app.
|
|
61
|
+
|
|
62
|
+
If the host app runs headless or the dialog is dismissed/denied, the write fails
|
|
63
|
+
(see below) and you must grant the permission manually.
|
|
64
|
+
|
|
65
|
+
## How to grant it manually
|
|
66
|
+
|
|
67
|
+
1. Open **System Settings** (or **System Preferences** on older macOS).
|
|
68
|
+
2. Go to **Privacy & Security → Automation**.
|
|
69
|
+
3. Find the **host app** that runs the MCP server (Claude, Terminal, iTerm, or
|
|
70
|
+
VS Code) in the list.
|
|
71
|
+
4. Expand it and enable the toggle next to **Numbers**.
|
|
72
|
+
|
|
73
|
+
| Host | App to allow |
|
|
74
|
+
|------|--------------|
|
|
75
|
+
| Claude Desktop | `Claude.app` |
|
|
76
|
+
| Claude Code in Terminal | `Terminal.app` |
|
|
77
|
+
| Claude Code in iTerm | `iTerm.app` |
|
|
78
|
+
| Claude Code in VS Code | `Visual Studio Code.app` |
|
|
79
|
+
|
|
80
|
+
> **Grant it to the right app.** Automation permission applies to the process that
|
|
81
|
+
> *spawns* the server, not to `node` or to Numbers.app. If you launch Claude Code
|
|
82
|
+
> from iTerm, allow iTerm to control Numbers; if you use Claude Desktop, allow
|
|
83
|
+
> Claude. Granting it to the wrong app has no effect.
|
|
84
|
+
|
|
85
|
+
## What failure looks like
|
|
86
|
+
|
|
87
|
+
When the host app lacks Automation permission for Numbers, the AppleScript layer
|
|
88
|
+
fails and the write/format tool returns an error containing:
|
|
89
|
+
|
|
90
|
+
```
|
|
91
|
+
Not authorized to send Apple events to Numbers.
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
(or, equivalently, an `errAEEventNotPermitted` / `-1743` error.) You may also see
|
|
95
|
+
`"Numbers got an error: ..."` style messages if Numbers.app itself can't be
|
|
96
|
+
driven. In all of these cases the underlying `.numbers` file is **not** modified.
|
|
97
|
+
|
|
98
|
+
If you instead see **"Numbers.app not running"** or a message that Numbers.app
|
|
99
|
+
can't be found, the problem is that the app isn't installed/openable — open
|
|
100
|
+
Numbers.app once and retry.
|
|
101
|
+
|
|
102
|
+
## Resetting the permission
|
|
103
|
+
|
|
104
|
+
If the grant got into a bad state (e.g. you clicked **Don't Allow** the first
|
|
105
|
+
time, and macOS now won't re-prompt), reset the Automation permissions and let the
|
|
106
|
+
prompt appear again on the next write:
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
tccutil reset AppleEvents
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
This clears Apple-event (Automation) grants for **all** apps; macOS will re-prompt
|
|
113
|
+
on the next attempt. To be more surgical you can scope it to the host bundle id,
|
|
114
|
+
e.g.:
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
tccutil reset AppleEvents com.apple.Terminal
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
After resetting, **fully quit and reopen the host app**, then run any write tool
|
|
121
|
+
(e.g. `set-cell`) and click **OK** when the dialog appears.
|
|
122
|
+
|
|
123
|
+
## Verifying
|
|
124
|
+
|
|
125
|
+
Run the **`doctor`** tool — it's the richest diagnostic and reports four checks
|
|
126
|
+
as `ok` / `warn` / `fail`:
|
|
127
|
+
|
|
128
|
+
- **`python_interpreter`** — the resolved Python's path and version (warns when
|
|
129
|
+
older than 3.11; stock macOS ships 3.9).
|
|
130
|
+
- **`numbers_parser`** — is the Python read sidecar installed (powers all reads).
|
|
131
|
+
- **`numbers_app`** — is Numbers.app present (required for any write/format tool).
|
|
132
|
+
- **`automation_permission`** — an informational reminder that write tools need
|
|
133
|
+
Automation permission, granted on first use.
|
|
134
|
+
|
|
135
|
+
> **Note:** Automation permission can't be probed without actually trying to
|
|
136
|
+
> control Numbers (that would itself trigger the prompt), so `doctor` reports it
|
|
137
|
+
> **informationally** rather than testing it live. The definitive test is to run a
|
|
138
|
+
> real write — e.g. `set-cell` on a scratch file. If it succeeds, the permission
|
|
139
|
+
> is in place; if it returns *"Not authorized to send Apple events to Numbers,"*
|
|
140
|
+
> grant or reset it as above.
|
|
141
|
+
|
|
142
|
+
## See also
|
|
143
|
+
|
|
144
|
+
- [docs/LIMITATIONS.md](./LIMITATIONS.md) — the full read-vs-write split and other
|
|
145
|
+
limits.
|
|
146
|
+
- [Known Limitations](../README.md#known-limitations) and
|
|
147
|
+
[Security and Privacy](../README.md#security-and-privacy) in the README.
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
# Limitations
|
|
2
|
+
|
|
3
|
+
Apple Numbers MCP is a **hybrid** bridge to `.numbers` spreadsheets: it **reads**
|
|
4
|
+
them offline with [numbers-parser](https://pypi.org/project/numbers-parser/)
|
|
5
|
+
(Python, no app required), and **writes/formats** them by scripting **Numbers.app**
|
|
6
|
+
via AppleScript (because numbers-parser can't write styles or formulas). That split
|
|
7
|
+
is the source of most of the limitations below.
|
|
8
|
+
|
|
9
|
+
This page documents the real limitations — what the server can't do and why — so
|
|
10
|
+
they aren't re-investigated every release. These agree with the README's
|
|
11
|
+
[Known Limitations](../README.md#known-limitations); this page adds the *why* and
|
|
12
|
+
*what to do* for each.
|
|
13
|
+
|
|
14
|
+
## Writes & formatting require Numbers.app + Automation permission (reads don't)
|
|
15
|
+
|
|
16
|
+
**Why:** numbers-parser can read a `.numbers` file directly off disk, but it does
|
|
17
|
+
**not** write styles, formulas, or cell-dimension changes reliably. To do those,
|
|
18
|
+
the server scripts **Numbers.app** through AppleScript. That means every
|
|
19
|
+
write/format tool needs (a) **Numbers.app installed** and (b) the host app to have
|
|
20
|
+
**Automation** permission to control Numbers. Read tools (`get-file-info`,
|
|
21
|
+
`read-table`, `get-cell`, `search`, `export-table`) use only numbers-parser and
|
|
22
|
+
need **neither** — they work on macOS or Linux with no Automation grant.
|
|
23
|
+
|
|
24
|
+
**What to do:** For inspection/search/export, nothing special is needed. For any
|
|
25
|
+
write — `set-cell(s)`, `add/update/delete-rows`, `add-sheet`/`add-table`,
|
|
26
|
+
`rename-*`, `set-formula(s)`, `set-*-style`, `set-column-width`/`set-row-height`,
|
|
27
|
+
`merge`/`unmerge`, `create-spreadsheet`, `import-csv` — install Numbers.app and
|
|
28
|
+
grant Automation permission. Full steps in
|
|
29
|
+
[AUTOMATION-PERMISSION.md](./AUTOMATION-PERMISSION.md). Verify with `doctor`.
|
|
30
|
+
|
|
31
|
+
## Formulas and styling are AppleScript-only
|
|
32
|
+
|
|
33
|
+
**Why:** Writing a formula (`set-formula`, `set-formulas-batch`) or a style
|
|
34
|
+
(`set-cell-style`, `set-cells-style-batch`, `set-column-width`, `set-row-height`,
|
|
35
|
+
`merge-cells`/`unmerge-cells`) cannot be done through the Python read path —
|
|
36
|
+
numbers-parser doesn't expose reliable writes for these. They go exclusively
|
|
37
|
+
through Numbers.app via AppleScript, so they inherit the macOS-only + Automation
|
|
38
|
+
requirements above and can't run on Linux.
|
|
39
|
+
|
|
40
|
+
**What to do:** Run formula/format tools on macOS with Numbers.app. If you only
|
|
41
|
+
have the Python path available (e.g. Linux), you can still read formulas and
|
|
42
|
+
formatted values (via `get-cell verbose: true`) — you just can't set them.
|
|
43
|
+
|
|
44
|
+
## Values vs. formulas
|
|
45
|
+
|
|
46
|
+
**Why:** The value-writing tools (`set-cell`, `set-cells-batch`, `add-rows`,
|
|
47
|
+
`update-rows`) write **computed values**, not formulas. Passing `"=SUM(...)"` as a
|
|
48
|
+
value writes the literal string, not a live formula.
|
|
49
|
+
|
|
50
|
+
**What to do:** Use `set-formula` / `set-formulas-batch` to write actual formulas
|
|
51
|
+
(these require Numbers.app). Use the value tools for plain data.
|
|
52
|
+
|
|
53
|
+
## No charts, images, or conditional formatting
|
|
54
|
+
|
|
55
|
+
**Why:** numbers-parser doesn't expose charts, embedded images, or
|
|
56
|
+
conditional-formatting rules, and the AppleScript layer here doesn't implement
|
|
57
|
+
them either. There is no tool to create, read, or edit a chart, an image, or a
|
|
58
|
+
conditional-format rule.
|
|
59
|
+
|
|
60
|
+
**What to do:** Build charts / conditional formatting by hand in Numbers.app on the
|
|
61
|
+
data this server writes. The server can populate and format the underlying cells;
|
|
62
|
+
the visualization layer stays manual.
|
|
63
|
+
|
|
64
|
+
## Sheet deletion is not supported
|
|
65
|
+
|
|
66
|
+
**Why:** numbers-parser doesn't expose sheet removal, so there's no `delete-sheet`
|
|
67
|
+
tool. (Rows can be deleted with `delete-rows`; whole sheets cannot.)
|
|
68
|
+
|
|
69
|
+
**What to do:** Delete a sheet manually in Numbers.app.
|
|
70
|
+
|
|
71
|
+
## Indexing is 0-based for rows and columns
|
|
72
|
+
|
|
73
|
+
**Why:** Every tool that takes a `row`/`col` (or `startRow`/`endRow`/`startCol`/
|
|
74
|
+
`endCol`) uses **0-based** indices — verified throughout `src/index.ts` (e.g.
|
|
75
|
+
`row: z.number().int().min(0).describe("Row index (0-based)")`). The header row is
|
|
76
|
+
**row 0**, so the first data row is **row 1**. This is why `read-table` defaults
|
|
77
|
+
`startRow` to `1` (i.e. "skip the header"). Ranges are **inclusive** on both ends
|
|
78
|
+
(e.g. `delete-rows startRow: 1 endRow: 3` deletes three rows).
|
|
79
|
+
|
|
80
|
+
**What to do:** Treat the header as row 0. A spreadsheet "row 5" that a human sees
|
|
81
|
+
in Numbers.app (1-based, header included) is index `4` here. When in doubt, call
|
|
82
|
+
`read-table` or `get-cell` first to confirm what's at a given index.
|
|
83
|
+
|
|
84
|
+
## Dates are ISO 8601
|
|
85
|
+
|
|
86
|
+
**Why:** The Python layer normalizes all dates to **ISO 8601** on read
|
|
87
|
+
(`val.isoformat()`), collapsing a pure date with no time to `YYYY-MM-DD` and
|
|
88
|
+
keeping the full datetime otherwise. On write, a value typed as `date` is parsed
|
|
89
|
+
with `datetime.fromisoformat`, so date inputs must be ISO 8601 too.
|
|
90
|
+
|
|
91
|
+
**What to do:** Pass dates as `"2025-06-01"` or a full ISO datetime, and expect ISO
|
|
92
|
+
8601 back. Locale-formatted dates (e.g. `"6/1/25"`) are not parsed as dates.
|
|
93
|
+
|
|
94
|
+
## numbers-parser may lag the newest Numbers file format
|
|
95
|
+
|
|
96
|
+
**Why:** Apple periodically changes the `.numbers` on-disk format with new
|
|
97
|
+
Numbers.app releases. numbers-parser is a third-party library that has to catch up
|
|
98
|
+
to each new format version. A file saved by a very new Numbers.app can occasionally
|
|
99
|
+
read incompletely (or error) on an older numbers-parser.
|
|
100
|
+
|
|
101
|
+
**What to do:** Keep numbers-parser current (`pip3 install -U numbers-parser`, or
|
|
102
|
+
re-run `pnpm run setup`). If a read fails or looks wrong on a freshly-saved file,
|
|
103
|
+
upgrade numbers-parser first. Check the installed version with `health-check` /
|
|
104
|
+
`doctor`.
|
|
105
|
+
|
|
106
|
+
## Concurrent edits while Numbers.app has the file open
|
|
107
|
+
|
|
108
|
+
**Why:** Two backends can touch the same file. The read path (numbers-parser) reads
|
|
109
|
+
whatever is on disk, and the write path drives Numbers.app. If Numbers.app has the
|
|
110
|
+
file **open with unsaved changes**, what numbers-parser reads off disk can be
|
|
111
|
+
stale, and a write through AppleScript targets the app's in-memory copy — the two
|
|
112
|
+
can disagree, and saves can race.
|
|
113
|
+
|
|
114
|
+
**What to do:** Prefer to **close the file in Numbers.app** before reading or doing
|
|
115
|
+
bulk writes through the server, so disk and app agree. If you must keep it open,
|
|
116
|
+
read back with `read-table` / `get-cell` after writes to confirm the result landed,
|
|
117
|
+
and avoid editing the same cells by hand in Numbers.app at the same time.
|
|
118
|
+
|
|
119
|
+
## Concurrent writes to the same file are last-writer-wins
|
|
120
|
+
|
|
121
|
+
**Why:** Each write tool opens the `.numbers` file, applies its change to an
|
|
122
|
+
in-memory document, and saves the **whole document** back. The save itself is
|
|
123
|
+
**atomic** — every mutating command writes to a sibling temp file and `os.replace()`s
|
|
124
|
+
it onto the target — so an interrupted or crashed write can never leave a torn or
|
|
125
|
+
half-written file. But atomicity protects against *corruption*, **not** against
|
|
126
|
+
*lost updates*: if two writes to the same file overlap (two agents, two server
|
|
127
|
+
instances, or a server write racing a hand edit in Numbers.app), each loaded the
|
|
128
|
+
document independently, and whichever saves **last** overwrites the other's change
|
|
129
|
+
wholesale. There is no file locking, no merge, and no optimistic-concurrency check.
|
|
130
|
+
|
|
131
|
+
**What to do:** **Serialize writes to a given file** — don't fan out concurrent
|
|
132
|
+
mutations against the same `.numbers` file from multiple agents or sessions. Batch
|
|
133
|
+
related edits into a single call (`set-cells-batch`, `update-rows`,
|
|
134
|
+
`set-formulas-batch`) instead of many overlapping ones, finish one tool call before
|
|
135
|
+
starting the next on the same file, and after a burst of writes read back with
|
|
136
|
+
`read-table` / `get-cell` to confirm the final state is what you intended.
|
|
137
|
+
|
|
138
|
+
## macOS-only for writes; reads are cross-platform
|
|
139
|
+
|
|
140
|
+
**Why:** Reads run anywhere numbers-parser runs (macOS or Linux). Writes/formatting
|
|
141
|
+
script Numbers.app, which only exists on macOS.
|
|
142
|
+
|
|
143
|
+
**What to do:** Run write/format workloads on a Mac with Numbers.app installed and
|
|
144
|
+
Automation permission granted. See
|
|
145
|
+
[AUTOMATION-PERMISSION.md](./AUTOMATION-PERMISSION.md).
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# Node runtime & TCC permission stability
|
|
2
|
+
|
|
3
|
+
macOS gates this MCP server's access to your data behind **TCC** permissions —
|
|
4
|
+
**Full Disk Access** (to read app data such as Mail, Notes, or Photos) and
|
|
5
|
+
**Automation / Apple Events** (to drive an app like Mail.app or Notes.app via
|
|
6
|
+
AppleScript). See this repo's Full Disk Access / Automation notes for *which*
|
|
7
|
+
operations need which permission.
|
|
8
|
+
|
|
9
|
+
This page is about a **separate, recurring annoyance**: being asked to approve
|
|
10
|
+
those permissions **over and over**, often right after a routine `brew upgrade`.
|
|
11
|
+
|
|
12
|
+
## Symptom
|
|
13
|
+
|
|
14
|
+
- You granted Full Disk Access (and/or Automation) to "node", but days later
|
|
15
|
+
macOS prompts again — `"node" wants access to ...` or `"node" wants to control
|
|
16
|
+
"Mail"`.
|
|
17
|
+
- System Settings → Privacy & Security → Full Disk Access shows **several
|
|
18
|
+
identical "node" rows**, usually only one enabled.
|
|
19
|
+
- It tends to happen immediately after you update Node.
|
|
20
|
+
|
|
21
|
+
## Cause
|
|
22
|
+
|
|
23
|
+
TCC binds a permission grant to the **code identity of the binary that performs
|
|
24
|
+
the access** — here, the `node` executable that launches the MCP server. For a
|
|
25
|
+
binary that is only **ad-hoc signed** (no Developer ID / Team ID), TCC keys the
|
|
26
|
+
grant to the binary's **cdhash**, a hash of its contents.
|
|
27
|
+
|
|
28
|
+
Homebrew's `node` formula is ad-hoc signed:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
$ codesign -dvvv "$(which node)" 2>&1 | grep -E 'Signature|TeamIdentifier'
|
|
32
|
+
Signature=adhoc
|
|
33
|
+
TeamIdentifier=not set
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Every Node update **replaces the binary**, which **changes the cdhash**, so TCC
|
|
37
|
+
no longer recognizes it as the thing you approved — and re-prompts. The extra
|
|
38
|
+
"node" rows are stale cdhashes from previous versions.
|
|
39
|
+
|
|
40
|
+
By contrast, properly signed apps (Chrome, Slack, …) keep their permissions
|
|
41
|
+
across auto-updates because TCC matches them on a stable **Designated
|
|
42
|
+
Requirement** derived from their Developer ID, not on the cdhash.
|
|
43
|
+
|
|
44
|
+
## Fix: run the MCP under the official, Developer-ID-signed Node
|
|
45
|
+
|
|
46
|
+
Node binaries distributed from **nodejs.org** are signed with a real Developer
|
|
47
|
+
ID (`Node.js Foundation`, Team `HX7739G8FX`), notarized, and self-contained.
|
|
48
|
+
Pointing the MCP server at one gives TCC a **stable** identity to match, so a
|
|
49
|
+
permission you grant **persists across future Node updates**. It also decouples
|
|
50
|
+
the MCP runtime from your Homebrew/dev Node, which can keep updating freely.
|
|
51
|
+
|
|
52
|
+
### Steps (Apple Silicon shown; use `darwin-x64` on Intel)
|
|
53
|
+
|
|
54
|
+
1. Install a current LTS to a stable path (kept off `PATH` so it won't shadow
|
|
55
|
+
your dev Node):
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
VER=v24.17.0 ARCH=darwin-arm64
|
|
59
|
+
mkdir -p ~/mcp-runtime && cd ~/mcp-runtime
|
|
60
|
+
curl -O https://nodejs.org/dist/$VER/node-$VER-$ARCH.tar.gz
|
|
61
|
+
curl -O https://nodejs.org/dist/$VER/SHASUMS256.txt
|
|
62
|
+
grep " node-$VER-$ARCH.tar.gz$" SHASUMS256.txt | shasum -a 256 -c - # must print OK
|
|
63
|
+
tar -xzf node-$VER-$ARCH.tar.gz
|
|
64
|
+
ln -sfn node-$VER-$ARCH node-current
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
2. Confirm it's Developer-ID signed:
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
codesign -dvvv ~/mcp-runtime/node-current/bin/node 2>&1 | grep -E 'Authority=Developer ID|TeamIdentifier'
|
|
71
|
+
# Authority=Developer ID Application: Node.js Foundation (HX7739G8FX)
|
|
72
|
+
# TeamIdentifier=HX7739G8FX
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
3. Point this MCP server's launcher at it. For Claude Desktop, edit
|
|
76
|
+
`~/Library/Application Support/Claude/claude_desktop_config.json` and set this
|
|
77
|
+
server's `command` to the absolute path:
|
|
78
|
+
|
|
79
|
+
```json
|
|
80
|
+
{
|
|
81
|
+
"mcpServers": {
|
|
82
|
+
"apple-numbers": {
|
|
83
|
+
"command": "/Users/<you>/mcp-runtime/node-current/bin/node",
|
|
84
|
+
"args": ["/path/to/apple-numbers-mcp/build/index.js"]
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Servers launched via `npx` that don't need Full Disk Access can stay on
|
|
91
|
+
Homebrew Node.
|
|
92
|
+
|
|
93
|
+
4. **Restart your MCP client** so the server relaunches under the new Node.
|
|
94
|
+
|
|
95
|
+
5. **Grant the permissions once** to the new binary:
|
|
96
|
+
- *Full Disk Access*: System Settings → Privacy & Security → Full Disk Access
|
|
97
|
+
→ **+** → ⌘⇧G → paste `~/mcp-runtime/node-current/bin/node`.
|
|
98
|
+
- *Automation*: the first time the server drives an app you'll get a one-time
|
|
99
|
+
`"node" wants to control "<App>"` prompt — click **Allow**.
|
|
100
|
+
|
|
101
|
+
Both grants are keyed to the official Node's stable signature, so you should
|
|
102
|
+
not be asked again — including after future Node updates. You can delete the
|
|
103
|
+
stale "node" rows from the Full Disk Access list.
|
|
104
|
+
|
|
105
|
+
### Updating the dedicated Node later
|
|
106
|
+
|
|
107
|
+
Drop a newer official LTS tarball into `~/mcp-runtime/`, repoint the
|
|
108
|
+
`node-current` symlink, and restart your client. The signing identity is
|
|
109
|
+
unchanged, so existing grants carry over — no re-approval.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "apple-numbers-mcp",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.6",
|
|
4
4
|
"description": "MCP server for Apple Numbers - read, write, search, and format .numbers spreadsheets via Claude and other AI assistants",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "build/index.js",
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
"src/utils/numbers_reader.py",
|
|
13
13
|
"scripts/setup.sh",
|
|
14
14
|
"requirements.txt",
|
|
15
|
+
"docs",
|
|
15
16
|
"README.md",
|
|
16
17
|
"LICENSE"
|
|
17
18
|
],
|
package/scripts/setup.sh
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
2
|
#
|
|
3
3
|
# Create a Python venv and install numbers-parser.
|
|
4
|
-
# Run via:
|
|
4
|
+
# Run via: pnpm run setup (or: bash scripts/setup.sh)
|
|
5
5
|
#
|
|
6
6
|
set -euo pipefail
|
|
7
7
|
|
|
@@ -32,7 +32,7 @@ echo " Using: $PYTHON ($($PYTHON --version))"
|
|
|
32
32
|
if ! "$PYTHON" -c 'import sys; sys.exit(0 if sys.version_info >= (3, 11) else 1)'; then
|
|
33
33
|
echo "ERROR: Python >= 3.11 required, but '$PYTHON' is $($PYTHON --version 2>&1)." >&2
|
|
34
34
|
echo " macOS ships Python 3.9. Install a newer one, e.g.:" >&2
|
|
35
|
-
echo " brew install python@3.12 # then re-run:
|
|
35
|
+
echo " brew install python@3.12 # then re-run: scripts/setup.sh" >&2
|
|
36
36
|
echo " or from https://www.python.org/downloads/" >&2
|
|
37
37
|
exit 1
|
|
38
38
|
fi
|
|
@@ -14,7 +14,12 @@ try:
|
|
|
14
14
|
from numbers_parser import Document
|
|
15
15
|
except ImportError:
|
|
16
16
|
print(json.dumps({
|
|
17
|
-
"error":
|
|
17
|
+
"error": (
|
|
18
|
+
"numbers-parser not installed. Install it with: pip3 install numbers-parser "
|
|
19
|
+
"(requires Python >= 3.11; stock macOS ships 3.9 - brew install python@3.12), "
|
|
20
|
+
"or run scripts/setup.sh from a repo checkout. Run the doctor tool to diagnose. "
|
|
21
|
+
"See https://github.com/sweetrb/apple-numbers-mcp#troubleshooting"
|
|
22
|
+
)
|
|
18
23
|
}))
|
|
19
24
|
sys.exit(1)
|
|
20
25
|
|