MCP server for Apple Photos - query, search, export, and inspect the macOS Photos library via Claude and other AI assistants, plus opt-in album/metadata write tools (read-only by default)
Strong foundation with 21 well-named tools following verb_noun convention (query, export, create-album, etc.). All tools have descriptions exceeding 20 chars, many with explicit 'Use when/Do not use when' guidance. Input schemas present for all tools with type definitions and descriptions. However, output schemas are not formally documented in the tool registration, responses are described in prose but not as JSON Schema. Error handling guidance is present in descriptions but not structured as recovery patterns. Tool composition is excellent (single responsibility, chainable IDs), but some parameter descriptions could be more prescriptive about constraints and formats.
Add photos to an album. Requires APPLE_PHOTOS_MCP_ENABLE_WRITES=1.
Create a new album in the Photos library. Requires APPLE_PHOTOS_MCP_ENABLE_WRITES=1.
Use when: a tool returns a permission, 'unable to open', or 'write tools are disabled' error, or you want a full setup diagnostic before querying, exporting, or writing. Returns: six checks — Python interpreter (path + version; warns below 3.11), osxphotos install, sidecar mode (persistent vs one-shot, plus last respawn), the write-tools gate (enabled/disabled, with the opt-in recipe and — when enabled — whether the photoscript backend and Photos.app look usable), Photos library readability, and Full Disk Access — each reported ok/warn/fail with actionable advice. Do not use when: you only need the lightweight is-it-working smoke test — use health-check instead.
Export photos to a directory — originals or edited versions. Specify photos by UUID or use a query filter to export matching results.
Find exact-duplicate groups in the library — photos with identical content (same pixels).
Output schemas not formally documented in tool registration. Responses described in prose ('Returns: ...') but not as JSON Schema in outputSchema field. Clients cannot validate structured responses against a machine-readable contract.
List tools (list-albums, list-folders, list-keywords, list-persons) lack pagination parameters (limit, offset, cursor). No indication of result count or whether results are truncated. Large libraries could return unbounded lists, exhausting context.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | C | 66 | 2025-06-18+ | v2 |
Fetch full metadata for a single photo by UUID — location, dimensions, EXIF camera data, ML score, detected text, shared-album comments/likes, burst siblings, type flags, and more.
Fetch full metadata for multiple photos by UUID in a single batch call — more efficient than repeated get-photo calls.
Read the live Photos.app selection — the photos currently selected in the Photos.app window.
Fetch a thumbnail image for a photo by UUID — returns inline base64-encoded JPEG suitable for display in the client.
Use when: you want a quick smoke test that osxphotos is installed and the Photos library can be opened. Returns: ok/fail plus the osxphotos version, library path, and total photo count. While another operation (a long query or export) is running, it responds immediately with a liveness summary instead of queueing behind it — re-run after the operation completes for the full result. Do not use when: you need a full setup diagnostic that pinpoints whether the failure is a missing osxphotos, an unreadable library, or denied Full Disk Access — use doctor instead.
Import photos from a directory into the Photos library. Requires APPLE_PHOTOS_MCP_ENABLE_WRITES=1.
Use when: you want high-level stats about the whole library — total counts of photos, movies, albums, folders, keywords, and persons — or to confirm which library you're targeting before drilling in. Returns: the library path, Photos DB and Photos.app versions, and the six counts. Do not use when: you want the actual albums/keywords/persons rather than just their counts — use list-albums / list-keywords / list-persons; or you want to find specific photos — use query.
List all albums in the library with their photo counts and UUIDs.
List all folders in the library with their album counts and UUIDs.
List all keywords in the library with their photo counts.
List all persons (faces) in the library with their photo counts and UUIDs.
Use when: you need to find photos matching one or more filters — album, keyword, person, ML label, place, GPS radius (near), folder, taken-date or import-date range (addedAfter/addedInLast for 'recently imported'), year, file size, media type (screenshot, screen recording, selfie, panorama, live, portrait, time-lapse, slow-mo, burst, video), aesthetic score (minScore), OCR-detected text (detectedText), favorite/hidden flags, or title/description substrings — and get back a list of matches. This is the primary search/discovery tool; start here when you don't already have a UUID. Hidden photos are excluded unless hidden=true. Pass newestFirst=true with a limit to get the N most recent matches. Returns: count (the TOTAL number of matches), returned (the number of summaries in this response — capped at limit, default 500), and photo summaries (UUID, filename, date, dimensions, favorite/hidden/movie flags)
Remove photos from an album. Requires APPLE_PHOTOS_MCP_ENABLE_WRITES=1.
Set keywords on a photo. Requires APPLE_PHOTOS_MCP_ENABLE_WRITES=1.
Set the taken date on a photo. Requires APPLE_PHOTOS_MCP_ENABLE_WRITES=1.
Set title, description, and favorite/hidden flags on a photo. Requires APPLE_PHOTOS_MCP_ENABLE_WRITES=1.
Write tools (create-album, add-to-album, set-photo-metadata, etc.) lack explicit confirmation or dry-run support. Descriptions mention APPLE_PHOTOS_MCP_ENABLE_WRITES=1 gate but no per-call confirmation pattern for irreversible operations.
Error handling descriptions are narrative ('returns ok/fail') rather than structured error codes or recovery guidance. No explicit categorization of retryable vs user-fixable vs fatal errors.
Tool annotations (readOnlyHint, destructiveHint, idempotentHint) not present in tool registration. Risk classification is implicit in descriptions but not machine-readable.