{"id":"45933b29-10d6-4b9d-823e-0408e323cced","slug":"mcp-photo-edit","kind":"mcp","name":"mcp-photo-edit","summary":"An MCP server for agent-driven Lightroom-like RAW photo editing with RawTherapee","owner":"joshua5201","repoUrl":"https://github.com/joshua5201/mcp-photo-edit","license":"GPL-3.0","licenseTier":"strong-copyleft","trust":"community","stars":2,"match":null,"fewStars":true,"format":"mcp","createdAt":"2026-04-12T01:07:02.000Z","addedAt":"2026-10-21T04:26:53.841Z","logoUrl":"https://avatars.githubusercontent.com/u/1542613?u=5be11d5a4447a3055fe8a27c5bc4015943f5afe3&v=4","linkOnly":false,"collection":null,"skillPath":null,"categories":["design-media","cloud-infra"],"tags":["agent","llm","photo-editing","rawtherapee"],"runtime":"python","local":true,"cloudCapable":false,"cloudCapability":"unknown","cloudReadyOnPlatform":false,"needsApiKey":false,"reviewed":false,"syncedAt":"2026-10-21T04:27:20.971Z","sample":false,"url":"https://conduits.dev/tools/mcp-photo-edit","language":"Python","transports":["stdio"],"install":{"pypi":"mcp-photo-edit"},"requirements":{"env":[],"upstreamMayCharge":false},"tools":null,"readme":"# mcp-photo-edit\n\nAn installable MCP server for agent-driven photo editing with RawTherapee.\n\nThe server exposes a session-based editing workflow instead of raw sidecar manipulation.\nAgents create an edit session, apply structured adjustments, regenerate previews when\nneeded, and export a final image. Installing `mcp-photo-edit` installs all Python runtime\ndependencies automatically; users only need Python, an MCP client, and RawTherapee.\n\nEach session now also maintains an explicit undo / redo timeline in `session.json`. Semantic edit history is tracked separately from preview-render history.\n\n## Examples\n\nThe JPEG images embedded in this README are original work by Tsung-en Hsiao and are\nlicensed under [CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/).\nSee [demo/ASSET_LICENSES.md](demo/ASSET_LICENSES.md) for the per-file list.\n\n### Example: Fujifilm Style (v0.2.0)\n\nCompare the baseline image with the two Fujifilm-style outputs below. Each thumbnail links to the full-size file. One with [advanced image info](#advanced-image-info) and the other off.\n\n**Prompt:**\n> Apply a Fujifilm camera like profile to `demo/cosplay.NEF`. Apply a crop to focus on the center but keep the aspect ratio, export the result as `demo/fujifilm_style.jpg`\n\n| Before | Preview only | With diagnostics |\n| :--- | :--- | :--- |\n| <a href=\"demo/cosplay.jpg\"><img src=\"demo/cosplay.jpg\" alt=\"Before\" width=\"240\"></a> | <a href=\"demo/fujifilm_style_pro.jpg\"><img src=\"demo/fujifilm_style_pro.jpg\" alt=\"After with advanced image info disabled\" width=\"240\"></a> | <a href=\"demo/fujifilm_style_advanced_info_pro.jpg\"><img src=\"demo/fujifilm_style_advanced_info_pro.jpg\" alt=\"After with advanced image info enabled\" width=\"240\"></a> |\n\n**Model:** gemini-3.1-pro-preview\n\n### Example: CCD Style (v0.2.0)\n\nThis example compares [advanced image info](#advanced-image-info)-assisted runs using the same source image, prompt but different models.\n\n**Prompt:**\n> Apply a 2000s CCD camera like profile to `demo/cosplay.NEF`. Apply a crop to focus on the center but keep the aspect ratio, export the result as [demo/ccd_style_gpt54_mini_medium.jpg](demo/ccd_style_gpt54_mini_medium.jpg)\n\nMain comparison:\n\n| Baseline | Gemini 3 Flash | Gemini 3.1 Pro | GPT-5.4 (Medium) | GPT-5.4 Mini (Medium) |\n| :--- | :--- | :--- | :--- | :--- |\n| <a href=\"demo/cosplay.jpg\"><img src=\"demo/cosplay.jpg\" alt=\"Baseline\" width=\"240\"></a> | <a href=\"demo/ccd_style_flash.jpg\"><img src=\"demo/ccd_style_flash.jpg\" alt=\"CCD style by Gemini 3 Flash\" width=\"240\"></a> | <a href=\"demo/ccd_style_pro.jpg\"><img src=\"demo/ccd_style_pro.jpg\" alt=\"CCD style by Gemini 3.1 Pro\" width=\"240\"></a> | <a href=\"demo/ccd_style_gpt54_medium.jpg\"><img src=\"demo/ccd_style_gpt54_medium.jpg\" alt=\"CCD style by GPT-5.4 Medium\" width=\"240\"></a> | <a href=\"demo/ccd_style_gpt54_mini_medium.jpg\"><img src=\"demo/ccd_style_gpt54_mini_medium.jpg\" alt=\"CCD style by GPT-5.4 Mini\" width=\"240\"></a> |\n\n**Models:** gemini-3-flash-preview, gemini-3.1-pro-preview, gpt-5.4 (medium), gpt-5.4-mini (medium)\n\n## Status\n\nThis is an MVP implementation.\n\nCurrent focus:\n\n- session-based editing flow\n- structured adjustment schema\n- `rawtherapee-cli` preview and export\n- RAW and common raster inputs when supported by the local RawTherapee build\n\nNot in scope:\n\n- local masks\n- healing / AI retouch\n- full photo-editor feature coverage\n- large preset libraries\n- batch editing UX\n\n## Requirements\n\n- Python 3.12+\n- `uv` for the easiest install and run workflow, or `pipx`\n- RawTherapee with `rawtherapee-cli` available on `PATH`, or an absolute executable\n  path set in `RAWTHERAPEE_CLI`\n\n### Tested Environment\n\n- **OS:** Windows 11 and Ubuntu 24.04 LTS\n- **RawTherapee:** v5.12 on Windows and in the Ubuntu 24.04 RAW E2E workflow\n\nVerify RawTherapee:\n\n```shell\nrawtherapee-cli -v\n```\n\n### Real RAW E2E test\n\nThe normal test suite skips the real RAW fixture so contributors without\nRawTherapee can run the fast unit tests. To exercise the complete MCP stdio →\nRawTherapee CLI path, provide an absolute CLI path and opt in explicitly:\n\n```powershell\n$env:RAWTHERAPEE_CLI = \"C:\\Program Files\\RawTherapee\\5.12\\rawtherapee-cli.exe\"\n$env:MCP_PHOTO_EDIT_RAW_E2E = \"1\"\nuv run --frozen pytest -m raw_e2e\n```\n\nThe public fixture is licensed separately under CC BY-SA 4.0 and the workflow\ndoes not upload any generated previews or exports.\n\nOn Windows, if RawTherapee is installed but its directory is not on `PATH`, set the\nabsolute executable path before starting the MCP client:\n\n```powershell\n$env:RAWTHERAPEE_CLI = \"C:\\Program Files\\RawTherapee\\5.12\\rawtherapee-cli.exe\"\n```\n\n## Install\n\nRun the published package without cloning this repository:\n\n```shell\nuvx mcp-photo-edit\n```\n\n`uvx` creates and caches an isolated environment. All Python dependencies are resolved\nfrom the package metadata. To install the command persistently instead:\n\n```shell\nuv tool install mcp-photo-edit\n```\n\nOr use `pipx`:\n\n```shell\npipx install mcp-photo-edit\n```\n\nAfter a persistent install, the executable is simply `mcp-photo-edit`.\n\n## MCP Quickstart\n\nExample stdio configurations\n\n### Codex CLI\n\nAdd this block:\n\n```toml\n[mcp_servers.photo_edit]\ncommand = \"uvx\"\nargs = [\"mcp-photo-edit\"]\n\n[mcp_servers.photo_edit.env]\nMCP_PHOTO_EDIT_WORKDIR = \"/absolute/path/to/.mcp-photo-edit\"\n```\n\nIf you prefer to add it from the CLI instead of editing TOML manually:\n\n```bash\ncodex mcp add photo-edit --env MCP_PHOTO_EDIT_WORKDIR=/absolute/path/to/.mcp-photo-edit -- uvx mcp-photo-edit\n```\n\nVerify the server is registered:\n\n```bash\ncodex mcp list\n```\n\nRecommended `AGENTS.md` snippet for better tool selection:\n\n```md\nUse the `photo-edit` MCP server for photo-editing tasks. Create an edit session first, iterate with previews, and export only when the preview looks correct.\n```\n\n### Gemini CLI\n\nAdd this block:\n\n```json\n{\n  \"mcpServers\": {\n    \"photo-edit\": {\n      \"command\": \"uvx\",\n      \"args\": [\"mcp-photo-edit\"],\n      \"env\": {\n        \"MCP_PHOTO_EDIT_WORKDIR\": \"/absolute/path/to/.mcp-photo-edit\"\n      },\n      \"timeout\": 30000,\n      \"trust\": true\n    }\n  }\n}\n```\n\nOr add it from the CLI. This example writes to user config instead of project-local config:\n\n```bash\ngemini mcp add --scope user --transport stdio --env MCP_PHOTO_EDIT_WORKDIR=/absolute/path/to/.mcp-photo-edit --timeout 30000 --trust photo-edit uvx mcp-photo-edit\n```\n\nIf you omit `--scope user`, Gemini CLI writes the MCP entry to project-local config by default.\n\nVerify the configuration:\n\n```bash\ngemini mcp list\n```\n\nIf Gemini shows the stdio server as disconnected, trust the current folder first:\n\n```bash\ngemini trust\n```\n\n## Compatibility Note\n\nRAW support depends on the local RawTherapee build and its bundled RAW decoders. A file extension being supported in principle does not guarantee that every camera or compression variant will decode on every machine. When diagnosing unsupported RAW files, check the installed RawTherapee version and the camera / compression mode used by the source file. For reference, this project is primarily developed and tested on the environment described in the [Tested Environment](#tested-environment) section.\n\n**Note on Nikon RAW:** Some compressed Nikon RAW formats (e.g., High Efficiency / HE* compression) may not be supported by the underlying libraries in current RawTherapee builds. If you encounter issues with Nikon files, try using uncompressed RAW or Lossless Compressed modes if available in-camera.\n\n## Advanced Image Info\n\nThe server can attach structured diagnostics to each preview:\n\n- `preview_path` remains the primary image for aesthetic judgment.\n- `diagnostic_summary` adds machine-readable stats for exposure, balance, and saturation.\n- Set `DISABLE_ADVANCED_IMAGE_INFO=true` to turn the diagnostics off and keep the original preview-first workflow.\n\n## Available Tools\n\n- `create_edit_session`\n- `get_edit_session`\n- `render_preview`\n- `apply_adjustments`\n- `reset_adjustments`\n- `undo_adjustment`\n- `redo_adjustment`\n- `export_image`\n- `list_supported_adjustments`\n\n`render_preview` regenerates the current session preview, appends a new preview artifact, and returns the latest `preview_count`.\n`undo_adjustment` and `redo_adjustment` move the session cursor across committed edit states without creating new edit-history entries.\n\n## Typical Agent Workflow\n\n1. Create a session from an input image.\n2. Inspect the returned session state, including `preview_path`, `preview_history`, current adjustment state, and history cursor fields such as `history_index`, `history_length`, `can_undo`, and `can_redo`.\n3. Apply one or more adjustments.\n4. Use `undo_adjustment` or `redo_adjustment` when you need to move across committed edit steps.\n5. Re-check the preview by calling `render_preview` whenever you want a fresh preview artifact and an explicit `preview_count` for the current step.\n6. Export a final image explicitly.\n\nSee [SKILL.md](skills/mcp-photo-edit/SKILL.md) for an agent-facing usage guide.\n\n## Adjustment Model\n\nThe public API exposes a stable edit schema. It does not ask clients to hand-author backend profile files.\n\nCurrent default-backend MVP adjustments:\n\n- `exposure`\n- `contrast`\n- `saturation`\n- `rgb_mixer`\n- `denoise_luma`\n- `denoise_detail`\n- `denoise_chroma`\n- `color_temperature`\n- `green_balance`\n- `highlights`\n- `shadows`\n- `sharpen_amount`\n- `sharpen_radius`\n- `sharpen_contrast`\n- `orientation`\n- `crop`\n\nUse `list_supported_adjustments` to discover exact ranges, defaults, and example payloads at runtime.\n\n`list_supported_adjustments` is the source of truth for the installed renderer's runtime\ncapabilities.\n\n## Session History\n\n- `session.json` is the authoritative session timeline.\n- `history` stores committed semantic edit steps.\n- `history_index` points to the current step.\n- `state.json` is the current renderer-neutral service request state.\n- `render_preview` appends preview artifacts but does not append semantic edit history.\n- Applying a new edit after undo truncates the redo tail.\n\n## Project Layout\n\n```text\nsrc/mcp_photo_edit/\n  interfaces.py    Backend protocols\n  backend.py       Local file editing backend\n  models.py        Pydantic schemas and validation\n  session.py       Session lifecycle and persistence\n  server.py        MCP tool registration\ntests/\nskills/\n```\n\n## Development\n\nInstall dev dependencies:\n\n```bash\nuv sync --frozen --group dev\n```\n\nRun tests:\n\n```bash\nuv run --frozen pytest\n```\n\nStart the server over stdio:\n\n```bash\nuv run --frozen mcp-photo-edit\n```\n\nThis repository is self-contained for development. `uv sync --frozen --group dev` uses\nthe checked-in public-index lockfile to resolve all declared Python dependencies\nautomatically. Development and CI require uv `0.11.32`; the project itself is the\nexpected editable root entry in `uv.lock`.\n\n\n## Disclaimers\n\n- This project invokes `rawtherapee-cli`; it does not embed or redistribute RawTherapee internals.\n- Exact visual behavior depends on the local RawTherapee version, decoder support, ICC setup, and the input file.\n- The server never modifies the original source image. It writes session artifacts and backend state files in a managed workspace.\n"}