Apple Photos MCP Server

Search, inspect and export photos from the macOS Photos library, with optional album and metadata edits

By Rob Sweet (individual) TypeScript Local · stdio MediaFiles and storage

43 popularity score ★ 44 ↓ 761/wk

Connect your client

Local (npm)

Add in one click

Opens the app, which asks before it adds the server.

Or add it by command or config

Claude CodeTerminal
claude mcp add apple-photos -- npx -y apple-photos-mcp
Claude Desktopclaude_desktop_config.json
{
  "mcpServers": {
    "apple-photos": {
      "command": "npx",
      "args": [
        "-y",
        "apple-photos-mcp"
      ]
    }
  }
}
Cursor~/.cursor/mcp.json
{
  "mcpServers": {
    "apple-photos": {
      "command": "npx",
      "args": [
        "-y",
        "apple-photos-mcp"
      ]
    }
  }
}
VS Code.vscode/mcp.json
{
  "servers": {
    "apple-photos": {
      "type": "stdio",
      "command": "npx",
      "args": [
        "-y",
        "apple-photos-mcp"
      ]
    }
  }
}
Codex~/.codex/config.toml
[mcp_servers.apple-photos]
command = "npx"
args = ["-y", "apple-photos-mcp"]
Gemini CLITerminal
gemini mcp add --scope user apple-photos npx -- -y apple-photos-mcp
Local (from source)

Add in one click

Opens the app, which asks before it adds the server. Then replace each <NAME> in its settings with your value.

Or add it by command or config

FirstTerminal
git clone https://github.com/sweetrb/apple-photos-mcp.git
cd apple-photos-mcp
pnpm install
pnpm run build
Claude CodeTerminal
claude mcp add apple-photos -- node '<ABSOLUTE_PATH_TO_CLONE>/build/index.js'
Claude Desktopclaude_desktop_config.json
{
  "mcpServers": {
    "apple-photos": {
      "command": "node",
      "args": [
        "<ABSOLUTE_PATH_TO_CLONE>/build/index.js"
      ]
    }
  }
}
Cursor~/.cursor/mcp.json
{
  "mcpServers": {
    "apple-photos": {
      "command": "node",
      "args": [
        "<ABSOLUTE_PATH_TO_CLONE>/build/index.js"
      ]
    }
  }
}
VS Code.vscode/mcp.json
{
  "servers": {
    "apple-photos": {
      "type": "stdio",
      "command": "node",
      "args": [
        "<ABSOLUTE_PATH_TO_CLONE>/build/index.js"
      ]
    }
  }
}
Codex~/.codex/config.toml
[mcp_servers.apple-photos]
command = "node"
args = ["<ABSOLUTE_PATH_TO_CLONE>/build/index.js"]
Gemini CLITerminal
gemini mcp add --scope user apple-photos node -- '<ABSOLUTE_PATH_TO_CLONE>/build/index.js'

Settings 8

APPLE_PHOTOS_MCP_ENABLE_WRITES Optional: Set to 1 to allow the seven write tools; unset keeps the server read-only.
APPLE_PHOTOS_MCP_TIMEOUT Optional: Default helper timeout in ms for read tools (60000); raise for very large libraries.
APPLE_PHOTOS_MCP_MAX_BUFFER Optional: Max bytes read from the Python helper's output (100 MB by default).
APPLE_PHOTOS_MCP_STALE_WHILE_REVALIDATE Optional: Set to 1 to answer from the last parse while a changed library re-parses in the background.
APPLE_PHOTOS_MCP_SIDECAR_IDLE_MS Optional: Idle time in ms before the Python helper is stopped (300000); 0 keeps it running.
APPLE_PHOTOS_MCP_NO_AUTO_SETUP Optional: Set to 1 to skip the automatic osxphotos venv setup and install it yourself.
APPLE_PHOTOS_MCP_SETUP_TIMEOUT Optional: Max ms the automatic venv setup may run (300000).
APPLE_PHOTOS_MCP_CONFIG_FILE Optional: Path of the JSON settings file used when the host drops env values.

What it does

