Immich MCP Server
Servidor MCP de Immich
Expone una biblioteca de fotos de Immich autoalojada a ChatGPT (y a cualquier otro cliente MCP) a través de HTTP Streamable, para que puedas hacer preguntas como "encuentra las fotos de la visita al sitio de Kigali en marzo" y obtener respuestas reales desde tu propio NAS.
ChatGPT ──HTTPS──▶ Cloudflare Tunnel ──▶ immich_mcp:8080 ──▶ immich_server:2283
bearer token MCP → REST x-api-keyLos conectores personalizados de ChatGPT solo aceptan un endpoint HTTPS remoto — no hay opción stdio ni localhost. Por lo tanto, el servidor debe ser accesible desde internet, de ahí el túnel, y debe defenderse, de ahí el token de portador.
Contenido
Related MCP server: immich-photo-manager
Herramientas
Herramienta | Propósito |
| Búsqueda semántica CLIP sobre el contenido de imagen |
| EXIF completo para un activo por UUID |
| Filtrar por fecha, lugar, cámara, persona, favorito |
| Todos los álbumes con recuentos |
| Detalles y contenido de un álbum |
| Rostros reconocidos, con IDs para filtrar |
| Recuentos de fotos/vídeos y uso de disco |
| Versión de Immich y funciones habilitadas |
| Enlace público a activos específicos — desactivado por defecto |
search y fetch están nombrados deliberadamente: el modo Deep Research de ChatGPT ignora
cualquier otra herramienta, así que esas dos asumen la carga si el Modo Desarrollador no está disponible.
Restringir el acceso a álbumes específicos
Por defecto, el servidor expone todo lo que la clave API puede ver. Para compartir solo un
subconjunto, coloca los UUID de los álbumes en ALLOWED_ALBUM_IDS:
python list_albums.py # prints every album with its UUIDALLOWED_ALBUM_IDS=a1b2c3d4-...,e5f6g7h8-...Cada herramienta se limita entonces a los activos dentro de esos álbumes. La búsqueda inteligente
de Immich no tiene filtro de álbumes, por lo que el servidor construye el conjunto de IDs de activos
permitidos por sí mismo y descarta cualquier cosa fuera de él, incluyendo la recuperación directa
por UUID mediante fetch, que devuelve una negativa en lugar del activo. El conjunto se almacena
en caché durante SCOPE_TTL segundos, por lo que las fotos añadidas a un álbum permitido aparecen
sin necesidad de reiniciar.
Vale la pena combinar dos capas: limita la clave API de Immich a un usuario dedicado
y establece ALLOWED_ALBUM_IDS. La clave limita lo que este servidor podría alcanzar;
la lista de álbumes limita lo que realmente expone.
Conectar diferentes clientes
El servidor acepta el token de tres maneras, porque los clientes MCP difieren en lo que pueden enviar:
Cliente | URL | Autenticación |
Conector ChatGPT |
|
|
Conector Claude |
| dejar campos OAuth en blanco |
Claude Code, Cursor, Zed |
|
|
Cualquier solo URL |
| — |
El diálogo del conector personalizado de Claude solo ofrece ID de Cliente OAuth y Secreto, que este servidor no implementa, de ahí la forma de ruta. La seguridad es equivalente dado un token de alta entropía, pero las rutas y cadenas de consulta llegan a los registros del proxy y al historial del shell más fácilmente que las cabeceras, así que prefiere la cabecera cuando el cliente lo permita.
Estructura del proyecto
immich-mcp/
├── Dockerfile
├── docker-compose.yml
├── .env <- you create this, never commit it
├── .env.example
├── .dockerignore
├── preflight.py <- validate config before building
├── run_local.py <- run without Docker, with auto-reload
├── list_albums.py <- discover album UUIDs for scoping
├── smoke_test.py <- full MCP handshake test
├── cloudflared/
│ └── config.example.yml
└── app/
├── immich_mcp.py
└── requirements.txtapp/ importa. Si esos dos archivos terminan junto al Dockerfile en lugar de
dentro de app/, la compilación falla con "/app/immich_mcp.py": not found.
Parte 1 — Hazlo funcionar en tu portátil
Opcional, pero un ciclo mucho más rápido que reconstruir una imagen para cada cambio de configuración. Todo aquí también funciona en el NAS.
1. Obtén una clave API de Immich
Immich → Configuración de la cuenta → Claves API → Nueva clave API. Limítala a solo lectura a menos que planees habilitar enlaces compartidos.
Immich 3.x limita las claves por endpoint. Las herramientas aquí necesitan acceso de lectura a
activos, álbumes, personas y búsqueda. /users/me no es necesario — el pre-vuelo informa de un
ámbito user.read faltante como una advertencia, no como un fallo.
2. Configura
cp .env.example .env
openssl rand -hex 32 # paste into MCP_BEARER_TOKEN
$EDITOR .envDesde el portátil, IMMICH_URL debe ser la dirección LAN del NAS — immich_server
es un nombre de contenedor Docker que solo se resuelve en el propio NAS:
IMMICH_URL=http://192.168.0.43:2283Ten en cuenta que no hay un segundo http://. Un esquema duplicado es un error fácil de pegar y
produce un fallo de nombre de host confuso.
3. Pre-vuelo
pip install httpx python-dotenv
python preflight.pyComprueba la estructura del proyecto, valida .env, abre una conexión TCP a Immich,
confirma que la clave API puede leer activos e informa si la búsqueda inteligente y el
reconocimiento facial están realmente habilitados. Nombra la solución exacta para cada fallo.
Vale la pena leer el recuento de activos que informa. Si dice 1 activo visible y tu biblioteca tiene miles, la clave pertenece a un usuario que posee casi nada — todo el flujo posterior funcionará perfectamente y no devolverá nada.
4. Ejecuta sin Docker
pip install -r app/requirements.txt
python run_local.pySirve en http://127.0.0.1:8099 con recarga automática. En un segundo terminal:
python smoke_test.py http://127.0.0.1:8099 <your-bearer-token>Esto ejecuta el protocolo de enlace exacto que hace ChatGPT: initialize, tools/list, luego una llamada a herramienta en vivo — y confirma que las solicitudes no autenticadas reciben un 401.
5. Construye la imagen (opcional en el portátil)
Si quieres verificar la compilación Docker antes de enviarla, elimina el
bloque networks: de docker-compose.yml primero — immich_default solo existe
en el NAS.
docker compose up -d --build
curl.exe http://127.0.0.1:8099/healthzParte 2 — Despliega en el NAS
Cuatro cosas cambian: cómo el contenedor llega a Immich, qué red Docker une, la propiedad de los archivos y cómo se construye la imagen.
0. Rota ambos secretos primero
Si la clave API de Immich o el token de portador se han pegado en un chat, un correo electrónico o un documento compartido, trátalo como quemado. Este endpoint está a punto de enfrentarse a internet.
Immich → Configuración de la cuenta → Claves API → elimina la antigua, crea una nueva
Nuevo token de portador:
openssl rand -hex 32
No copies tu .env del portátil. Apunta IMMICH_URL a una dirección LAN,
lo que funciona pero enruta los metadatos de las fotos a la LAN y de vuelta sin
motivo. Comienza desde .env.example en el NAS.
1. Copia el proyecto
Colócalo junto a tus otras pilas, por ejemplo, /volume1/docker/immich-mcp/. Ya sea
arrastrándolo a través de File Station o:
scp -r . wanjau@<nas-ip>:/volume1/docker/immich-mcp/Verifica que app/ sobrevivió — arrastrar y soltar en File Station a veces aplana
directorios:
ls -la /volume1/docker/immich-mcp/app/2. Encuentra el nombre real del contenedor y la red
Conéctate por SSH (Panel de control → Terminal y SNMP → Habilitar SSH), luego:
sudo docker ps --format '{{.Names}}\t{{.Image}}' | grep -i immich
sudo docker network ls | grep -i immichContainer Manager a menudo prefija los nombres con el proyecto, por lo que puedes obtener
immich-immich_server-1 en lugar de immich_server. Comprueba que el nombre se resuelve
desde dentro de Docker, que es lo que realmente importa:
sudo docker run --rm --network <network-name> curlimages/curl:latest \
-s -o /dev/null -w '%{http_code}\n' http://<container-name>:2283/api/server/versionUn 200 aquí significa que el resto de esto es aburrido. Omitirlo significa un 502 del túnel
más tarde que parece un problema de Cloudflare pero no lo es.
3. Escribe .env en el NAS
cd /volume1/docker/immich-mcp
cp .env.example .env
vi .env
chmod 600 .envAhora IMMICH_URL usa el nombre del contenedor del paso 2, manteniendo el tráfico dentro
de Docker:
IMMICH_URL=http://immich_server:2283
IMMICH_API_KEY=<the new key>
MCP_BEARER_TOKEN=<the new token>
PUBLIC_URL=https://photos.yourdomain.com
ALLOWED_ALBUM_IDS=4. Corrige el nombre de la red y el usuario
En docker-compose.yml, establece la red a la que informó el paso 2:
networks:
immich-net:
external: true
name: immich_default # <- from step 2El Dockerfile crea un usuario con UID 1027, la convención habitual de Synology.
Comprueba la tuya con id; si difiere, edita el Dockerfile o anula en
compose con user: "1026:100". Solo importa una vez que montes volúmenes —
una discrepancia es inofensiva por ahora.
5. Pre-vuelo y selecciona álbumes, desde dentro de un contenedor
El Python de DSM es complicado para instalar paquetes, y ejecutar el pre-vuelo en el host no probaría la resolución de nombres de contenedor a contenedor de todos modos:
cd /volume1/docker/immich-mcp
sudo docker run --rm -it \
--network <network-name> \
-v "$PWD":/work -w /work \
python:3.12-slim sh -c "pip install -q httpx python-dotenv && python preflight.py"El mismo comando de una línea ejecuta list_albums.py. Copia los UUID que quieras exponer en
ALLOWED_ALBUM_IDS.
6. Construye e inicia
sudo docker compose up -d --build
sudo docker compose logs -f immich-mcpBusca tres líneas:
Immich MCP server configured for http://immich_server:2283
Scope: restricted to <album-id>
Album scope refreshed: 1 album(s), N asset(s)Si N es 0, el ID del álbum es incorrecto o la clave no puede leer ese álbum.
La interfaz gráfica de Container Manager también funciona: Proyecto → Crear → apuntar a la
carpeta — pero a veces tiene problemas con redes external: true. Usa SSH si da error.
7. Verifica en el NAS antes de exponer nada
curl -s http://127.0.0.1:8099/healthz | head -c 300Espera estado ok, la versión de Immich y tu resumen de ámbito. Luego el protocolo de enlace completo:
sudo docker run --rm -it --network host \
-v "$PWD":/work -w /work \
python:3.12-slim sh -c "pip install -q httpx && \
python smoke_test.py http://127.0.0.1:8099 <bearer-token>"Un problema encontrado aquí es un problema de configuración. El mismo problema encontrado después de la siguiente sección parece un problema de túnel.
Parte 3 — Exponlo y conecta ChatGPT
1. Añade el nombre de host del túnel Cloudflare
Panel de Zero Trust → Redes → Túneles → tu túnel → Nombre de host público → Añadir:
Subdominio:
immich-mcpDominio:
tudominio.comServicio:
HTTP→immich_mcp:8080
Si cloudflared se ejecuta como contenedor, debe compartir una red con immich_mcp para que
ese nombre se resuelva; si se ejecuta en el host, usa http://127.0.0.1:8099. Consulta
cloudflared/config.example.yml para el equivalente en archivo de configuración.
No adjuntes una política de Access. ChatGPT no puede completar un inicio de sesión interactivo de Access. El token de portador es la única puerta — por eso rotarlo era importante.
Verifica desde fuera de la LAN si puedes; un punto de acceso del teléfono es una buena prueba:
python smoke_test.py https://immich-mcp.yourdomain.com <bearer-token>2. Crea el conector
Configuración → Conectores → Configuración avanzada → habilita el Modo Desarrollador (requiere un plan de pago), luego Crear:
Nombre: Fotos de Immich
Descripción: esto importa — el modelo lo lee para decidir si invocar el conector. Algo como "Biblioteca personal de fotos y vídeos. Úsalo para encontrar, describir o listar fotos, álbumes y personas reconocidas."
URL:
https://immich-mcp.tudominio.com/mcpAutenticación: Clave API / cabecera personalizada →
Authorization: Bearer <token>
Luego habilita el conector en el compositor del chat y prueba con un nombre de herramienta explícito:
Usa immich search para encontrar fotos de los bastidores de secado
Operación
Nombra la herramienta en tu mensaje. ChatGPT no adivinará de forma fiable cuándo recurrir a un conector personalizado. "Usa immich search para encontrar fotos de los bastidores de secado" funciona donde "encuentra mis fotos de los bastidores de secado" a menudo no funciona.
ChatGPT no puede ver tus fotos. Los resultados de las herramientas son texto —
descripciones y metadatos, no píxeles. create_share_link salva esa brecha, pero un enlace
compartido es público para cualquiera que tenga la URL, por lo que está desactivado por defecto.
Actualizar código. Edita app/immich_mcp.py, luego sudo docker compose up -d --build.
Rotar el token de portador. Edita .env, docker compose up -d --force-recreate,
luego actualiza el conector en ChatGPT. Hay una ventana donde ChatGPT está roto —
hazlo cuando no estés en medio de una conversación.
Añadir fotos a un álbum con ámbito. No hay que hacer nada. La caché de ámbito se reconstruye
cada SCOPE_TTL segundos (por defecto 300).
Inicio automático después de un reinicio. restart: unless-stopped lo maneja, pero
los proyectos de Container Manager a veces necesitan que se marque el reinicio automático en la
interfaz gráfica. Reinicia una vez deliberadamente, en un momento que te convenga, en lugar de
descubrirlo mientras estás fuera.
Fija tu versión de Immich. La API cambia entre versiones — /server/statistics
era /server-info/statistics no hace mucho. Tu instancia publica la especificación exacta
en https://photos.tudominio.com/api/docs; compruébalo antes de depurar un 404.
Síntoma | Causa |
Build: | Los archivos están planos; pertenecen a |
| Nombre de red incorrecto — rehacer paso 2 de la parte 2 |
| No se puede alcanzar Immich — |
El contenedor sale inmediatamente | Falta variable de entorno requerida — consulta |
| ID del álbum incorrecto, o la clave no puede leer ese álbum |
Preflight: clave API rechazada 403 en | Falta el ámbito |
Preflight: solo 1 activo visible | La clave pertenece a un usuario que no posee casi nada |
401 en cada solicitud | Discrepancia del token Bearer entre |
Funciona en el NAS, 502 a través del túnel | cloudflared no puede resolver |
El túnel devuelve una página de inicio de sesión | Hay una política de acceso adjunta; elimínala |
ChatGPT: "acción de búsqueda no encontrada" | Añadido en modo Deep Research; habilita el modo Desarrollador |
Conector añadido pero nunca se activa | Descripción demasiado vaga, o la herramienta no está activada en el chat |
| Aprendizaje automático de Immich deshabilitado — verifica |
Immich rechaza la clave (401 en los registros) | Clave revocada, o pertenece a un usuario diferente de Immich |
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
Search photos/videos; manage collections, people and duplicates. Requires paid OwAI Cloud Access.
AI-native digital asset management: semantic search, generative image edits, and CDN delivery.
Search, organize, and publish AI-generated images and video with provenance and lineage.
Related MCP Servers
- FlicenseNot gradedqualityCmaintenanceEnables AI assistants to search, browse, and retrieve metadata and images from your Google Photos library. It supports content-based filtering, album listing, and location extraction via STDIO and HTTP transports.47-
- AlicenseAqualityAmaintenanceManage your self-hosted Immich photo library through conversation — natural language search via CLIP, geographic album curation, duplicate detection with perceptual hashing,94277 PyPI54MIT
- AlicenseAqualityAmaintenanceEnables AI assistants to query and export from the macOS Apple Photos library using natural language, backed by osxphotos.21780 npm30MIT

CoreViz MCPofficial
AlicenseNot gradedqualityDmaintenanceExposes a visual library with semantic search, tagging, editing, and management of photos as tools for AI agents like Claude Code.13 npm49MIT