Immich MCP Server
Immich MCP Server
셀프 호스팅 Immich 사진 라이브러리를 ChatGPT(및 기타 MCP 클라이언트)에 Streamable HTTP로 노출하여, "3월 키갈리 현장 방문 사진 찾아줘" 같은 질문에 실제 NAS에서 답변을 얻을 수 있게 합니다.
ChatGPT ──HTTPS──▶ Cloudflare Tunnel ──▶ immich_mcp:8080 ──▶ immich_server:2283
bearer token MCP → REST x-api-keyChatGPT 사용자 지정 커넥터는 원격 HTTPS 엔드포인트만 허용합니다. stdio나 localhost 옵션은 없습니다. 따라서 서버는 인터넷에서 접근 가능해야 하므로 터널이 필요하며, 자기 방어를 위해 bearer 토큰이 필요합니다.
목차
Related MCP server: immich-photo-manager
도구
도구 | 용도 |
| 이미지 콘텐츠에 대한 CLIP 의미 검색 |
| UUID로 하나의 에셋에 대한 전체 EXIF 정보 |
| 날짜, 장소, 카메라, 인물, 즐겨찾기로 필터링 |
| 모든 앨범과 개수 |
| 하나의 앨범 상세 정보와 내용 |
| 인식된 얼굴과 필터링용 ID |
| 사진/비디오 개수 및 디스크 사용량 |
| Immich 버전 및 활성화된 기능 |
| 특정 에셋에 대한 공개 링크 — 기본적으로 꺼짐 |
search와 fetch는 의도적으로 명명되었습니다. ChatGPT의 딥 리서치 모드는 다른 모든 도구를 무시하므로, 개발자 모드를 사용할 수 없을 때 이 두 도구가 부담을 짊어집니다.
특정 앨범으로 접근 제한
기본적으로 서버는 API 키가 볼 수 있는 모든 것을 노출합니다. 하위 집합만 공유하려면 ALLOWED_ALBUM_IDS에 앨범 UUID를 넣으세요:
python list_albums.py # prints every album with its UUIDALLOWED_ALBUM_IDS=a1b2c3d4-...,e5f6g7h8-...그러면 모든 도구가 해당 앨범 내의 에셋으로 제한됩니다. Immich의 스마트 검색에는 앨범 필터가 없으므로, 서버가 직접 허용된 에셋 ID 집합을 구축하고 그 외의 것은 삭제합니다. 여기에는 UUID로 직접 fetch하는 것도 포함되며, 에셋 대신 거부 응답을 반환합니다. 이 집합은 SCOPE_TTL초 동안 캐시되므로 허용된 앨범에 추가된 사진은 재시작 없이 나타납니다.
두 가지 계층을 결합하는 것이 좋습니다: Immich API 키를 전용 사용자로 범위를 지정하고, ALLOWED_ALBUM_IDS를 설정하는 것입니다. 키는 이 서버가 도달할 수 있는 것을 제한하고, 앨범 목록은 실제로 노출하는 것을 제한합니다.
다양한 클라이언트 연결
서버는 세 가지 방법으로 토큰을 받습니다. MCP 클라이언트마다 보낼 수 있는 것이 다르기 때문입니다.
클라이언트 | URL | 인증 |
ChatGPT 커넥터 |
|
|
Claude 커넥터 |
| OAuth 필드 비워두기 |
Claude Code, Cursor, Zed |
|
|
URL만 가능한 모든 것 |
| — |
Claude의 사용자 지정 커넥터 대화상자는 OAuth 클라이언트 ID와 시크릿만 제공하며, 이 서버는 이를 구현하지 않습니다. 그래서 경로 형식을 사용합니다. 높은 엔트로피 토큰을 사용하면 보안은 동등하지만, 경로와 쿼리 문자열은 헤더보다 프록시 로그와 셸 히스토리에 더 쉽게 기록되므로, 클라이언트가 허용하는 경우 헤더를 선호하세요.
프로젝트 구조
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/이 중요합니다. 이 두 파일이 app/ 내부 대신 Dockerfile 옆에 있으면 빌드가 실패하며 "/app/immich_mcp.py": not found 오류가 발생합니다.
1부 — 노트북에서 작동시키기
선택 사항이지만, 모든 설정 변경마다 이미지를 다시 빌드하는 것보다 훨씬 빠른 루프입니다. 여기에 있는 모든 내용은 NAS에서도 동일하게 작동합니다.
1. Immich API 키 받기
Immich → 계정 설정 → API 키 → 새 API 키. 공유 링크를 활성화할 계획이 없다면 읽기 전용으로 범위를 지정하세요.
Immich 3.x는 엔드포인트별로 키를 범위 지정합니다. 여기 있는 도구는 에셋, 앨범, 인물, 검색에 대한 읽기 접근이 필요합니다. /users/me는 필요하지 않습니다. 사전 점검 시 user.read 범위가 없으면 경고만 표시하고 실패하지 않습니다.
2. 설정
cp .env.example .env
openssl rand -hex 32 # paste into MCP_BEARER_TOKEN
$EDITOR .env노트북에서 IMMICH_URL은 NAS LAN 주소여야 합니다. immich_server는 NAS 자체에서만 확인되는 Docker 컨테이너 이름입니다:
IMMICH_URL=http://192.168.0.43:2283http://가 두 번 나오지 않도록 주의하세요. 체계가 중복되면 붙여넣기 오류가 발생하기 쉬우며 혼란스러운 호스트 이름 오류가 발생합니다.
3. 사전 점검
pip install httpx python-dotenv
python preflight.py프로젝트 레이아웃을 확인하고, .env의 유효성을 검사하며, Immich에 TCP 연결을 열고, API 키가 에셋을 읽을 수 있는지 확인하며, 스마트 검색과 얼굴 인식이 실제로 활성화되어 있는지 보고합니다. 각 실패에 대해 정확한 수정 방법을 알려줍니다.
보고된 에셋 개수를 읽어볼 가치가 있습니다. 1개의 에셋이 보임이라고 표시되는데 라이브러리에 수천 개가 있다면, 키가 거의 아무것도 소유하지 않은 사용자에게 속한 것입니다. 이후 모든 다운스트림은 완벽하게 작동하지만 아무것도 반환하지 않습니다.
4. Docker 없이 실행
pip install -r app/requirements.txt
python run_local.pyhttp://127.0.0.1:8099에서 자동 리로드로 제공합니다. 두 번째 터미널에서:
python smoke_test.py http://127.0.0.1:8099 <your-bearer-token>이는 ChatGPT가 수행하는 정확한 핸드셰이크(초기화, tools/list, 그 다음 실제 도구 호출)를 실행하고, 인증되지 않은 요청이 401을 받는지 확인합니다.
5. 이미지 빌드 (노트북에서는 선택 사항)
배포 전에 Docker 빌드를 확인하려면 먼저 docker-compose.yml에서 networks: 블록을 삭제하세요. immich_default는 NAS에만 존재합니다.
docker compose up -d --build
curl.exe http://127.0.0.1:8099/healthz2부 — NAS에 배포하기
네 가지가 변경됩니다: 컨테이너가 Immich에 도달하는 방식, 연결되는 Docker 네트워크, 파일 소유권, 이미지 빌드 방식.
0. 먼저 두 비밀을 교체하세요
Immich API 키나 bearer 토큰이 채팅, 이메일, 공유 문서에 붙여넣어진 경우 손상된 것으로 간주하세요. 이 엔드포인트는 곧 인터넷에 노출될 예정입니다.
Immich → 계정 설정 → API 키 → 이전 키 삭제, 새 키 생성
새 bearer 토큰:
openssl rand -hex 32
노트북의 .env를 복사하지 마세요. IMMICH_URL은 LAN 주소를 가리키는데, 작동은 하지만 사진 메타데이터가 LAN을 통해 나갔다가 돌아오는 불필요한 경로를 만듭니다. NAS에서는 .env.example부터 시작하세요.
1. 프로젝트를 NAS로 복사
다른 스택과 함께 배치하세요. 예: /volume1/docker/immich-mcp/. File Station으로 드래그하거나 다음 명령어 사용:
scp -r . wanjau@<nas-ip>:/volume1/docker/immich-mcp/app/이 그대로 있는지 확인하세요. File Station 드래그 앤 드롭 시 디렉터리가 평탄화되는 경우가 있습니다:
ls -la /volume1/docker/immich-mcp/app/2. 실제 컨테이너 이름과 네트워크 찾기
SSH로 접속(제어판 → 터미널 및 SNMP → SSH 활성화) 후:
sudo docker ps --format '{{.Names}}\t{{.Image}}' | grep -i immich
sudo docker network ls | grep -i immichContainer Manager는 종종 프로젝트 이름을 접두사로 붙이므로 immich_server 대신 immich-immich_server-1이 나올 수 있습니다. Docker 내부에서 이름이 확인되는지 확인하세요. 이것이 실제로 중요합니다:
sudo docker run --rm --network <network-name> curlimages/curl:latest \
-s -o /dev/null -w '%{http_code}\n' http://<container-name>:2283/api/server/version여기서 200이 나오면 나머지는 지루합니다. 건너뛰면 나중에 Cloudflare 문제처럼 보이지만 실제로는 아닌 터널 502 오류가 발생합니다.
3. NAS에서 .env 작성
cd /volume1/docker/immich-mcp
cp .env.example .env
vi .env
chmod 600 .env이제 IMMICH_URL은 2단계의 컨테이너 이름을 사용하여 트래픽을 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. 네트워크 이름과 사용자 수정
docker-compose.yml에서 네트워크를 2단계에서 확인된 것으로 설정하세요:
networks:
immich-net:
external: true
name: immich_default # <- from step 2Dockerfile은 일반적인 Synology 관례인 UID 1027로 사용자를 생성합니다. id 명령어로 자신의 UID를 확인하세요; 다르다면 Dockerfile을 수정하거나 compose에서 user: "1026:100"으로 재정의하세요. 볼륨을 마운트할 때만 중요합니다 — 현재는 불일치해도 문제없습니다.
5. 컨테이너 내부에서 사전 점검 및 앨범 선택
DSM의 Python은 패키지 설치가 어렵고, 호스트에서 사전 점검을 실행해도 컨테이너 간 이름 확인을 테스트하지 못합니다:
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"같은 한 줄 명령어로 list_albums.py도 실행됩니다. 노출하려는 UUID를 복사하여 ALLOWED_ALBUM_IDS에 넣으세요.
6. 빌드 및 시작
sudo docker compose up -d --build
sudo docker compose logs -f immich-mcp세 줄을 확인하세요:
Immich MCP server configured for http://immich_server:2283
Scope: restricted to <album-id>
Album scope refreshed: 1 album(s), N asset(s)N이 0이면 앨범 ID가 잘못되었거나 키가 해당 앨범을 읽을 수 없는 것입니다.
Container Manager GUI도 작동합니다(프로젝트 → 생성 → 폴더 지정) 하지만 external: true 네트워크에서 때때로 문제가 발생합니다. 오류가 발생하면 SSH를 사용하세요.
7. 노출 전에 NAS에서 확인
curl -s http://127.0.0.1:8099/healthz | head -c 300상태 ok, Immich 버전, 그리고 범위 요약이 표시되어야 합니다. 그 다음 전체 핸드셰이크:
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>"여기서 발견된 문제는 설정 문제입니다. 다음 섹션 후에 동일한 문제가 발견되면 터널 문제처럼 보입니다.
3부 — 노출하고 ChatGPT 연결하기
1. Cloudflare Tunnel 호스트 이름 추가
Zero Trust 대시보드 → 네트워크 → 터널 → 사용자 터널 → 공개 호스트 이름 → 추가:
서브도메인:
immich-mcp도메인:
yourdomain.com서비스:
HTTP→immich_mcp:8080
cloudflared가 컨테이너로 실행되는 경우 이름 확인을 위해 immich_mcp와 네트워크를 공유해야 합니다; 호스트에서 실행되는 경우 http://127.0.0.1:8099를 사용하세요. 설정 파일에 해당하는 내용은 cloudflared/config.example.yml을 참조하세요.
Access 정책을 첨부하지 마세요. ChatGPT는 대화형 Access 로그인을 완료할 수 없습니다. bearer 토큰이 유일한 게이트입니다 — 따라서 교체하는 것이 중요했던 이유입니다.
가능하면 LAN 외부에서도 확인하세요. 휴대폰 핫스팟이 좋은 테스트 방법입니다:
python smoke_test.py https://immich-mcp.yourdomain.com <bearer-token>2. 커넥터 생성
설정 → 커넥터 → 고급 설정 → 개발자 모드 활성화(유료 플랜 필요), 그 다음 생성:
이름: Immich Photos
설명: 중요합니다. 모델이 이를 읽고 커넥터를 호출할지 결정합니다. "개인 사진 및 비디오 라이브러리입니다. 사진, 앨범, 인식된 인물을 찾거나 설명하거나 나열하는 데 사용하세요." 같은 내용
URL:
https://immich-mcp.yourdomain.com/mcp인증: API 키 / 사용자 지정 헤더 →
Authorization: Bearer <token>
그런 다음 채팅 작성기에서 커넥터를 활성화하고 명시적인 도구 이름으로 테스트하세요:
immich search를 사용하여 건조대 사진을 찾아줘
운영
프롬프트에 도구 이름을 명시하세요. ChatGPT는 언제 사용자 지정 커넥터를 사용해야 할지 신뢰성 있게 추측하지 않습니다. "immich search를 사용하여 건조대 사진을 찾아줘"는 잘 작동하는 반면, "내 건조대 사진 찾아줘"는 종종 작동하지 않습니다.
ChatGPT는 사진을 볼 수 없습니다. 도구 결과는 텍스트(설명과 메타데이터)이며 픽셀이 아닙니다. create_share_link가 그 격차를 메워주지만, 공유 링크는 URL을 가진 모든 사람에게 공개되므로 기본적으로 비활성화되어 있습니다.
코드 업데이트. app/immich_mcp.py를 편집한 후 sudo docker compose up -d --build를 실행하세요.
Bearer 토큰 교체. .env를 편집하고 docker compose up -d --force-recreate를 실행한 후 ChatGPT에서 커넥터를 업데이트하세요. ChatGPT가 중단되는 시간이 있습니다 — 대화 중이 아닐 때 수행하세요.
범위가 지정된 앨범에 사진 추가. 할 일이 없습니다. 범위 캐시는 SCOPE_TTL초마다시 재구성됩니다(기본값 300).
재부트 후 자동 시작. restart: unless-stopped가 처리하지만, Container Manger 프로젝트는 때로 GUI에서 자동 재시작을 체크해야 합니다. 자리 비운 사이에 발견하기보다는 편한 시간에 의도적으로 한 번 재부팅하세요.
Imich 버전을 고정하세요. API는 릴리스 사이에 변경됩니다. /server/statistics는 얼마 전까지만 해도 /server-info/statistics였습니다. 인스턴스는 https://photos.youromain.com/api/docs에서 정확한 스펙을 제공합니다; 404를 디버깅하기 전에 거기서 확인하세요.
증상 | 원인 |
빌드: | 파일이 평면 구조이며 |
| 잘못된 네트워크 이름 — 2부 2단계 다시 수행 |
| Immich에 연결할 수 없음 — |
컨테이너가 즉시 종료됨 | 필수 환경 변수 누락 — |
| 앨범 ID가 잘못되었거나 키가 해당 앨범을 읽을 수 없음 |
사전 점검: API 키가 |
|
사전 점검: 1개의 자산만 표시됨 | 키가 거의 아무것도 소유하지 않은 사용자에 속함 |
모든 요청에서 401 발생 |
|
NAS에서는 작동하지만 터널을 통해 502 발생 | cloudflared가 |
터널이 로그인 페이지 반환 | Access 정책이 연결되어 있음; 제거 |
ChatGPT: "search action not found" | Deep Research 모드에서 추가됨; Developer Mode 활성화 |
커넥터가 추가되었지만 실행되지 않음 | 설명이 너무 모호하거나 채팅에서 도구가 활성화되지 않음 |
| Immich 머신 러닝 비활성화됨 — |
Immich가 키를 거부함 (로그에서 401) | 키가 해지되었거나 다른 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
- AlicenseNot 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.54MIT
- AlicenseAqualityAmaintenanceManage your self-hosted Immich photo library through conversation — natural language search via CLIP, geographic album curation, duplicate detection with perceptual hashing,94124 PyPI62MIT
- AlicenseAqualityAmaintenanceEnables AI assistants to query and export from the macOS Apple Photos library using natural language, backed by osxphotos.211,219 npm36MIT

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