apple-notes-mcp 2.7.1 → 2.7.3

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.
Files changed (3) hide show
  1. package/README.md +35 -5
  2. package/build/index.js +112 -1
  3. package/package.json +2 -1
package/README.md CHANGED
@@ -1187,16 +1187,26 @@ When sending content containing backslashes (`\`) to this MCP server, **you must
1187
1187
  ```json
1188
1188
  {
1189
1189
  "title": "Install Script",
1190
- "content": "cp ~/Library/Mobile\\\\ Documents/file.txt ~/.config/"
1190
+ "content": "cp ~/Library/Mobile\\ Documents/file.txt ~/.config/"
1191
1191
  }
1192
1192
  ```
1193
+ → arrives as: `cp ~/Library/Mobile\ Documents/file.txt ~/.config/`
1193
1194
 
1194
- The `\\\\` in JSON becomes `\\` in the actual string, which represents a single `\` in the note.
1195
+ In a JSON string literal the two characters `\\` denote **one** literal backslash. Doubling them to `\\\\` denotes *two* backslashes in the note, which is almost never what you want.
1196
+
1197
+ **Example - Literal double backslash:**
1198
+ ```json
1199
+ {
1200
+ "title": "Escaping Notes",
1201
+ "content": "Send \\\\ only when you want two backslashes"
1202
+ }
1203
+ ```
1204
+ → arrives as: `Send \\ only when you want two backslashes`
1195
1205
 
1196
1206
  **Common patterns requiring escaping:**
1197
- - Shell escaped spaces: `Mobile\ Documents` → `Mobile\\\\ Documents` in JSON
1198
- - Windows paths: `C:\Users\``C:\\\\Users\\\\` in JSON
1199
- - Regex patterns: `\d+``\\\\d+` in JSON
1207
+ - Shell escaped spaces: `Mobile\ Documents` → `Mobile\\ Documents` in JSON
1208
+ - Regex patterns: `\d+``\\d+` in JSON
1209
+ - Literal double backslash: `\\``\\\\` in JSON
1200
1210
 
1201
1211
  **If you see errors** when creating/updating notes with backslashes, double-check that backslashes are properly escaped in the JSON payload.
1202
1212
 
@@ -1229,6 +1239,26 @@ The `\\\\` in JSON becomes `\\` in the actual string, which represents a single
1229
1239
  - Apple Notes' internal HTML processing preserves empty divs from previous edits, so the gaps are baked into the note's internal representation and cannot be fixed through further updates
1230
1240
  - Fix: delete the note with `delete-note` and create a fresh one with `create-note`
1231
1241
 
1242
+ ### Every tool is refused: "invalid outputSchema … unsupported dialect"
1243
+
1244
+ If your client reports something like
1245
+
1246
+ ```
1247
+ Tool 'list-notes' has an invalid outputSchema: JSON Schema declares an unsupported
1248
+ dialect ("$schema": "http://json-schema.org/draft-07/schema#"). The default
1249
+ validator supports JSON Schema 2020-12 only.
1250
+ ```
1251
+
1252
+ you are on a version older than **2.7.2**. MCP standardized on JSON Schema
1253
+ 2020-12, and every tool this server advertised carried the older draft-07
1254
+ dialect, so clients rejected all of them at once — nothing about your Notes
1255
+ library, permissions, or configuration is involved.
1256
+
1257
+ - Fix: upgrade to 2.7.2 or later. `npx -y apple-notes-mcp@latest` picks it up on
1258
+ the next launch; a marketplace install updates through the marketplace.
1259
+ - Running from a clone: `git pull && pnpm install && pnpm run build`, then
1260
+ restart the client.
1261
+
1232
1262
  ### `apple-notes` server fails to connect when run from a clone
1233
1263
  - Launch `claude` from **inside the repo directory** so `CLAUDE_PROJECT_DIR` resolves to the repo root (the bare `.` fallback is unreliable — it points at the launching process's working directory)
1234
1264
  - If you've been editing the source, rerun `pnpm run build` — the entrypoint is `${CLAUDE_PROJECT_DIR:-.}/build/index.js`, and the committed bundle only reflects your changes after a rebuild
package/build/index.js CHANGED
@@ -42209,6 +42209,117 @@ function registerResourcesAndPrompts(server2, manager) {
42209
42209
  );
42210
42210
  }
42211
42211
 
42212
+ // src/utils/jsonSchemaDialect.ts
42213
+ var JSON_SCHEMA_2020_12 = "https://json-schema.org/draft/2020-12/schema";
42214
+ var DEFINITIONS_REF_PREFIX = "#/definitions/";
42215
+ var SCHEMA_MAP_KEYWORDS = /* @__PURE__ */ new Set([
42216
+ "properties",
42217
+ "patternProperties",
42218
+ "$defs",
42219
+ "dependentSchemas"
42220
+ ]);
42221
+ var DATA_KEYWORDS = /* @__PURE__ */ new Set([
42222
+ "enum",
42223
+ "const",
42224
+ "default",
42225
+ "examples",
42226
+ "required",
42227
+ "dependentRequired"
42228
+ ]);
42229
+ function isPlainObject3(value) {
42230
+ return typeof value === "object" && value !== null && !Array.isArray(value);
42231
+ }
42232
+ function convertSchemaMap(node) {
42233
+ if (!isPlainObject3(node)) return node;
42234
+ const out = {};
42235
+ for (const [name, subschema] of Object.entries(node)) out[name] = convertNode(subschema);
42236
+ return out;
42237
+ }
42238
+ function convertNode(node) {
42239
+ if (Array.isArray(node)) return node.map(convertNode);
42240
+ if (!isPlainObject3(node)) return node;
42241
+ const hasTupleItems = Array.isArray(node.items);
42242
+ const out = {};
42243
+ for (const [key, value] of Object.entries(node)) {
42244
+ switch (key) {
42245
+ case "$schema":
42246
+ break;
42247
+ case "definitions":
42248
+ out.$defs = convertSchemaMap(value);
42249
+ break;
42250
+ case "$ref":
42251
+ out.$ref = typeof value === "string" && value.startsWith(DEFINITIONS_REF_PREFIX) ? "#/$defs/" + value.slice(DEFINITIONS_REF_PREFIX.length) : value;
42252
+ break;
42253
+ case "items":
42254
+ if (hasTupleItems) out.prefixItems = value.map(convertNode);
42255
+ else out.items = convertNode(value);
42256
+ break;
42257
+ case "additionalItems":
42258
+ if (hasTupleItems) out.items = convertNode(value);
42259
+ break;
42260
+ case "dependencies": {
42261
+ const dependentRequired = {};
42262
+ const dependentSchemas = {};
42263
+ if (isPlainObject3(value)) {
42264
+ for (const [property, dependency] of Object.entries(value)) {
42265
+ if (Array.isArray(dependency)) dependentRequired[property] = dependency;
42266
+ else dependentSchemas[property] = convertNode(dependency);
42267
+ }
42268
+ }
42269
+ if (Object.keys(dependentRequired).length > 0) out.dependentRequired = dependentRequired;
42270
+ if (Object.keys(dependentSchemas).length > 0) out.dependentSchemas = dependentSchemas;
42271
+ break;
42272
+ }
42273
+ case "exclusiveMinimum":
42274
+ case "exclusiveMaximum": {
42275
+ const bound = key === "exclusiveMinimum" ? node.minimum : node.maximum;
42276
+ if (value === true && typeof bound === "number") out[key] = bound;
42277
+ else if (value !== false) out[key] = convertNode(value);
42278
+ break;
42279
+ }
42280
+ case "minimum":
42281
+ if (node.exclusiveMinimum === true) break;
42282
+ out.minimum = convertNode(value);
42283
+ break;
42284
+ case "maximum":
42285
+ if (node.exclusiveMaximum === true) break;
42286
+ out.maximum = convertNode(value);
42287
+ break;
42288
+ default:
42289
+ if (DATA_KEYWORDS.has(key)) out[key] = value;
42290
+ else if (SCHEMA_MAP_KEYWORDS.has(key)) out[key] = convertSchemaMap(value);
42291
+ else out[key] = convertNode(value);
42292
+ }
42293
+ }
42294
+ return out;
42295
+ }
42296
+ function toJsonSchema2020_12(schema) {
42297
+ if (!isPlainObject3(schema)) return schema;
42298
+ return {
42299
+ $schema: JSON_SCHEMA_2020_12,
42300
+ ...convertNode(schema)
42301
+ };
42302
+ }
42303
+ function normalizeOutgoingMessage(message) {
42304
+ if (!isPlainObject3(message)) return message;
42305
+ const result = message.result;
42306
+ if (!isPlainObject3(result) || !Array.isArray(result.tools)) return message;
42307
+ const tools = result.tools.map((tool) => {
42308
+ if (!isPlainObject3(tool)) return tool;
42309
+ const next = { ...tool };
42310
+ if (isPlainObject3(tool.inputSchema)) next.inputSchema = toJsonSchema2020_12(tool.inputSchema);
42311
+ if (isPlainObject3(tool.outputSchema))
42312
+ next.outputSchema = toJsonSchema2020_12(tool.outputSchema);
42313
+ return next;
42314
+ });
42315
+ return { ...message, result: { ...result, tools } };
42316
+ }
42317
+ function withJsonSchema2020_12(transport2) {
42318
+ const originalSend = transport2.send.bind(transport2);
42319
+ transport2.send = (message, options) => originalSend(normalizeOutgoingMessage(message), options);
42320
+ return transport2;
42321
+ }
42322
+
42212
42323
  // src/index.ts
42213
42324
  loadFileConfig();
42214
42325
  var require2 = createRequire(import.meta.url);
@@ -43747,7 +43858,7 @@ for (const sig of ["SIGINT", "SIGTERM"]) {
43747
43858
  }
43748
43859
  process.stdin.on("end", shutdown);
43749
43860
  process.stdin.on("close", shutdown);
43750
- var transport = new StdioServerTransport();
43861
+ var transport = withJsonSchema2020_12(new StdioServerTransport());
43751
43862
  await server.connect(transport);
43752
43863
  /*! Bundled license information:
43753
43864
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "apple-notes-mcp",
3
- "version": "2.7.1",
3
+ "version": "2.7.3",
4
4
  "description": "MCP server for Apple Notes - create, search, update, and manage notes via Claude and other AI assistants",
5
5
  "type": "module",
6
6
  "main": "build/index.js",
@@ -53,6 +53,7 @@
53
53
  "@typescript-eslint/eslint-plugin": "^8.0.0",
54
54
  "@typescript-eslint/parser": "^8.0.0",
55
55
  "@vitest/coverage-v8": "^3.2.6",
56
+ "ajv": "^8.17.1",
56
57
  "esbuild": "^0.28.1",
57
58
  "eslint": "^9.0.0",
58
59
  "globals": "^17.0.0",