@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/LICENSE +1 -1
- package/README.md +129 -32
- package/SKILL.md +16 -0
- package/lib/bridge.d.ts +23 -12
- package/lib/bridge.js +48 -21
- package/lib/bridge.js.map +1 -1
- package/lib/cli.d.ts +6 -14
- package/lib/cli.js +72 -94
- package/lib/cli.js.map +1 -1
- package/lib/config.d.ts +5 -1
- package/lib/config.js +32 -2
- package/lib/config.js.map +1 -1
- package/lib/index.js +6 -6
- package/lib/index.js.map +1 -1
- package/lib/tools/index.js +22 -7
- package/lib/tools/index.js.map +1 -1
- package/lib/tools/kit.d.ts +6 -2
- package/lib/tools/kit.js +29 -6
- package/lib/tools/kit.js.map +1 -1
- package/package.json +3 -3
- package/pyproject.toml +3 -3
- package/src/apple_photos_mcp/doctor.py +2 -2
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
|
-
//
|
|
35
|
-
|
|
36
|
-
|
|
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
|
-
//
|
|
40
|
-
//
|
|
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
|
-
|
|
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, {
|
package/lib/tools/kit.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
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,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;
|
|
1
|
+
{"version":3,"file":"kit.js","sourceRoot":"","sources":["../../src-ts/tools/kit.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thenavidm/apple-photos-mcp-cli",
|
|
3
|
-
"version": "1.0.
|
|
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 = "
|
|
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
|
-
"
|
|
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
|
|
79
|
+
"Set APPLE_PHOTOS_LIBRARY to your .photoslibrary path.",
|
|
80
80
|
)
|
|
81
81
|
)
|
|
82
82
|
|