apple-notes-mcp 2.9.34 → 2.9.35

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
@@ -2097,7 +2097,10 @@ On macOS 27, Notes' AppleScript does not list PDF attachments, so it cannot see
2097
2097
  a PDF this tool just added. When that happens and the server has Full Disk
2098
2098
  Access, it verifies through the read-only NoteStore database instead: success
2099
2099
  requires exactly one new attachment row on the note whose media file matches
2100
- the source bytes, and the result carries `verifiedBy: "database"`. Without Full
2100
+ the source bytes, whose type fits the file's extension, and, when the decoded
2101
+ note body lists attachments, that the body references. The check repeats for
2102
+ about two seconds while Notes' database catches up, and `contentHash` is read
2103
+ after it finishes. The result carries `verifiedBy: "database"`. Without Full
2101
2104
  Disk Access a PDF attach reports "insertion outcome uncertain"; read the note
2102
2105
  before retrying, because the attachment was probably created.
2103
2106
 
package/build/index.js CHANGED
@@ -54118,18 +54118,34 @@ function storedAttachmentIds(manager, id2) {
54118
54118
  return null;
54119
54119
  }
54120
54120
  }
54121
- function storedInsertion(manager, id2, before, bytes, returnedId) {
54121
+ var KIND_BY_EXTENSION = {
54122
+ ".pdf": "pdf",
54123
+ ".png": "image",
54124
+ ".jpg": "image",
54125
+ ".jpeg": "image",
54126
+ ".heic": "image",
54127
+ ".tif": "image",
54128
+ ".tiff": "image",
54129
+ ".gif": "image"
54130
+ };
54131
+ function referencedByBody(assets, row) {
54132
+ return assets.orderSource === "body" ? row.bodyIndex !== null : void 0;
54133
+ }
54134
+ function storedInsertion(manager, id2, before, bytes, name, returnedId) {
54122
54135
  let added = [];
54136
+ let assets;
54123
54137
  for (let attempt = 0; attempt < 8; attempt++) {
54124
54138
  if (attempt > 0) pause(250);
54125
54139
  try {
54126
- added = manager.getAttachmentAssetsById(id2).attachments.filter(
54140
+ assets = manager.getAttachmentAssetsById(id2);
54141
+ added = assets.attachments.filter(
54127
54142
  (item) => item.parentIdentifier === null && !before.has(item.identifier.toLowerCase())
54128
54143
  );
54129
54144
  } catch {
54130
54145
  added = [];
54131
54146
  }
54132
- if (added.length === 1 && added[0].assetPaths.length > 0) break;
54147
+ if (added.length === 1 && added[0].assetPaths.length > 0 && referencedByBody(assets, added[0]) !== false)
54148
+ break;
54133
54149
  }
54134
54150
  if (added.length === 0) return null;
54135
54151
  if (added.length > 1) throw new Error(UNCERTAIN);
@@ -54137,6 +54153,15 @@ function storedInsertion(manager, id2, before, bytes, returnedId) {
54137
54153
  const attachmentId = attachmentCoreDataId(id2, row.pk);
54138
54154
  if (returnedId && /\/ICAttachment\/p\d+$/.test(returnedId) && returnedId !== attachmentId)
54139
54155
  throw new Error(UNCERTAIN);
54156
+ const expectedKind = KIND_BY_EXTENSION[extname7(name).toLowerCase()];
54157
+ if (expectedKind && row.kind !== expectedKind)
54158
+ throw new Error(
54159
+ `Notes' database shows new attachment ${attachmentId} on this note, but its type (${row.uti ?? "unknown"}) does not fit ${name}; read the exact note and do not attach the file again`
54160
+ );
54161
+ if (referencedByBody(assets, row) === false)
54162
+ throw new Error(
54163
+ `Notes' database shows new attachment ${attachmentId} on this note, but the note body does not reference it; read the exact note and do not attach the file again`
54164
+ );
54140
54165
  const expected = sha256(bytes);
54141
54166
  const matches = row.assetPaths.some((path10) => fileMatches(path10, bytes.length, expected));
54142
54167
  if (!matches)
@@ -54188,7 +54213,7 @@ function attachFile(manager, args, checked, progress = { insertionStarted: false
54188
54213
  if (!saved.success || !fileMatches(saved.savedPath ?? verifyPath, bytes.length, sha256(bytes)))
54189
54214
  throw new Error("Attachment bytes were not verified; read the exact note before retrying");
54190
54215
  } else {
54191
- const stored = inserted.length === 0 && beforeStored ? storedInsertion(manager, id2, beforeStored, bytes, returnedId) : null;
54216
+ const stored = inserted.length === 0 && beforeStored ? storedInsertion(manager, id2, beforeStored, bytes, name, returnedId) : null;
54192
54217
  if (!stored)
54193
54218
  throw new Error(
54194
54219
  inserted.length === 0 && !beforeStored ? `${UNCERTAIN}. Notes' AppleScript does not list some attachments (PDFs on macOS 27); grant Full Disk Access so the server can verify through the Notes database` : UNCERTAIN
@@ -54198,11 +54223,17 @@ function attachFile(manager, args, checked, progress = { insertionStarted: false
54198
54223
  verifiedBy = "database";
54199
54224
  }
54200
54225
  const nameVerified = reportedName === name;
54226
+ let contentHash = after.hash;
54227
+ if (verifiedBy === "database") {
54228
+ const final = readSnapshot(manager, id2);
54229
+ assertExistingContentPreserved(before, final);
54230
+ contentHash = final.hash;
54231
+ }
54201
54232
  return {
54202
54233
  ok: true,
54203
54234
  id: id2,
54204
54235
  attachmentId,
54205
- contentHash: after.hash,
54236
+ contentHash,
54206
54237
  bytes: bytes.length,
54207
54238
  name: reportedName,
54208
54239
  ...verifiedBy === "database" ? { verifiedBy } : {},
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "apple-notes-mcp",
3
- "version": "2.9.34",
3
+ "version": "2.9.35",
4
4
  "description": "MCP server for Apple Notes - read, search, create, edit, organize, and export notes on macOS via Claude and other AI assistants",
5
5
  "type": "module",
6
6
  "main": "build/index.js",