apple-numbers-mcp 1.1.16 → 1.1.17

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
@@ -765,6 +765,11 @@ These are tracked for future releases. The underlying `numbers-parser` library h
765
765
  - Run `claude mcp list` to check for conflicting scopes; project-scope `.mcp.json` outranks a user-scope `apple-numbers` entry, and a local-scope entry outranks both.
766
766
  - If the server is listed as pending, approve the project-scope server when Claude Code prompts.
767
767
 
768
+ ### Every tool is rejected with "invalid outputSchema … unsupported dialect"
769
+ - Full symptom: `Tool '<name>' has an invalid outputSchema: JSON Schema declares an unsupported dialect ("$schema": "http://json-schema.org/draft-07/schema#"). The default validator supports JSON Schema 2020-12 only.` The host refuses **every** tool, so the server looks completely dead even though it started fine.
770
+ - **Upgrade to 1.1.17 or newer.** MCP standardized on JSON Schema 2020-12, and hosts now reject any other dialect; releases before 1.1.17 advertised draft-07 because the MCP SDK emits it. 1.1.17 advertises `https://json-schema.org/draft/2020-12/schema` on every tool's `inputSchema` and `outputSchema`.
771
+ - If you installed via `npx -y apple-numbers-mcp`, restart the host to pick up the new version; if you run from a clone, `git pull && pnpm install && pnpm run build`.
772
+
768
773
  ### "File not found"
769
774
  - Check the path; expand `~` if your shell isn't doing it.
770
775
  - Ensure the file extension is `.numbers`.
package/build/index.js CHANGED
@@ -22362,6 +22362,117 @@ function loadFileConfig(env = process.env, path = fileConfigPath(env)) {
22362
22362
  return applied;
22363
22363
  }
22364
22364
 