Apple Photos MCP Server gives an assistant access to the Photos library on a Mac. It is a Node program that talks MCP over stdio and hands the actual library work to a bundled Python helper built on osxphotos, which reads the library's SQLite database directly. Everything happens on the user's machine.

On the reading side it can filter the library by date taken or date imported, album, keyword, named person, Photos' own ML labels, place name, GPS radius, media type (screenshots, selfies, bursts and so on), aesthetic score or text Photos found in the image. It returns full metadata including EXIF camera data, shows a photo inline as a thumbnail, groups exact duplicates, reads what is currently selected in Photos.app, and copies originals or edited versions out to a folder, downloading iCloud-only originals through Photos.app when needed.

Writing is off by default. With APPLE_PHOTOS_MCP_ENABLE_WRITES=1 (set as an env value or in its config.json) it can create albums, add or remove photos from albums, set titles, descriptions, favourites, keywords and dates, and import files. These edits go through Photos.app by AppleScript, not the database. No tool deletes a photo, album or folder.

The README documents each tool but never gives a count: the v2.1.20 source (src/index.ts) registers 21 tools, 14 that read and seven gated write tools, which stay listed even while writes are disabled and return an opt-in error when called.

What it needs

RuntimeNode.js 20+

macOS with a Photos library; Node.js 20 or newer; Python 3.11 or newer with pip on the PATH (stock macOS ships 3.9). On the first tool call it builds a local Python venv with osxphotos, which needs network access and takes about a minute. The app that launches the server (Claude Desktop, Terminal, VS Code) needs Full Disk Access; write tools also trigger a one-time macOS Automation prompt for controlling Photos.app.

Limits

Read-only unless APPLE_PHOTOS_MCP_ENABLE_WRITES=1; even then nothing can be deleted, and an import cannot be undone except by hand in Photos.app. Writes act on whichever library Photos.app has open, not the library parameter. remove-from-album rebuilds the album, so its UUID changes and manual sort order is lost. query returns 500 results by default (limit up to 100000); album edits take at most 100 UUIDs and imports 50 files per call. export writes only under the home folder, /tmp, /private/tmp or /Volumes. Person filters work only on named faces. Large libraries can exceed the 60-second default timeout (APPLE_PHOTOS_MCP_TIMEOUT). Claude Desktop drops env values, so use the config file.

Who it suits

Suits Mac users who want an assistant to find, review, tag or pull out photos from their own Photos library without uploading anything, since it reads the library locally and stays read-only until writes are switched on. The opt-in edits fit album filing and keyword clean-up, but anyone who needs deletion, bulk wildcard edits, or a non-Mac or cloud-hosted photo service should look elsewhere. It is a community project, not from Apple, and depends on Full Disk Access and a recent Python being set up first.

Tools 21

health-check
Confirms osxphotos is installed and the library opens
doctor
Runs setup checks (Python, osxphotos, helper mode, write gate, library access, Full Disk Access) with advice
library-info
Counts photos, videos, albums, folders, keywords and people
query
Finds photos by combinable filters such as date, album, keyword, person, place or media type
get-photo
Returns full metadata for one photo, including EXIF and location
get-photos
Returns full metadata for up to 50 photos at once
get-selected-photos
Reads which photos are selected in the Photos.app window
get-thumbnail
Returns a photo as an inline image from Photos' preview files
find-duplicates
Groups exact duplicates using Photos' fingerprints
list-albums
Lists albums with folder paths and photo counts
list-folders
Lists folders with their parents and contents counts
list-keywords
Lists keywords ordered by how often they are used
list-persons
Lists people recognised by Photos, ordered by photo count
export
Copies originals or edited versions of chosen photos to an allowed folder
create-album
Creates an album, optionally inside a folder (write, opt-in)
add-to-album
Adds photos to an album by UUID (write, opt-in)
remove-from-album
Takes photos out of an album by rebuilding it (write, opt-in)
set-photo-metadata
Changes a photo's title, description or favourite flag (write, opt-in)
set-keywords
Adds or removes keywords while keeping the rest (write, opt-in)
set-photo-date
Sets or shifts a photo's date, as a dry run unless told otherwise (write, opt-in)
import-photos
Imports files into the library, optionally into an album (write, opt-in)

Similar servers