immich-library-mcp
Provides tools for searching, browsing, analysing, exporting, and organising an Immich photo library, including CLIP content search, metadata and EXIF lookup, people/albums/tags/places, image and contact-sheet viewing, duplicate and storage analysis, gallery exports with manifests, and optional curation such as favourites, ratings, descriptions, tags, albums, uploads, and reprocessing.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@immich-library-mcpshow me recent photos of my dog and make a contact sheet"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
immich-library-mcp
MCP server for an Immich photo library (built against Immich v3.3.3). It lets an agent search the library by content (CLIP smart search) or by metadata, read EXIF/people/album/tag detail, count and map the library, look at the photos themselves (preview/thumbnail images and numbered contact sheets returned as MCP image content), analyse it (duplicates, largest files, stacks, activity, processing queues), export browser-ready files plus a metadata manifest, stage originals on a shared mount for other MCP servers and, with a second key, organise it (favourites, ratings, descriptions, dates, locations, tags, albums, people, uploads, reprocessing).
Two keys, two trust levels:
IMMICH_API_KEY(always): read-only. Scope it to read permissions only, so Immich itself refuses writes (the integration suite asserts a403on album create). With only this key the server is read-only: the curation tools are not registered at all, and the only writes are local files (the shared mount and the export folder).IMMICH_WRITE_API_KEY(optional): curation. Scoped to exactly the 13 write permissions the curation tools use and no read permissions, so every lookup still goes through the read key. It cannot delete or trash photos, share anything, or touch admin settings (the integration suite asserts403s on/server/about,DELETE /assetsandPOST /shared-links). Give it only to clients that should organise the library; a shared HTTP deployment (chat front ends, automation) can run without it.
Install
uvx immich-library-mcp --stdio # or: pip install immich-library-mcpThe distribution is immich-library-mcp (the name immich-mcp on PyPI belongs to
another project); the import package is immich_mcp, and both immich-library-mcp
and immich-mcp commands are installed. Claude Desktop / Claude Code (stdio):
{"mcpServers": {"immich": {"command": "uvx", "args": ["immich-library-mcp", "--stdio"],
"env": {"IMMICH_URL": "http://localhost:2283", "IMMICH_API_KEY": "<read-only key>"}}}}Related MCP server: Immich MCP Server
Tools
All tools take at least one parameter (Claude.ai's remote client rejects
empty schemas). Every read tool carries readOnlyHint. The local file
writers (immich_download, immich_export, immich_export_cleanup) and
the curation tools don't; immich_export_cleanup, immich_delete_album,
immich_delete_tag and immich_merge_people are marked destructiveHint
(and prompt for confirmation through the fleet's MCP guard).
Reading
Tool | What it does | Key parameters |
| Find assets. |
|
| How many assets match | same filters (no |
| Full metadata: EXIF, GPS + place, people, tags, albums, live-photo link, OCR text |
|
| Returns the images (with caption lines) so the model can see them |
|
| One grid JPEG of up to 50 thumbnails, each stamped with its index ( |
|
| Named people (face clusters), optional asset counts |
|
| Albums with counts and date span |
|
| Geotagged counts per country/state/city |
|
| "On this day" memories |
|
| Library summary (version, totals, span, people, albums, tags, countries) |
|
| Save one original/fullsize/preview: on the shared mount ( |
|
| Export up to 200 assets as browser-ready files + |
|
| Delete export folders/files whose newest file is older than N days |
|
Library analysis (read)
Tool | What it does | Key parameters |
| Immich's duplicate groups (visually near-identical), with sizes, dimensions, the suggested keeper and reclaimable space |
|
| Biggest files first |
|
| Random assets, narrowed by the search filters |
|
| Bursts / RAW+JPEG pairs: list stacks, or every member of one asset's stack |
|
| Photos per day: total, active days, busiest days, per-month totals (every day when ≤62 days) |
|
| Background queues (faces, OCR, smart search, thumbnails …): waiting/active/failed |
|
| Folders Immich stores originals under, or the assets in one |
|
| One album: description, count, span, users, order, cover, top places, first N assets |
|
| One person: flags, asset count, link, and their face thumbnail as an image |
|
immich_get_asset also returns Immich's per-asset key/value metadata, the
stack it belongs to and its duplicate group.
Organising (only with IMMICH_WRITE_API_KEY)
Tool | What it does | Key parameters |
| Change up to 200 assets; only the fields passed change. Returns each asset's previous values so the change can be put back |
|
| Tag (creating missing tags; |
|
| Delete a tag everywhere (assets untouched); reports how many had it. Destructive, asks first |
|
| New private album, optionally with assets; flags a name clash |
|
| Rename, describe, set cover or sort order |
|
| Add/remove assets (removing keeps them in the library) |
|
| Delete an album; its photos stay. Destructive, asks first |
|
| Name/rename a face cluster, birth date, hide, favourite, face-thumbnail photo; flags an existing person with the same name |
|
| Move every face of |
|
| Upload from the shared mount ( |
|
| Queue |
|
Edits never modify original files: Immich keeps them in its database and
an XMP sidecar. immich_upload only reads from the two hand-off folders
(symlinks out of them are refused) and only accepts the extensions Immich
lists in /server/media-types.
Names (people, albums, tags) resolve exact → case-insensitive → unique substring; ambiguous names error with the candidates. UUIDs pass through.
Times are the camera's local wall clock (Immich localDateTime); bare dates
in filters are interpreted in TZ.
Gallery exports
immich_export writes into EXPORT_DIR/<folder> — a persistent, non-hidden
folder (default ~/Pictures/Immich Exports, created at startup) that you can
connect to another tool once and leave connected. Nothing sweeps it; prune with
immich_export_cleanup(older_than_days=…). Because cleanup deletes inside it,
EXPORT_DIR must be a dedicated folder: ~, ~/Pictures, ~/Desktop etc. are
refused.
Parameter | Default | Notes |
| — | Up to 200; duplicates collapsed |
| — | One plain folder name, e.g. |
|
|
|
|
|
|
| 0 (none) | Downscale only (64–10000); needs |
| 82 | 1–100 |
|
| Fields: |
| false | Videos always export a poster-frame image; this adds Immich's web-playable video ( |
Where pixels come from. Immich renditions first: thumbnail/preview are
Immich's own; fullsize follows Immich's redirect (the original for web formats,
the preview where Immich has no full-size rendition). Local conversion
(Pillow + pillow-heif) only fills the gaps: HEIC originals at fullsize/original
are decoded and re-encoded locally. Camera RAW (ARW, NEF …) can't be decoded
here, so it falls back to Immich's preview, flagged in that asset's note
(turn on Immich's Full-size image generation for true full-res RAW).
Re-encoded files keep the colour profile (iPhone Display P3) and EXIF
orientation, and drop all other metadata, GPS included — safe to publish.
keep files are untouched, so originals keep their EXIF.
Dedupe. If the folder's manifest already has the asset with the same
settings and its file still matches the recorded sha256, it is skipped with
no download (unchanged). Otherwise new bytes identical to the file on disk
are not rewritten. A name clash with another asset, or with a file no
manifest owns (your own edits), gets a -2 suffix rather than being
overwritten. If a re-export renames an asset's file (new pattern or format),
its old file is removed.
manifest.json is a JSON array, one entry per exported asset, sorted by capture time. It accumulates across runs (an asset re-exported replaces its entry):
{
"asset_id": "a1b2c3d4-…", "file": "2009-12-02_0135_a1b2c3d4.jpg",
"width": 1920, "height": 1440, "bytes": 285982, "sha256": "5f1d…",
"taken": "2009-12-02T01:35:46", "place": "Kyoto, Japan", "city": "Kyoto",
"country": "Japan", "camera": "Canon IXY DIGITAL 10", "people": ["…"],
"immich_url": "https://photos.example.com/photos/a1b2c3d4-…",
"type": "image", "duration_s": null, "variant": "preview/jpeg/0/q82"
}Videos add video_file, video_bytes, video_sha256 when exported with
include_video. variant records the export settings (for dedupe).
immich_url is the plain web link; the API key never appears in any URL,
filename or manifest.
The tool returns the absolute folder and manifest paths, count,
total_bytes, by_status and per-asset {asset_id, status, file, note?, error?} with status exported | updated | unchanged | failed.
Failures are per asset; the rest of the batch still exports. Downloads run 5
at a time, with at most 2 large decodes in parallel.
Configuration
Env | Default | Notes |
|
| Server base URL, no |
| — | Scope read-only: |
| — (curation tools off) | Optional. Scope to exactly |
|
| Browser-facing base for the |
|
| Cross-MCP mount for hand-offs to other MCP servers |
|
| Persistent export root ( |
| 2 GiB | Cap per streamed file (originals, videos) |
| 60 | Seconds; cold smart search pays a CLIP model load |
| UTC | For date filters |
| 8336 | HTTP mode |
| — | Required for HTTP mode (fails closed) |
Running
# stdio (interactive clients; no network surface, no bearer)
uvx --env-file .env immich-library-mcp --stdio
# Streamable HTTP at /mcp (stateless, bearer-authenticated)
MCP_BEARER_TOKEN=... IMMICH_API_KEY=... immich-mcp
# container
podman build -t immich-library-mcp .Sync tool bodies run in a worker thread (one slow upstream call never
stalls the event loop) and each call logs tool=X outcome=Y duration_ms=N
to stderr. Argument values are never logged (httpx request logging is
silenced because query strings carry names).
Testing
uv run --extra test pytest -q # tier 1 + 2 (mocked)
IMMICH_TEST=1 uv run --env-file .env \
--extra test pytest tests/test_integration.py -v # tier 3, liveThe live curation tests run only when IMMICH_WRITE_API_KEY is in the env
too. They change one real photo and one named person and restore every
value in a finally (favourite, rating, description, a +60/−60 minute time
shift, location), and create and delete their own album and tag. Merging
people is never run live.
tests/test_formatting.py— pure helpers (date bounds, rows, aggregation, name matching)tests/test_client.py— request shapes, errors, caching, streaming downloadtests/test_server.py— every tool through a mocked Immich, schema/annotation and bearer checkstests/test_library.py— the library-analysis tools (duplicates, large assets, random, stacks, activity, queues, folders, album, person)tests/test_curation.py— curation tools: request bodies, validation sends nothing, previous-value capture, upload path confinement, which key each request carries, registration only with the write keytests/test_export.py— HEIC/JPEG/WebP encoding (orientation, ICC kept, EXIF/GPS stripped), filename patterns, name claiming, manifest, cleanup, contact sheettests/test_gallery.py—immich_exportend to end against real image bytes and Immich's fullsize 302s: manifest schema, dedupe, HEIC/RAW paths, video, per-asset failures, collisions, cross-origin redirect refusaltests/test_integration.py— live: scope probes (403), search → detail → view, counts, places, download, HEIC + video export round trip, contact sheet, library analysis; with the write key, the restore-everything curation round trips
This server cannot be deployed
Maintenance
Related MCP Connectors
Search photos and video moments by visual meaning, people, dates, and folders across local libraries, Apple Photos, and OneDrive. Manage collections, groups, favorites, people, and duplicate review. Synced metadata remains searchable while the desktop is offline; local and Apple Photos media access needs the owning device online with remote access enabled. OneDrive media can be accessed directly from the cloud. OAuth or Bearer API keys. Paid Cloud Access required; hosted visual search uses prepaid credits. Text-in-image search is semantic matching, not guaranteed exact OCR. Setup: https://organizewith.ai/en/guides/connect-ai-assistants
Generate, manage and explore your Switch AI image and video library, scoped to your account.
The media memory layer for AI agents and their humans. Your AI client gets 29 tools to search your collection, add items, update ratings, preview music, and find patterns across everything you've read, watched, and listened to.
Search photos/videos; manage collections, people and duplicates. Requires paid OwAI Cloud Access.
Related MCP Servers
- AlicenseNot gradedqualityAmaintenanceA local, read-only MCP server that lets AI agents inspect and analyze photo libraries by scanning files, aggregating EXIF stats, finding duplicates, scoring blur, and generating cull reports without uploading any data.MIT
- FlicenseNot gradedqualityBmaintenanceEnables users to search and retrieve photos from a self-hosted Immich photo library via natural language, supporting CLIP-based semantic search, metadata filtering, album browsing, and share link creation.-
- AlicenseBqualityCmaintenanceExposes 22 tools for Immich, enabling bidirectional photo handling: pulling images into LLM context, pushing metadata and descriptions back, and managing albums, people, and faces.221 npm1MIT

Lumaflux MCP Serverofficial
AlicenseNot gradedqualityAmaintenanceEnables local agents to browse, import, organize, nondestructively edit, and export photos in a running desktop photo catalog, with revision-checked edits, previews, and batch operations over an authenticated loopback endpoint or bundled stdio adapter.MIT