@thenavidm/apple-photos-mcp-cli 1.0.2 → 1.0.4

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/lib/tools/kit.js CHANGED
@@ -3,6 +3,13 @@ import { z } from "zod";
3
3
  import { PhotosError, ToolError } from "../errors.js";
4
4
  import { annotationsFor, needsConfirm } from "../safety.js";
5
5
  export function ok(data) {
6
+ // Content parts that are already MCP-shaped pass straight through. That is
7
+ // what keeps look_at_photos working: it returns images interleaved with
8
+ // captions, and serialising them into a text blob deletes the pictures,
9
+ // leaving a tool whose whole purpose is seeing that returns filenames.
10
+ if (Array.isArray(data) && data.every((p) => p && typeof p === "object" && "type" in p)) {
11
+ return { content: data };
12
+ }
6
13
  const text = typeof data === "string" ? data : JSON.stringify(data, null, 2);
7
14
  return { content: [{ type: "text", text }] };
8
15
  }
@@ -31,19 +38,35 @@ export async function runTool(spec, args, ctx) {
31
38
  const summary = spec.summary?.(args) ?? spec.name;
32
39
  ctx.guard.check(spec.name, spec.risk, args.confirm, summary);
33
40
  }
34
- // Drop empties so Python sees its own defaults rather than nulls.
35
- const payload = Object.fromEntries(Object.entries(args).filter(([, v]) => v !== undefined && v !== null && v !== ""));
36
- const result = await ctx.bridge.call(spec.python ?? spec.name, payload);
41
+ // Only undefined and null are dropped. An empty string is a real value here:
42
+ // clearing a caption is `set_photo_description --description ""`, and
43
+ // stripping it made the engine reject the call for a missing required
44
+ // argument the caller had plainly supplied.
45
+ const payload = Object.fromEntries(Object.entries(args).filter(([, v]) => v !== undefined && v !== null));
46
+ const result = await ctx.bridge.call(spec.python ?? spec.name, payload, spec.timeoutMs);
37
47
  if (result.isError)
38
48
  throw new ToolError(result.text || `${spec.name} failed.`);
39
- // The Python returns JSON as text. Parse it so `--json` gives real fields and
40
- // an MCP client gets structure rather than a string containing JSON.
49
+ // Anything that is not plain text — images from look_at_photos — is returned
50
+ // as content parts rather than squashed into a string.
51
+ if (result.content.some((part) => part.type !== "text"))
52
+ return result.content;
53
+ let parsed;
41
54
  try {
42
- return JSON.parse(result.text);
55
+ parsed = JSON.parse(result.text);
43
56
  }
44
57
  catch {
45
58
  return result.text;
46
59
  }
60
+ // The engine reports its own failures as an ordinary return carrying
61
+ // {"error": ...}, which the protocol marks successful. Without this check a
62
+ // failed export exited 0 with the error printed on stdout, so
63
+ // `export-originals ... && rm ...` would go on to delete the source.
64
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
65
+ const record = parsed;
66
+ if (typeof record.error === "string" && record.ok !== true)
67
+ throw new ToolError(record.error);
68
+ }
69
+ return parsed;
47
70
  }