22365
+ // src/utils/jsonSchemaDialect.ts
22366
+ var JSON_SCHEMA_2020_12 = "https://json-schema.org/draft/2020-12/schema";
22367
+ var DEFINITIONS_REF_PREFIX = "#/definitions/";
22368
+ var SCHEMA_MAP_KEYWORDS = /* @__PURE__ */ new Set([
22369
+ "properties",
22370
+ "patternProperties",
22371
+ "$defs",
22372
+ "dependentSchemas"
22373
+ ]);
22374
+ var DATA_KEYWORDS = /* @__PURE__ */ new Set([
22375
+ "enum",
22376
+ "const",
22377
+ "default",
22378
+ "examples",
22379
+ "required",
22380
+ "dependentRequired"
22381
+ ]);
22382
+ function isPlainObject3(value) {
22383
+ return typeof value === "object" && value !== null && !Array.isArray(value);
22384
+ }
22385
+ function convertSchemaMap(node) {
22386
+ if (!isPlainObject3(node)) return node;
22387
+ const out = {};
22388
+ for (const [name, subschema] of Object.entries(node)) out[name] = convertNode(subschema);
22389
+ return out;
22390
+ }
22391
+ function convertNode(node) {
22392
+ if (Array.isArray(node)) return node.map(convertNode);
22393
+ if (!isPlainObject3(node)) return node;
22394
+ const hasTupleItems = Array.isArray(node.items);
22395
+ const out = {};
22396
+ for (const [key, value] of Object.entries(node)) {
22397
+ switch (key) {
22398
+ case "$schema":
22399
+ break;
22400
+ case "definitions":
22401
+ out.$defs = convertSchemaMap(value);
22402
+ break;
22403
+ case "$ref":
22404
+ out.$ref = typeof value === "string" && value.startsWith(DEFINITIONS_REF_PREFIX) ? "#/$defs/" + value.slice(DEFINITIONS_REF_PREFIX.length) : value;
22405
+ break;
22406
+ case "items":
22407
+ if (hasTupleItems) out.prefixItems = value.map(convertNode);
22408
+ else out.items = convertNode(value);
22409
+ break;
22410
+ case "additionalItems":
22411
+ if (hasTupleItems) out.items = convertNode(value);
22412
+ break;
22413
+ case "dependencies": {
22414
+ const dependentRequired = {};
22415
+ const dependentSchemas = {};
22416
+ if (isPlainObject3(value)) {
22417
+ for (const [property, dependency] of Object.entries(value)) {
22418
+ if (Array.isArray(dependency)) dependentRequired[property] = dependency;
22419
+ else dependentSchemas[property] = convertNode(dependency);
22420
+ }
22421
+ }
22422
+ if (Object.keys(dependentRequired).length > 0) out.dependentRequired = dependentRequired;
22423
+ if (Object.keys(dependentSchemas).length > 0) out.dependentSchemas = dependentSchemas;
22424
+ break;
22425
+ }
22426
+ case "exclusiveMinimum":
22427
+ case "exclusiveMaximum": {
22428
+ const bound = key === "exclusiveMinimum" ? node.minimum : node.maximum;
22429
+ if (value === true && typeof bound === "number") out[key] = bound;
22430
+ else if (value !== false) out[key] = convertNode(value);
22431
+ break;
22432
+ }
22433
+ case "minimum":
22434
+ if (node.exclusiveMinimum === true) break;
22435
+ out.minimum = convertNode(value);
22436
+ break;
22437
+ case "maximum":
22438
+ if (node.exclusiveMaximum === true) break;
22439
+ out.maximum = convertNode(value);
22440
+ break;
22441
+ default:
22442
+ if (DATA_KEYWORDS.has(key)) out[key] = value;
22443
+ else if (SCHEMA_MAP_KEYWORDS.has(key)) out[key] = convertSchemaMap(value);
22444
+ else out[key] = convertNode(value);
22445
+ }
22446
+ }
22447
+ return out;
22448
+ }
22449
+ function toJsonSchema2020_12(schema) {
22450
+ if (!isPlainObject3(schema)) return schema;
22451
+ return {
22452
+ $schema: JSON_SCHEMA_2020_12,
22453
+ ...convertNode(schema)
22454
+ };
22455
+ }
22456
+ function normalizeOutgoingMessage(message) {
22457
+ if (!isPlainObject3(message)) return message;
22458
+ const result = message.result;
22459
+ if (!isPlainObject3(result) || !Array.isArray(result.tools)) return message;
22460
+ const tools = result.tools.map((tool) => {
22461
+ if (!isPlainObject3(tool)) return tool;
22462
+ const next = { ...tool };
22463
+ if (isPlainObject3(tool.inputSchema)) next.inputSchema = toJsonSchema2020_12(tool.inputSchema);
22464
+ if (isPlainObject3(tool.outputSchema))
22465
+ next.outputSchema = toJsonSchema2020_12(tool.outputSchema);
22466
+ return next;
22467
+ });
22468
+ return { ...message, result: { ...result, tools } };
22469
+ }
22470
+ function withJsonSchema2020_12(transport) {
22471
+ const originalSend = transport.send.bind(transport);
22472
+ transport.send = (message, options) => originalSend(normalizeOutgoingMessage(message), options);
22473
+ return transport;
22474
+ }
22475
+
22365
22476
  // src/index.ts
22366
22477
  loadFileConfig();
22367
22478
  var __filename2 = fileURLToPath2(import.meta.url);
@@ -23200,7 +23311,7 @@ async function main() {
23200
23311
  process.on("unhandledRejection", (reason) => {
23201
23312
  console.error("[unhandledRejection]", reason);
23202
23313
  });
23203
- const transport = new StdioServerTransport();
23314
+ const transport = withJsonSchema2020_12(new StdioServerTransport());
23204
23315
  await server.connect(transport);
23205
23316
  console.error(`apple-numbers-mcp v${version2} running on stdio`);
23206
23317
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "apple-numbers-mcp",
3
- "version": "1.1.16",
3
+ "version": "1.1.17",
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",