immich-mcp
The immich-mcp server provides AI-accessible tools for managing a self-hosted Immich photo library, including browsing, searching, organizing, and safe deletion of assets, albums, people, tags, shared links, activities, and duplicates, with safety features like dry-run and protected asset handling.
Server & User: Verify connectivity and server capabilities (immich_ping, immich_capabilities), view your user profile.
Assets: List, get, upload, update metadata (favorite, archived, description, rating), bulk update, delete (with dry-run/force), view thumbnails, originals, and web UI links, and get asset statistics.
Search: Metadata searches (filters by date, type, location, camera, person, filename, OCR text), semantic smart searches (natural language CLIP-based), and exploring popular places and people.
Albums: Create, list, get, update, delete albums; add/remove assets; get album statistics.
People: List, get, update person details (name, visibility); merge face clusters; get statistics and assets featuring a person.
Tags: Create, list, get, update, delete tags; support nested tags with / separator; add/remove assets from tags; bulk assign tags.
Shared Links: Create, list, get, update, revoke shareable links with expiry, password, and permissions (download/upload).
Activities: List, create (comments/likes), and delete activities on albums/assets; get activity statistics.
Duplicates: List duplicate groups with advanced analysis (format priority scoring, resolution comparison, protection for favorited/album-linked assets). Delete or dismiss duplicates with dry-run support and safety guardrails.
Safety & Workflows: Destructive operations are annotated with destructiveHint and support dry_run by default. AI-guided workflows (prompts) help with duplicate review, album organization, and discovering untagged photos.
Provides AI-accessible tools for browsing, searching, organizing, and managing a self-hosted Immich photo library, including duplicate detection and safe deletion workflows.
Click on "Install 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-mcpfind photos of sunsets from last summer"
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-mcp
MCP server for Immich photo management. Provides AI-accessible tools for browsing, searching, organizing, and managing your self-hosted photo library — including duplicate detection and safe deletion workflows.
Features
40+ MCP tools covering assets, albums, search, people, tags, shared links, activities, and duplicates
3 MCP prompts for guided workflows: duplicate review, album organization, and untagged photo discovery
Tool annotations (
title,readOnlyHint,destructiveHint,idempotentHint) for safe AI-driven automationDry-run support on all destructive operations
Duplicate analysis with format priority scoring and protection for favorited/album-linked assets
Automatic retries via
httpx.AsyncHTTPTransport(configurable viaIMMICH_MAX_RETRIES)
Related MCP server: jgkme/kilo-image-gen-mcp
Requirements
Python 3.11+
Immich server with API access
uv(recommended) orpip
Installation
git clone https://github.com/whitehara/immich-mcp
cd immich-mcp
uv pip install -e .Configuration
Set environment variables before running:
Variable | Required | Default | Description |
| Yes | — | Immich server URL (e.g. |
| Yes | — | API key from Immich → Account Settings → API Keys |
| No | same as | Public URL used for |
| No |
| HTTP timeout in seconds. The |
| No |
| Retry attempts on transient errors |
Immich API Key Permissions
Immich 1.138.0+ supports granular API key permissions. Grant the following scopes when creating your key (Immich → Account Settings → API Keys → Create).
For full functionality (all tools enabled):
Scope | Required by |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
For read-only use (no create/update/delete tools), grant only:
server.about, user.read, asset.read, asset.statistics, album.read, person.read, person.statistics, tag.read, sharedLink.read, activity.read, activity.statistics, duplicate.read
On Immich versions prior to 1.138.0, select All permissions.
Usage
stdio (Claude Desktop / Claude Code)
export IMMICH_BASE_URL=https://photos.example.com
export IMMICH_API_KEY=your-api-key
immich-mcp --transport stdioClaude Desktop config (claude_desktop_config.json):
{
"mcpServers": {
"immich": {
"command": "immich-mcp",
"args": ["--transport", "stdio"],
"env": {
"IMMICH_BASE_URL": "https://photos.example.com",
"IMMICH_API_KEY": "your-api-key"
}
}
}
}HTTP (Docker / remote)
docker run -e IMMICH_BASE_URL=https://photos.example.com \
-e IMMICH_API_KEY=your-api-key \
-p 8000:8000 \
ghcr.io/whitehara/immich-mcp:latestOr build locally with docker compose up.
Default transport in Docker is streamable-http on port 8000.
Tool Reference
Annotation columns: R = readOnlyHint, D = destructiveHint, I = idempotentHint
Each tool also carries a human-readable title annotation used by MCP clients for display.
Health
Tool | Description | R | D | I |
| Verify connectivity, returns server version | ✓ | ✓ | |
| List supported server features | ✓ | ✓ |
User
Tool | Description | R | D | I |
| Get the authenticated user's profile (name, email, quota, role) | ✓ | ✓ |
Assets
Tool | Description | R | D | I |
| List assets with filters (favorite, visibility, trashed, type), via metadata search | ✓ | ✓ | |
| Get full metadata for a single asset | ✓ | ✓ | |
| Get thumbnail, original, and web UI URLs for an asset | ✓ | ✓ | |
| Upload an asset from a local file path or URL | |||
| Update favorite, archived, description, rating | ✓ | ||
| Bulk update multiple assets (dry_run supported) | ✓ | ||
| Delete assets, optionally permanently (dry_run supported) | ✓ | ✓ | |
| Get counts by asset type | ✓ | ✓ |
v3.1.0 breaking change:
immich_assets_listpreviously called the non-existentGET /api/assetsendpoint and always failed. It now usesPOST /api/search/metadataand returns{count, next_page, items}instead of a bare list.
Search
Tool | Description | R | D | I |
| Filter by date, type, location, camera, person, album, tag, OCR text, filename | ✓ | ||
| Semantic/CLIP search with natural language queries | ✓ | ||
| Discover popular places, people, and things | ✓ | ✓ |
immich_search_metadata and immich_search_smart default visibility to "timeline".
Immich v3 defaults to returning every visibility except "locked" when visibility is
omitted, which would silently mix archived and hidden assets into results; the explicit
default here preserves the previous timeline-only behavior. Pass visibility explicitly
to search a different state.
Albums
Tool | Description | R | D | I |
| List albums, filterable by shared status, ownership, or name | ✓ | ✓ | |
| Get album metadata (see note below) | ✓ | ✓ | |
| Create a new album | |||
| Update album name, description, or cover | ✓ | ||
| Delete an album (assets are not deleted) | ✓ | ✓ | |
| Add assets to an album | ✓ | ||
| Remove assets from an album | ✓ | ||
| Get counts of owned, shared, and not-shared albums | ✓ | ✓ |
v3.1.0 breaking change: immich_albums_list's shared parameter was renamed to
is_shared, and is_owned/name filters were added (Immich v3 renamed the underlying
query param from shared to isShared). immich_albums_get no longer returns the
album's assets or accepts a without_assets parameter — Immich v3's AlbumResponseDto
dropped the assets field entirely. Use immich_search_metadata with album_ids to
list an album's assets instead.
People
Tool | Description | R | D | I |
| List recognized people | ✓ | ✓ | |
| Get person details | ✓ | ✓ | |
| Update name or visibility | ✓ | ||
| Merge two face clusters | ✓ | ||
| Get asset count for a person | ✓ | ✓ | |
| List assets featuring a person (shortcut for | ✓ | ✓ |
Tags
Tool | Description | R | D | I |
| List all tags | ✓ | ✓ | |
| Get a tag by ID | ✓ | ✓ | |
| Create a tag (use | |||
| Update a tag's color | ✓ | ||
| Add assets to a tag | ✓ | ||
| Remove assets from a tag (dry_run supported) | ✓ | ✓ | |
| Assign multiple tags to multiple assets in one call | ✓ | ||
| Delete a tag | ✓ | ✓ |
v3.1.0 breaking change: immich_tags_update no longer accepts a name parameter —
Immich v3's TagUpdateDto only supports updating color. Tag renaming is not supported
by the Immich API.
Shared Links
Tool | Description | R | D | I |
| List all shared links | ✓ | ✓ | |
| Get shared link details | ✓ | ✓ | |
| Create a shareable URL | |||
| Update expiry, password, permissions | ✓ | ||
| Revoke a shared link | ✓ | ✓ |
immich_shared_links_update accepts clear_expires_at: true to remove an existing
expiry and make the link permanent (mutually exclusive with expires_at). expires_at
on both create and update accepts a bare date (2026-12-31) and normalizes it to a
UTC datetime — Immich v3 rejects timezone-less datetime strings outright.
Activities
Tool | Description | R | D | I |
| List comments and likes | ✓ | ✓ | |
| Add a comment or like | |||
| Delete an activity | ✓ | ✓ | |
| Get comment count | ✓ | ✓ |
Duplicates
Tool | Description | R | D | I |
| List duplicate groups with analysis (format score, resolution, protection status). Paginated ( | ✓ | ✓ | |
| Resolve a duplicate group atomically: mark keep/trash and clear the grouping in one call (dry_run supported, recommended over | ✓ | ✓ | |
| Delete assets from duplicate groups (dry_run supported) | ✓ | ✓ | |
| Dismiss duplicate groups without deleting files (dry_run supported) | ✓ | ✓ |
Whether immich_duplicates_resolve's trash_asset_ids moves matched assets to
trash (restorable) or deletes them permanently depends on the target server's
trash feature setting (GET /api/server/features) — Immich v3.1.0's
resolveGroup() skips the trash entirely and deletes files on disk when that
feature is disabled server-wide. The tool checks this automatically on every
non-dry-run call: if the server's trash feature is disabled, the call is
blocked (no HTTP mutation happens) unless allow_permanent_delete=true is
passed explicitly. dry_run=true always reports the detected trash_enabled
value (true/false/null if the check itself failed) without blocking,
so a null result never blocks a subsequent real call — it's treated as
"unknown," not "disabled." If keep/trash from a duplicate group is going to
happen on a server where you haven't confirmed trash is enabled, you can
instead use immich_duplicates_delete(force=false) followed by
immich_duplicates_dismiss — that path always goes to trash regardless of
the server's trash setting. If keep_asset_ids is omitted, every other asset
in the group is kept automatically; Immich requires every asset in a group to
be classified as either kept or trashed.
Pagination
immich_duplicates_list returns paginated results to avoid oversized responses on large libraries:
Parameter | Default | Description |
|
| Page number (1-based) |
|
| Groups per page (max 500) |
The response includes total_groups, total_pages, page, and page_size fields. Iterate page=1..total_pages to process all groups.
Duplicate Analysis Fields
immich_duplicates_list with analyze=true (default) returns per-group analysis:
Field | Description |
| Recommended asset to retain (highest quality) |
| Assets not favorited and not in any album |
| Assets that are favorited or in albums — require explicit user approval |
|
|
| Why review is needed: |
|
|
| Immich's own keep suggestion for the group ( |
Note: while album_membership="unknown", review_reasons contains only album_membership_unknown — a per-asset protected_assets reason (e.g. from favorites) is not added separately, since every delete candidate is already protected wholesale until membership is resolved.
Album membership can't be read off an individual asset — Immich's AssetResponseDto has no albums field — so it's derived by cross-referencing /api/albums with /api/search/metadata in a background task. While that index is still building (album_index_ready=false in the top-level response), every delete candidate in a group is treated as protected (album_membership="unknown", safe_to_delete_ids=[]) rather than risking an unprotected asset that actually belongs to an album. This is conservative by design — protection defaults to "on" until membership is confirmed.
Quality Priority for keep_id (highest to lowest)
Live Photo > Format score > Resolution > File size
Favorites and album membership are tiebreakers only — they do not override a quality difference. A favorited JPEG will not be recommended over an unfavorited RAW; instead the JPEG is listed in protected_ids for user review.
Known limitation: locked assets (visibility="locked") are excluded from the default /api/search/metadata results used to build the album index, so album membership for locked-and-in-an-album assets cannot be detected.
Format Score (highest to lowest)
RAW/DNG > HEIC/HEIF > PNG/TIFF > JPEG > WebP > GIF
Prompt Reference
Invoke prompts from your MCP client to start guided workflows.
immich/review_duplicates
Step-by-step workflow for reviewing and safely resolving duplicate photos:
Fetch duplicate groups with analysis
Present summary: safe-to-delete count vs. protected assets needing review
For each group, choose an action:
Delete: keep the best asset, move the rest to trash (or permanently delete)
Dismiss: assets are intentionally kept as separate copies — remove the duplicate grouping without deleting files
Dry-run confirmation before execution
immich/organize_album
Guided album creation workflow:
Organize by date, event, person, or location
Uses both metadata search and semantic (CLIP) search
Checks for existing albums to avoid duplicates
Confirms asset count before creating
immich/find_untagged
Discover unorganized assets in the library:
Identifies assets with no album, no description, or no recognized people
Suggests descriptions from EXIF data
Hands off to
immich/organize_albumfor album creation
Error Reporting
When Immich returns a non-2xx response, the error message raised back to the MCP client includes the response body (truncated to 2000 characters) — e.g. Immich's Zod validation details on a 400. Request headers (including the API key) are never included.
Safety Model
All destructive tools (delete, merge, remove) carry destructiveHint=true in their MCP annotations, signalling to clients that human confirmation is required before execution. Additional safeguards:
dry_run=trueis the default on all delete operations — no changes occur without explicit opt-inDuplicate analysis places favorited and album-linked assets in
protected_ids; they are never auto-deletedPrompts explicitly instruct the AI to present a summary and obtain user approval before any destructive action
Development
# Install with dev dependencies
uv pip install -e ".[dev]"
# Run tests
pytest
# Run a single test file
pytest tests/tools/test_assets.py -v
# Lint
ruff check .
# Type check (optional)
pyright src/tests/contract/ validates every tool's mocked HTTP calls against a vendored copy of the
Immich OpenAPI spec (method, path, query params, body keys) — run automatically as part of
pytest. tests/live/ smoke-tests read-only tools against a real Immich server; it's
excluded by default (-m "not live") and needs its own env vars so it's never confused
with the mocked test suite's placeholder settings:
IMMICH_LIVE_BASE_URL=https://your-immich-server \
IMMICH_LIVE_API_KEY=your-api-key \
pytest -m liveMaintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- Alicense-qualityDmaintenanceThis MCP server aids users in searching and analyzing their photo library by location, labels, and people, offering functionalities like photo analysis and fuzzy matching for enhanced photo management.24MIT
- Alicense-qualityAmaintenanceMCP server for generating, editing, and processing images via multiple providers including Kilo, OpenRouter, OpenAI, and Gemini, with local tools for background removal, resizing, and cropping.372MIT
- Flicense-qualityCmaintenanceAn MCP server that integrates AI assistants with the Flickr API, enabling management of photos, albums, groups, and contacts via natural language commands.1
- Alicense-qualityDmaintenanceThis MCP server enables AI tools to interact with your Apple Photos library via the osxphotos CLI, providing tools for querying and managing photos.MIT
Related MCP Connectors
MCP server for NanoBanana AI image generation and editing
MCP server for Flux AI image generation
Cloud-hosted MCP server for durable AI memory
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/whitehara/immich-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server