48
71
  export function register(server, contextFor, spec) {
49
72
  server.registerTool(spec.name, {
@@ -1 +1 @@
1
- {"version":3,"file":"kit.js","sourceRoot":"","sources":["../../src-ts/tools/kit.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"kit.js","sourceRoot":"","sources":["../../src-ts/tools/kit.ts"],"names":[],"mappings":"AAAA,uFAAuF;AAGvF,OAAO,EAAE,CAAC,EAAoB,MAAM,KAAK,CAAC;AAI1C,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,YAAY,EAA8B,MAAM,cAAc,CAAC;AAKxF,MAAM,UAAU,EAAE,CAAC,IAAa;IAC9B,2EAA2E;IAC3E,wEAAwE;IACxE,wEAAwE;IACxE,uEAAuE;IACvE,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,MAAM,IAAI,CAAC,CAAC,EAAE,CAAC;QACxF,OAAO,EAAE,OAAO,EAAE,IAA6B,EAAE,CAAC;IACpD,CAAC;IACD,MAAM,IAAI,GAAG,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAC7E,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;AAC/C,CAAC;AAED,MAAM,UAAU,IAAI,CAAC,KAAc;IACjC,MAAM,OAAO,GACX,KAAK,YAAY,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAG,KAAe,EAAE,OAAO,IAAI,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;IACxG,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;AAChG,CAAC;AAED,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,OAAO,EAAE,CAAC;SACP,OAAO,EAAE;SACT,QAAQ,EAAE;SACV,QAAQ,CAAC,iHAAiH,CAAC;CAC/H,CAAC;AAgBF,MAAM,UAAU,UAAU,CAAwB,IAAiB;IACjE,OAAO,IAAI,CAAC;AACd,CAAC;AAID;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,OAAO,CAC3B,IAAiB,EACjB,IAA6B,EAC7B,GAAgB;IAEhB,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;QACzB,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC,IAAa,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC;QAC3D,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAG,IAA8B,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAC1F,CAAC;IAED,6EAA6E;IAC7E,sEAAsE;IACtE,sEAAsE;IACtE,4CAA4C;IAC5C,MAAM,OAAO,GAAG,MAAM,CAAC,WAAW,CAChC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,SAAS,IAAI,CAAC,KAAK,IAAI,CAAC,CACtE,CAAC;IAEF,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;IACxF,IAAI,MAAM,CAAC,OAAO;QAAE,MAAM,IAAI,SAAS,CAAC,MAAM,CAAC,IAAI,IAAI,GAAG,IAAI,CAAC,IAAI,UAAU,CAAC,CAAC;IAE/E,6EAA6E;IAC7E,uDAAuD;IACvD,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,MAAM,CAAC;QAAE,OAAO,MAAM,CAAC,OAAO,CAAC;IAE/E,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACnC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,MAAM,CAAC,IAAI,CAAC;IACrB,CAAC;IAED,qEAAqE;IACrE,4EAA4E;IAC5E,8DAA8D;IAC9D,qEAAqE;IACrE,IAAI,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QACnE,MAAM,MAAM,GAAG,MAAiC,CAAC;QACjD,IAAI,OAAO,MAAM,CAAC,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,EAAE,KAAK,IAAI;YAAE,MAAM,IAAI,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAChG,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,MAAiB,EAAE,UAA6B,EAAE,IAAiB;IAC1F,MAAM,CAAC,YAAY,CACjB,IAAI,CAAC,IAAI,EACT;QACE,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,WAAW,EAAE,IAAI,CAAC,WAAW;QAC7B,WAAW,EAAE,IAAI,CAAC,MAAM;QACxB,WAAW,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,GAAG,cAAc,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,CAAC,EAAE;KAClG,EACD,CAAC,KAAK,EAAE,IAA6B,EAAE,EAAE;QACvC,IAAI,CAAC;YACH,OAAO,EAAE,CAAC,MAAM,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC;QACrD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC;QACrB,CAAC;IACH,CAAC,CAAU,CACZ,CAAC;AACJ,CAAC;AAED,OAAO,EAAE,YAAY,EAAE,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thenavidm/apple-photos-mcp-cli",
3
- "version": "1.0.2",
3
+ "version": "1.0.4",
4
4
  "description": "Apple Photos MCP server and CLI for Claude Code and AI agents. 13 tools to search, look at, organise and export your own Photos library, entirely on your Mac.",
5
5
  "type": "module",
6
6
  "main": "./lib/index.js",
@@ -31,10 +31,10 @@
31
31
  "homepage": "https://navid.me",
32
32
  "repository": {
33
33
  "type": "git",
34
- "url": "git+https://github.com/navidmoazzez/apple-photos-mcp.git"
34
+ "url": "git+https://github.com/navidmoazzez/apple-photos-mcp-cli.git"
35
35
  },
36
36
  "bugs": {
37
- "url": "https://github.com/navidmoazzez/apple-photos-mcp/issues"
37
+ "url": "https://github.com/navidmoazzez/apple-photos-mcp-cli/issues"
38
38
  },
39
39
  "keywords": [
40
40
  "mcp",
package/pyproject.toml CHANGED
@@ -4,7 +4,7 @@
4
4
  # name is free, so both Python packages are named the same way. The installed
5
5
  # command is still `apple-photos-mcp`.
6
6
  name = "thenavidm-apple-photos-mcp"
7
- version = "0.1.0"
7
+ version = "1.0.4"
8
8
  description = "Apple Photos MCP server for Claude Code and AI agents. Photo search, scene labels, text in images, faces, places, albums, previews, and exports."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -33,8 +33,8 @@ dependencies = [
33
33
  ]
34
34
 
35
35
  [project.urls]
36
- Homepage = "https://github.com/navidmoazzez/apple-photos-mcp"
37
- Issues = "https://github.com/navidmoazzez/apple-photos-mcp/issues"
36
+ Homepage = "https://github.com/navidmoazzez/apple-photos-mcp-cli"
37
+ Issues = "https://github.com/navidmoazzez/apple-photos-mcp-cli/issues"
38
38
  Author = "https://navid.me"
39
39
 
40
40
  [project.scripts]
@@ -67,7 +67,7 @@ def run(config: Config, lib: PhotosLibrary) -> dict[str, Any]:
67
67
  found,
68
68
  str(lib_path),
69
69
  "Open Photos once so macOS records a library path, or set "
70
- "APPLE_PHOTOS_MCP_LIBRARY to a .photoslibrary folder.",
70
+ "APPLE_PHOTOS_LIBRARY to a .photoslibrary folder.",
71
71
  )
72
72
  )
73
73
  except Exception as exc:
@@ -76,7 +76,7 @@ def run(config: Config, lib: PhotosLibrary) -> dict[str, Any]:
76
76
  "library found",
77
77
  False,
78
78
  str(exc),
79
- "Set APPLE_PHOTOS_MCP_LIBRARY to your .photoslibrary path.",
79
+ "Set APPLE_PHOTOS_LIBRARY to your .photoslibrary path.",
80
80
  )
81
81
  )
82
82