apple-numbers-mcp 0.5.0 → 0.6.0

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 CHANGED
@@ -703,7 +703,9 @@ Contributions are welcome! Please open an issue or PR at [github.com/sweetrb/app
703
703
 
704
704
  ## Related Projects
705
705
 
706
- - [apple-mail-mcp](https://github.com/sweetrb/apple-mail-mcp) — MCP server for Apple Mail
707
- - [apple-notes-mcp](https://github.com/sweetrb/apple-notes-mcp) — MCP server for Apple Notes
708
- - [apple-photos-mcp](https://github.com/sweetrb/apple-photos-mcp) — MCP server for Apple Photos
706
+ Part of a family of macOS MCP servers:
707
+
708
+ - [apple-mail-mcp](https://github.com/sweetrb/apple-mail-mcp) — MCP server for Apple Mail (read, search, send, and organize email)
709
+ - [apple-notes-mcp](https://github.com/sweetrb/apple-notes-mcp) — MCP server for Apple Notes (create, search, update, and export notes)
710
+ - [apple-photos-mcp](https://github.com/sweetrb/apple-photos-mcp) — MCP server for Apple Photos (query metadata and export originals)
709
711
  - [numbers-parser](https://pypi.org/project/numbers-parser/) — The Python library that powers this server
@@ -2,7 +2,7 @@ export interface PythonResult<T = unknown> {
2
2
  data?: T;
3
3
  error?: string;
4
4
  }
5
- /** Reset the cached Python path (useful for testing). */
5
+ /** Reset cached interpreter + bootstrap state (useful for testing). */
6
6
  export declare function _resetPythonCache(): void;
7
7
  export declare function runNumbersReader<T = unknown>(command: string, args: string[], timeoutMs?: number): PythonResult<T>;
8
8
  export declare function checkDependencies(): {
@@ -1 +1 @@
1
- {"version":3,"file":"python.d.ts","sourceRoot":"","sources":["../../src/utils/python.ts"],"names":[],"mappings":"AA+CA,MAAM,WAAW,YAAY,CAAC,CAAC,GAAG,OAAO;IACvC,IAAI,CAAC,EAAE,CAAC,CAAC;IACT,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAID,yDAAyD;AACzD,wBAAgB,iBAAiB,IAAI,IAAI,CAExC;AAcD,wBAAgB,gBAAgB,CAAC,CAAC,GAAG,OAAO,EAC1C,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EAAE,EACd,SAAS,SAAQ,GAChB,YAAY,CAAC,CAAC,CAAC,CAiCjB;AAED,wBAAgB,iBAAiB,IAAI;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAcpE"}
1
+ {"version":3,"file":"python.d.ts","sourceRoot":"","sources":["../../src/utils/python.ts"],"names":[],"mappings":"AA+DA,MAAM,WAAW,YAAY,CAAC,CAAC,GAAG,OAAO;IACvC,IAAI,CAAC,EAAE,CAAC,CAAC;IACT,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAMD,uEAAuE;AACvE,wBAAgB,iBAAiB,IAAI,IAAI,CAIxC;AAsKD,wBAAgB,gBAAgB,CAAC,CAAC,GAAG,OAAO,EAC1C,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EAAE,EACd,SAAS,SAAQ,GAChB,YAAY,CAAC,CAAC,CAAC,CAkBjB;AAED,wBAAgB,iBAAiB,IAAI;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAepE"}
@@ -1,31 +1,68 @@
1
1
  import { execSync, execFileSync } from "node:child_process";
2
- import { existsSync } from "node:fs";
2
+ import { existsSync, readFileSync } from "node:fs";
3
3
  import { fileURLToPath } from "node:url";
4
4
  import { dirname, join } from "node:path";
5
5
  const __filename = fileURLToPath(import.meta.url);
6
6
  const __dirname = dirname(__filename);
7
+ // pip/display name vs. the importable module name (underscore).
8
+ const PACKAGE = "numbers-parser";
9
+ const MODULE = "numbers_parser";
10
+ const ENV_PREFIX = "APPLE_NUMBERS_MCP";
7
11
  function getProjectRoot() {
8
- // Walk up from build/utils/ or src/utils/ to project root
12
+ // build/utils/ or src/utils/ -> project root
9
13
  return join(__dirname, "..", "..");
10
14
  }
11
- // Resolve path to the Python helper script
12
15
  function getScriptPath() {
13
16
  return join(getProjectRoot(), "src", "utils", "numbers_reader.py");
14
17
  }
18
+ function venvPythonPath() {
19
+ return join(getProjectRoot(), "venv", "bin", "python3");
20
+ }
21
+ function requirementsPath() {
22
+ return join(getProjectRoot(), "requirements.txt");
23
+ }
24
+ function setupScriptPath() {
25
+ return join(getProjectRoot(), "scripts", "setup.sh");
26
+ }
27
+ // Written by scripts/setup.sh after a successful install; holds a copy of the
28
+ // requirements.txt the venv was built against, so we can detect a stale venv
29
+ // after a package update changes requirements.
30
+ function depsMarkerPath() {
31
+ return join(getProjectRoot(), "venv", ".deps-ok");
32
+ }
33
+ function readIfExists(p) {
34
+ try {
35
+ return existsSync(p) ? readFileSync(p, "utf8") : null;
36
+ }
37
+ catch {
38
+ return null;
39
+ }
40
+ }
15
41
  /**
16
- * Find the best Python executable. Preference order:
17
- * 1. Project-local venv (./venv/bin/python3)
18
- * 2. System python3
19
- * 3. System python
42
+ * True when the venv exists AND was built against the CURRENT requirements.txt.
43
+ * A package update that changes requirements invalidates the marker, so the
44
+ * server knows to rebuild rather than run against stale deps.
20
45
  */
21
- function findPython() {
22
- const projectRoot = getProjectRoot();
23
- const venvPython = join(projectRoot, "venv", "bin", "python3");
24
- // Prefer the project venv — it has numbers-parser installed
25
- if (existsSync(venvPython)) {
26
- return venvPython;
27
- }
28
- // Fall back to system Python
46
+ function venvIsReady() {
47
+ if (!existsSync(venvPythonPath()))
48
+ return false;
49
+ const reqs = readIfExists(requirementsPath());
50
+ // If requirements.txt isn't present (unexpected), trust an existing venv.
51
+ if (reqs === null)
52
+ return true;
53
+ const marker = readIfExists(depsMarkerPath());
54
+ return marker !== null && marker.trim() === reqs.trim();
55
+ }
56
+ let cachedPython = null;
57
+ let readyConfirmed = false;
58
+ let bootstrapAttempted = false;
59
+ /** Reset cached interpreter + bootstrap state (useful for testing). */
60
+ export function _resetPythonCache() {
61
+ cachedPython = null;
62
+ readyConfirmed = false;
63
+ bootstrapAttempted = false;
64
+ }
65
+ function findSystemPython() {
29
66
  for (const cmd of ["python3", "python"]) {
30
67
  try {
31
68
  execSync(`${cmd} --version`, { stdio: "pipe" });
@@ -37,15 +74,101 @@ function findPython() {
37
74
  }
38
75
  throw new Error('Python 3 not found. Run "npm run setup" to create a venv, or ensure python3 is on PATH.');
39
76
  }
40
- let cachedPython = null;
41
- /** Reset the cached Python path (useful for testing). */
42
- export function _resetPythonCache() {
77
+ /**
78
+ * Resolve a Python interpreter. The project venv is cached once present (it's
79
+ * stable); a system-Python fallback is deliberately NOT cached, so a venv
80
+ * created later (e.g. by auto-bootstrap, or a manual `npm run setup`) is picked
81
+ * up on the very next call WITHOUT requiring a server restart.
82
+ */
83
+ function resolvePython() {
84
+ if (cachedPython && existsSync(cachedPython))
85
+ return cachedPython;
43
86
  cachedPython = null;
87
+ const venv = venvPythonPath();
88
+ if (existsSync(venv)) {
89
+ cachedPython = venv;
90
+ return venv;
91
+ }
92
+ return findSystemPython();
93
+ }
94
+ function isTrueish(v) {
95
+ return v !== undefined && v !== "" && v !== "0" && v.toLowerCase() !== "false";
96
+ }
97
+ /** Auto-bootstrap is off under tests, or when explicitly disabled via env. */
98
+ function autoSetupDisabled() {
99
+ if (process.env.VITEST || process.env.NODE_ENV === "test")
100
+ return true;
101
+ return isTrueish(process.env[`${ENV_PREFIX}_NO_AUTO_SETUP`]);
102
+ }
103
+ function bootstrapTimeoutMs() {
104
+ const raw = process.env[`${ENV_PREFIX}_SETUP_TIMEOUT`];
105
+ if (raw !== undefined) {
106
+ const n = Number(raw);
107
+ if (Number.isFinite(n) && n > 0)
108
+ return n;
109
+ }
110
+ return 5 * 60 * 1000; // 5 minutes — pip install of numbers-parser can be slow.
111
+ }
112
+ /**
113
+ * Create or refresh the venv by running scripts/setup.sh. Returns true on
114
+ * success. Progress is logged to STDERR only — stdout is the MCP protocol
115
+ * channel and must never be written to.
116
+ */
117
+ function bootstrapVenv() {
118
+ bootstrapAttempted = true;
119
+ const setup = setupScriptPath();
120
+ if (!existsSync(setup))
121
+ return false;
122
+ console.error(`[numbers-mcp] ${PACKAGE} not ready — setting up the Python venv (one-time; this can take a minute)…`);
123
+ try {
124
+ const out = execFileSync("bash", [setup], {
125
+ encoding: "utf-8",
126
+ timeout: bootstrapTimeoutMs(),
127
+ stdio: ["ignore", "pipe", "pipe"],
128
+ env: process.env,
129
+ });
130
+ const last = out.trim().split("\n").pop() ?? "";
131
+ console.error(`[numbers-mcp] Python venv ready. ${last}`.trim());
132
+ cachedPython = null;
133
+ readyConfirmed = false;
134
+ return true;
135
+ }
136
+ catch (err) {
137
+ const e = err;
138
+ const detail = (e.stderr?.toString() || e.stdout?.toString() || e.message || "").trim();
139
+ console.error(`[numbers-mcp] Automatic venv setup failed: ${detail.split("\n").pop() ?? detail}`);
140
+ return false;
141
+ }
142
+ }
143
+ /**
144
+ * Ensure the Python deps are ready, auto-bootstrapping the venv if it's missing
145
+ * or stale (and auto-setup isn't disabled). Cheap and idempotent: once the venv
146
+ * is confirmed ready it short-circuits, and bootstrap is attempted at most once
147
+ * per process.
148
+ */
149
+ function ensureReady() {
150
+ if (readyConfirmed)
151
+ return;
152
+ if (venvIsReady()) {
153
+ readyConfirmed = true;
154
+ return;
155
+ }
156
+ if (bootstrapAttempted || autoSetupDisabled())
157
+ return;
158
+ if (bootstrapVenv() && venvIsReady()) {
159
+ readyConfirmed = true;
160
+ }
161
+ }
162
+ function looksLikeMissingDep(message) {
163
+ return /not installed|No module named|ModuleNotFoundError/i.test(message);
164
+ }
165
+ function setupHint() {
166
+ return `Run: npm run setup (or set ${ENV_PREFIX}_NO_AUTO_SETUP=0 to allow automatic setup).`;
44
167
  }
45
168
  const DEFAULT_MAX_BUFFER_BYTES = 50 * 1024 * 1024; // 50MB for large spreadsheets
46
169
  /** Max stdout bytes from the Python sidecar, overridable via env for huge files. */
47
170
  function getMaxBuffer() {
48
- const raw = process.env.APPLE_NUMBERS_MCP_MAX_BUFFER;
171
+ const raw = process.env[`${ENV_PREFIX}_MAX_BUFFER`];
49
172
  if (raw !== undefined) {
50
173
  const n = Number(raw);
51
174
  if (Number.isFinite(n) && n > 0)
@@ -53,12 +176,11 @@ function getMaxBuffer() {
53
176
  }
54
177
  return DEFAULT_MAX_BUFFER_BYTES;
55
178
  }
56
- export function runNumbersReader(command, args, timeoutMs = 30000) {
57
- const python = cachedPython ?? (cachedPython = findPython());
179
+ function execReader(command, args, timeoutMs) {
180
+ const python = resolvePython();
58
181
  const scriptPath = getScriptPath();
59
182
  const fullArgs = [scriptPath, command, ...args];
60
- const debug = process.env.DEBUG || process.env.VERBOSE;
61
- if (debug) {
183
+ if (process.env.DEBUG || process.env.VERBOSE) {
62
184
  console.error(`[numbers-mcp] ${python} ${fullArgs.join(" ")}`);
63
185
  }
64
186
  try {
@@ -76,25 +198,51 @@ export function runNumbersReader(command, args, timeoutMs = 30000) {
76
198
  }
77
199
  catch (err) {
78
200
  const error = err;
79
- if (error.stderr?.includes("numbers-parser not installed")) {
80
- return { error: "numbers-parser not installed. Run: npm run setup" };
201
+ const stderr = error.stderr?.toString().trim() ?? "";
202
+ if (stderr.includes(`${PACKAGE} not installed`) || looksLikeMissingDep(stderr)) {
203
+ return { error: `${PACKAGE} not installed. ${setupHint()}` };
81
204
  }
82
205
  if (error.message?.includes("ETIMEDOUT") || error.message?.includes("timed out")) {
83
206
  return { error: `Operation timed out after ${timeoutMs}ms. File may be very large.` };
84
207
  }
208
+ // Surface the Python traceback when there is one — without it the user just
209
+ // sees "Command failed: <python> <args>" with no clue what actually broke.
210
+ if (stderr) {
211
+ return { error: stderr };
212
+ }
85
213
  return { error: error.message || "Unknown error executing Python script" };
86
214
  }
87
215
  }
216
+ export function runNumbersReader(command, args, timeoutMs = 30000) {
217
+ ensureReady();
218
+ const result = execReader(command, args, timeoutMs);
219
+ // Belt-and-suspenders: if the deps still look missing and we haven't tried a
220
+ // bootstrap yet, attempt it once and retry — covers a venv that exists but is
221
+ // missing the package, which the marker check alone wouldn't catch.
222
+ if (result.error &&
223
+ looksLikeMissingDep(result.error) &&
224
+ !bootstrapAttempted &&
225
+ !autoSetupDisabled()) {
226
+ if (bootstrapVenv()) {
227
+ return execReader(command, args, timeoutMs);
228
+ }
229
+ }
230
+ return result;
231
+ }
88
232
  export function checkDependencies() {
233
+ ensureReady();
89
234
  try {
90
- const python = cachedPython ?? (cachedPython = findPython());
91
- const version = execSync(`${python} -c "import numbers_parser; print(numbers_parser.__version__)"`, { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
92
- return { ok: true, message: `All dependencies available (numbers-parser ${version})` };
235
+ const python = resolvePython();
236
+ const version = execSync(`${python} -c "import ${MODULE}; print(${MODULE}.__version__)"`, {
237
+ encoding: "utf-8",
238
+ stdio: ["pipe", "pipe", "pipe"],
239
+ }).trim();
240
+ return { ok: true, message: `All dependencies available (${PACKAGE} ${version})` };
93
241
  }
94
242
  catch {
95
243
  return {
96
244
  ok: false,
97
- message: "numbers-parser not installed. Run: npm run setup",
245
+ message: `${PACKAGE} not installed. ${setupHint()}`,
98
246
  };
99
247
  }
100
248
  }
@@ -1 +1 @@
1
- {"version":3,"file":"python.js","sourceRoot":"","sources":["../../src/utils/python.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"python.js","sourceRoot":"","sources":["../../src/utils/python.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "apple-numbers-mcp",
3
- "version": "0.5.0",
3
+ "version": "0.6.0",
4
4
  "description": "MCP server for reading and writing Apple Numbers (.numbers) spreadsheet files",
5
5
  "type": "module",
6
6
  "main": "build/index.js",
package/scripts/setup.sh CHANGED
@@ -43,4 +43,8 @@ echo "==> Installing numbers-parser..."
43
43
  echo "==> Verifying installation..."
44
44
  "$VENV_DIR/bin/python3" -c "import numbers_parser; print(f' numbers-parser {numbers_parser.__version__} installed')"
45
45
 
46
+ # Record which requirements.txt this venv was built against, so the server can
47
+ # detect a stale venv after an update changes requirements and rebuild itself.
48
+ cp "$PROJECT_ROOT/requirements.txt" "$VENV_DIR/.deps-ok"
49
+
46
50
  echo "==> Done! Python venv ready."