Immich MCP Server
Immich MCP サーバー
セルフホスト型の Immich フォトライブラリを、Streamable HTTP 経由で ChatGPT(およびその他の MCP クライアント)に公開します。これにより、「3月のキガリサイト訪問時の写真を探して」といった質問に対して、自宅のNASから実際の回答を得られるようになります。
ChatGPT ──HTTPS──▶ Cloudflare Tunnel ──▶ immich_mcp:8080 ──▶ immich_server:2283
bearer token MCP → REST x-api-keyChatGPT のカスタムコネクタは リモートの HTTPS エンドポイント のみを受け付けます。stdio や localhost のオプションはありません。そのため、サーバーはインターネットから到達可能である必要があり、トンネルが必要です。また、ベアラートークンによる防御も必要です。
目次
Related MCP server: immich-photo-manager
ツール
ツール | 目的 |
| 画像内容に対するCLIPセマンティック検索 |
| UUIDによる1アセットの完全なEXIF情報 |
| 日付、場所、カメラ、人物、お気に入りによるフィルタリング |
| カウント付きの全アルバム |
| 1つのアルバムの詳細と内容 |
| 認識された顔(フィルタリング用のID付き) |
| 写真/動画の数とディスク使用量 |
| Immichのバージョンと有効な機能 |
| 特定のアセットへの公開リンク — デフォルトではオフ |
search と fetch は意図的に命名されています。ChatGPTのDeep Researchモードは他のすべてのツールを無視するため、Developer Modeが利用できない場合、これら2つが処理を担当します。
特定のアルバムへのアクセス制限
デフォルトでは、サーバーはAPIキーが参照できるすべてを公開します。サブセットのみを共有するには、アルバムUUIDを ALLOWED_ALBUM_IDS に設定します。
python list_albums.py # prints every album with its UUIDALLOWED_ALBUM_IDS=a1b2c3d4-...,e5f6g7h8-...すべてのツールは、それらのアルバム内のアセットに制限されます。Immichのスマート検索にはアルバムフィルターがないため、サーバーは許可されたアセットIDのセットを自身で構築し、それ以外のものを除外します。UUIDによる直接の fetch も含まれ、その場合はアセットではなく拒否が返されます。このセットは SCOPE_TTL 秒間キャッシュされるため、許可されたアルバムに写真を追加しても、再起動せずに反映されます。
2つのレイヤーを組み合わせることをお勧めします。Immich APIキーを専用ユーザーにスコープ設定し、かつ ALLOWED_ALBUM_IDS を設定します。キーはこのサーバーが到達できる範囲を制限し、アルバムリストは実際に公開する内容を制限します。
異なるクライアントの接続
サーバーはトークンを3つの方法で受け付けます。これは、MCPクライアントによって送信できるものが異なるためです。
クライアント | URL | 認証 |
ChatGPT コネクタ |
|
|
Claude コネクタ |
| OAuthフィールドは空白のまま |
Claude Code, Cursor, Zed |
|
|
URLのみのクライアント |
| — |
ClaudeのカスタムコネクタダイアログはOAuth Client IDとSecretのみを提供しますが、このサーバーはそれを実装していません。そのため、パス形式を使用します。高いエントロピーのトークンを使用すればセキュリティは同等ですが、パスとクエリ文字列はヘッダーよりもプロキシログやシェル履歴に残りやすいため、クライアントが許可する場合はヘッダーを優先してください。
プロジェクト構成
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/ が重要です。これら2つのファイルが app/ 内ではなくDockerfileの隣に配置されると、ビルドは "/app/immich_mcp.py": not found で失敗します。
パート1 — ノートPCで動作させる
必須ではありませんが、設定変更のたびにイメージを再ビルドするよりもはるかに高速なループです。ここで説明する内容はすべて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ノートPCからは、IMMICH_URL をNASのLANアドレスにする必要があります。immich_server はNAS上でのみ解決されるDockerコンテナ名です。
IMMICH_URL=http://192.168.0.43:2283http:// が2つないことに注意してください。スキームの重複はよくある貼り付けミスで、混乱を招くホスト名エラーの原因になります。
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.py自動リロード付きで http://127.0.0.1:8099 で提供されます。2つ目のターミナルで:
python smoke_test.py http://127.0.0.1:8099 <your-bearer-token>これはChatGPTが行うのとまったく同じハンドシェイク(初期化、tools/list、そしてライブツールコール)を実行し、認証されていないリクエストが401を返すことを確認します。
5. イメージをビルドする(ノートPCでは任意)
Dockerビルドを出荷前に確認したい場合は、まず docker-compose.yml から networks: ブロックを削除してください。immich_default はNAS上にのみ存在します。
docker compose up -d --build
curl.exe http://127.0.0.1:8099/healthzパート2 — NASにデプロイする
変更されるのは4つです。コンテナがImmichに到達する方法、参加するDockerネットワーク、ファイルの所有権、イメージのビルド方法です。
0. まず両方のシークレットをローテーションする
Immich APIキーまたはベアラートークンがチャット、メール、共有ドキュメントに貼り付けられた場合は、漏洩したものとして扱ってください。このエンドポイントはまもなくインターネットに公開されます。
Immich → アカウント設定 → APIキー → 古いキーを削除し、新しいものを作成する
新しいベアラートークン:
openssl rand -hex 32
ノートPCの .env をコピーしないでください。IMMICH_URL がLANアドレスを指しており、これは機能しますが、フォトメタデータをLAN経由で無駄に往復させることになります。NAS上では .env.example から始めてください。
1. プロジェクトをコピーする
他のスタックと一緒に配置します(例: /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はUID 1027(Synologyの一般的な慣例)のユーザーを作成します。id で確認してください。異なる場合は、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次の3行に注目してください。
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ログインを完了できません。ベアラートークンが唯一のゲートです。そのため、ローテーションが重要だったのです。
可能であればLAN外から確認してください。スマートフォンのテザリングが良いテストになります。
python smoke_test.py https://immich-mcp.yourdomain.com <bearer-token>2. コネクタを作成する
設定 → コネクタ → 詳細設定 → Developer Mode を有効にする(有料プランが必要)。その後、作成:
名前: 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 を実行します。
ベアラートークンのローテーション。 .env を編集し、docker compose up -d --force-recreate を実行し、ChatGPTのコネクタを更新します。ChatGPTが使えなくなる期間があります。会話の途中で行わないでください。
スコープ設定されたアルバムへの写真追加。 何もする必要はありません。スコープキャッシュは SCOPE_TTL 秒(デフォルト300)ごとに再構築されます。
再起動後の自動起動。 restart: unless-stopped で処理されますが、Container ManagerのプロジェクトはGUIで自動再起動をオンにする必要がある場合があります。都合の良い時間に、意図的に一度再起動して確認してください。不在時に問題が発生するのを防げます。
Immichのバージョンを固定してください。 APIはリリース間で変化します。/server/statistics は少し前まで /server-info/statistics でした。あなたのインスタンスは https://photos.yourdomain.com/api/docs で正確な仕様を公開しています。404をデバッグする前に、そこで確認してください。
トラブルシューティング
症状 | 原因 |
ビルド: | ファイルはフラットです。 |
| 間違ったネットワーク名 — パート2のステップ2をやり直してください |
| Immich に到達できません — |
コンテナがすぐに終了する | 必要な環境変数が不足 — |
| アルバム ID が間違っているか、キーがそのアルバムを読み取れません |
Preflight: API キーが |
|
Preflight: アセットが 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