loading…
Search for a command to run...
loading…
Enables Claude and other AI assistants to control darktable for photo management and editing through its Lua API.
Enables Claude and other AI assistants to control darktable for photo management and editing through its Lua API.
A Model Context Protocol (MCP) server that exposes a small set of darktable operations to MCP clients (e.g. Claude Desktop, Claude Code). The AI lives in the client; this server drives darktable.
Implemented tools:
Library operations (headless, via darktable Lua API):
view_photos — Browse your darktable library with filtering and rating optionsrate_photos — Apply star ratings to photos already in your libraryimport_batch — Import photos from a directory into the libraryimport_from_camera — Detect a connected camera (libgphoto2) and copy photos to a local directoryVision-rating workflow (headless, file-based — no library required):
extract_previews — Pull auto-rotated JPEG previews out of raw files (NEF/CR2/ARW/DNG/etc), with a tiered thumb pass and an EXIF summary per file. Designed for token-efficient visual rating loops in MCP clients.apply_ratings_batch — Write XMP sidecars (xmp:Rating) for a {stem: rating} batch, plus an append-only ratings.jsonl log so the history survives session resets.open_in_darktable — Launch the darktable GUI on a folder. The folder registers as a film roll on first launch and the XMP sidecars are picked up automatically. With an exact rating (rating=N or rating_min == rating_max), the lighttable opens already filtered via darktable.gui.libs.collect.filter (the official Lua API). Range filtering is currently echoed as a hint without being pre-applied.GUI / export:
adjust_exposure — Adjust exposure settings (opens darktable GUI for preview)export_images — Export photos to JPEG/PNG/TIFF via darktable-cliNot yet implemented:
apply_preset — Apply editing presets to photos (planned)The vision-rating tools require an optional [vision] install (rawpy / Pillow / pyexiv2) so the base install stays light.
darktable-cli for export;
the official Lua API for everything else. Do not read or write
library.db directly under any circumstances.darktable-cli deliberately does not load the user's library, so it
cannot browse it. darktable --lua brings up the full GUI. That means
there is no headless, official-API path today for library reads or
writes. The honest answer is to not ship those tools yet.
The planned unblocker is a long-running darktable instance running a Lua plugin that exposes a small RPC (e.g. unix socket); the MCP server talks to that plugin. That keeps every rule above intact — official API, headless after the user already has darktable open, no DB poking.
# Base install — library, import, export, GUI tools.
pip install darktable-mcp
# Optional: vision-rating workflow (extract_previews, apply_ratings_batch).
pip install 'darktable-mcp[vision]'
You also need darktable (with darktable-cli) installed and available
on your PATH. The [vision] extra pulls in rawpy, Pillow, and
pyexiv2, which in turn need libraw and libexiv2 system packages.
Quick test: After installation, try:
# In Claude Desktop, you can now ask:
# "Show me my recent photos" (uses view_photos)
# "Rate these photos 4 stars" (uses rate_photos)
# "Import photos from ~/Pictures/vacation" (uses import_batch)
Note: First run will auto-detect your darktable library location. Make sure you've opened darktable and imported some photos before using the MCP server.
Add to your Claude Desktop config:
~/Library/Application Support/Claude/claude_desktop_config.json%APPDATA%\Claude\claude_desktop_config.json~/.config/Claude/claude_desktop_config.json{
"mcpServers": {
"darktable": {
"command": "darktable-mcp"
}
}
}
Library:
view_photos(filter?, rating_min?, limit?) — Browse photos in your darktable library. Filter by filename, minimum rating, or limit results.rate_photos(photo_ids, rating) — Apply 1-5 star ratings to specific photos by ID.import_batch(source_path, recursive?) — Import photos from a directory into the library.import_from_camera(destination?, camera_port?, timeout_seconds?) — Detect a connected camera via libgphoto2 and copy all photos to a local directory. Returns the destination path.Vision-rating workflow:
extract_previews(source_dir, output_dir?, max_dim?, thumb_dim?, overwrite?) — Extract embedded JPEG previews from raws, auto-rotate via EXIF orientation, and write a tiered preview (default 1024px) plus a small first-pass thumb (default 384px). Returns per-file paths and an EXIF summary (ISO, shutter, focal, aperture, datetime).apply_ratings_batch(source_dir, ratings, log?) — Write XMP sidecars for a {stem: rating} batch (range -1..5, -1 = reject). Appends each rating to <source_dir>/ratings.jsonl for replay/audit.open_in_darktable(source_dir, rating?, rating_min?, rating_max?) — Launch darktable on a folder. The folder is registered as a film roll on first launch and XMP sidecars are picked up automatically. With an exact rating=N, the lighttable opens already filtered to that rating via darktable.gui.libs.collect.filter (the official Lua API). Range filtering (rating_min != rating_max) is not yet pre-applied — the request comes back as a hint.GUI / export:
adjust_exposure(photo_ids, exposure_ev) — Adjust exposure settings for photos. Opens darktable GUI to show preview.export_images(photo_ids, output_path, format, quality?) — Export photos to JPEG/PNG/TIFF via darktable-cli.apply_preset(photo_ids, preset_name) — Apply editing presets to photos. Planned for next release.When darktable's library doesn't yet know about your shoot — typically straight off a card or a freshly-copied folder — you can rate by vision before any import:
extract_previews writes auto-rotated JPEGs (and small thumbs) next to a small EXIF summary so an MCP client can iterate efficiently.apply_ratings_batch to write XMP sidecars alongside the raws.open_in_darktable launches the GUI with the folder imported as a film roll. With an exact rating (e.g. rating=5) the lighttable opens already filtered to those photos via the Lua API; range filtering currently returns a hint instead.No SQLite poking, no half-imported state, and no GUI launch until step 3.
darktable-cli on PATH)"darktable setup error" — Ensure darktable is installed and you've opened it at least once to create the library database.
"Failed to parse photo data" — Your darktable library may be corrupted or in an unexpected format. Try opening darktable directly to verify it works.
"Library not found" — The auto-detector couldn't find your darktable library. Common locations:
~/.config/darktable/library.db~/Library/Application Support/darktable/library.db %APPDATA%\Local\darktable\library.dbIf your library is in a custom location, please open an issue.
Tool timeouts — Some operations may take longer on large libraries. This is normal for the first run or after major library changes.
Contributions welcome. The most useful starting point is the long-running
Lua-plugin + IPC integration that unblocks every parked tool. Any change
that reads or writes library.db directly will be rejected.
MIT — see LICENSE.
darktable, MCP, model context protocol, photo editing, RAW processing, batch processing, photography workflow, Claude
Добавь это в claude_desktop_config.json и перезапусти Claude Desktop.
{
"mcpServers": {
"darktable-mcp": {
"command": "npx",
"args": []
}
}
}