GIMP MCP
Demo
Full demo (with audio): https://github.com/gimp-mcp/gimp-mcp/raw/main/docs/demo.mp4
AI agent using GIMP MCP to remove a background, edit a character's expression, and verify results — all through natural language via Claude
Overview
GIMP MCP bridges GIMP's professional image editing capabilities with AI assistants through the Model Context Protocol. It lets you edit images by describing what you want — and gives the AI a live visual feedback channel to verify each change before moving on.
What makes it different from other GIMP integrations:
- The AI can see the image at any point in the workflow without saving to disk (
get_state_snapshot) - Supports fully autonomous multi-step pipelines: open → edit → verify → refine → export
- 79 dedicated tool commands covering every major GIMP operation
- Fully compatible with GIMP 3.2.x (all breaking API changes resolved)
Key Features
| 👁️ Live Visual Feedback | get_state_snapshot returns a PNG preview mid-workflow so the AI verifies each step |
| 🎨 79 GIMP Tools | Adjustments, transforms, selections, layers, drawing, text, filters — all via MCP |
| 🔧 GIMP 3.2 Compatible | All GIMP 3.2 API breaks fixed and tested (59/59 passing) |
| 🔁 Iterative Workflows | AI loops until a goal is met — e.g. keeps removing BG until no pixels remain |
| 🖼️ Region Snapshots | Zoom into any area for detail verification (face, mouth, corner, etc.) |
| 🔌 Universal MCP | Works with Claude Desktop, Claude Code, Gemini CLI, PydanticAI, and more |
What Can It Do?
Background Removal with Iterative Verification
The AI removes the background, takes a snapshot to inspect the result, detects remaining pixels, and loops until the image is clean:
"Remove the background from this image and keep looping until only the character remains"
Expression Editing
"Make the character smile — paint a smile arc with teeth over her mouth"
Complex Multi-Step Pipelines
"Open navi_portrait.png, remove the background, verify it's clean,
then make her smile and export the final result as a PNG"
Color & Tone Work
"Boost the contrast, shift the hue 15 degrees warmer, then show me a before/after zoom of the face"
Text & Compositing
"Add a bold title at the top in white with a subtle drop shadow, then export for web"
Prerequisites
- GIMP 3.2+ — tested on GIMP 3.2.2 (Windows, macOS, Linux)
- uv — Python package manager (install uv);
uvxdownloads the MCP server and a suitable Python (3.11+) on first use - MCP-compatible AI client — Claude Desktop, Claude Code, Gemini CLI, PydanticAI, etc.
Quick Start
The MCP server and the GIMP plugin ship together as the gimp-mcp-plugin package on PyPI. No clone needed.
1. Install the GIMP Plugin
Launch GIMP once (so its config folder exists), close it, then run:
uvx gimp-mcp-plugin@latest install-plugin
This copies the plugin into the newest GIMP 3.x config folder it finds (Linux standard, Snap and Flatpak locations, macOS, Windows) and makes it executable. Restart GIMP afterward.
--dry-runshows where it would install without writing anything.--gimp-dir DIRinstalls into a specific GIMP config folder, e.g.--gimp-dir ~/.config/GIMP/3.2.
If you have more than one GIMP 3 installation (e.g. a system GIMP and a Flatpak), the newest folder found may not be the one your GIMP uses. Check the folder shown in GIMP's Edit → Preferences → Folders → Plug-ins and pass the folder that contains plug-ins with --gimp-dir.
Which folder does GIMP use? GIMP names its per-user folder after its major.minor version (
3.0,3.2,3.4, …) and creates a fresh one on each minor upgrade, so the plug-ins folder moves when you upgrade GIMP. Re-runinstall-pluginafter upgrading. To check the active path, open Edit → Preferences → Folders → Plug-ins in GIMP.
2. Start the MCP Server in GIMP
- Open any image in GIMP
- Go to Tools > MCP > Start MCP Server
- Server starts on
localhost:9877
Start automatically when GIMP launches
To skip step 2 on every launch, open Tools > MCP > MCP Server Settings..., tick Start MCP server when GIMP launches, and restart GIMP. Autostart is off by default.
The same dialog sets the port (default 9877). If you change it, set GIMP_MCP_PORT
in your MCP client config so the MCP server connects to the same port:
"gimp": {
"command": "uvx",
"args": ["gimp-mcp-plugin@latest"],
"env": { "GIMP_MCP_PORT": "9988" }
}
Settings are saved to gimp-mcp.json in GIMP's per-user config folder (e.g.
~/.config/GIMP/3.2/gimp-mcp.json). Port changes apply the next time the server starts.
Timeout for long commands
The MCP server waits up to 300 seconds for GIMP to finish each command. For heavier work
(large or 16-bit images, slow filters), set GIMP_MCP_TIMEOUT (in seconds) in your MCP
client config, the same way as GIMP_MCP_PORT above, e.g. "GIMP_MCP_TIMEOUT": "900".
check_server reports the timeout in effect. When a command times out, GIMP may still be
running it, so check the image before retrying. Your MCP client may have its own tool
timeout (in Claude Code, MCP_TOOL_TIMEOUT, in milliseconds); raise it too if it's shorter.
3. Configure Your MCP Client
gimp-mcp-plugin@latest makes uvx check PyPI for a new release each time your client starts the server.
Claude Desktop
~/.config/Claude/claude_desktop_config.json (Linux/macOS) or %APPDATA%\Claude\claude_desktop_config.json (Windows):
{
"mcpServers": {
"gimp": {
"command": "uvx",
"args": ["gimp-mcp-plugin@latest"]
}
}
}
Claude Code
claude mcp add gimp-mcp -- uvx gimp-mcp-plugin@latest
Gemini CLI
~/.config/gemini/.gemini_config.json:
{
"mcpServers": {
"gimp": {
"command": "uvx",
"args": ["gimp-mcp-plugin@latest"]
}
}
}
PydanticAI
from pydantic_ai import Agent
from pydantic_ai.mcp import MCPServerStdio
server = MCPServerStdio('uvx', args=['gimp-mcp-plugin@latest'])
agent = Agent('openai:gpt-4o', mcp_servers=[server])
Cancelling long commands
GIMP runs one command at a time, in the order they're sent. While it works, the MCP server stays responsive, so your client can cancel a call. The cancel returns at once: a command that's still waiting its turn never runs, but one GIMP has already started is finished in the background. Check the image before retrying a cancelled edit, or it may be applied twice.
Updating
The plugin and the MCP server must be the same version. check_server and get_gimp_info report a mismatch and print the command that fixes it. To update both:
- Restart your MCP client. With
@latest, it picks up the newest server. - Run
uvx gimp-mcp-plugin@latest install-pluginand restart GIMP.
Running from a Git Checkout (contributors)
To work on the code, run the server and install the plugin from a clone instead:
git clone https://github.com/gimp-mcp/gimp-mcp.git
cd gimp-mcp
uv sync
uv run gimp_mcp_server.py install-plugin # installs this checkout's plugin
Then point your MCP client at the checkout, e.g. for Claude Desktop:
"gimp": {
"command": "uv",
"args": ["run", "--directory", "/full/path/to/gimp-mcp", "gimp_mcp_server.py"]
}
Claude Code picks up the repo's .mcp.json automatically when started in the checkout. After git pull, re-run install-plugin if the plugin changed.
Available MCP Tools
👁️ Visual Feedback
get_state_snapshot(image_index, max_size, region, label)
Returns a live PNG of the current image state — the AI's primary feedback mechanism. Call this between any edits to verify the result without saving to disk.
# Full image snapshot
snapshot = get_state_snapshot(max_size=512)
# Zoom into a face region for detail inspection
snapshot = get_state_snapshot(
region={"x": 140, "y": 80, "width": 240, "height": 300},
max_size=512,
label="face-check"
)
This enables iterative agentic workflows: edit → snapshot → assess → refine → repeat.
get_image_bitmap(image_index, max_width, max_height, region)
Lower-level bitmap fetch with region extraction and scaling. Returns base64-encoded PNG.
🎨 Adjustments
| Tool | Description |
|---|---|
adjust_brightness_contrast |
Brightness and contrast |
adjust_curves |
Curves by channel (RGB/R/G/B/A) |
adjust_hue_saturation |
Hue, saturation, lightness |
adjust_color_balance |
Shadows/midtones/highlights color balance |
auto_levels |
Auto-stretch levels |
desaturate |
Convert to grayscale (keep RGB mode) |
invert_colors |
Invert all channels |
convert_color_mode |
Convert between RGB, grayscale, and indexed modes |
sharpen |
Unsharp mask sharpening |
blur |
Gaussian blur |
denoise |
Noise reduction |
🔄 Transforms
| Tool | Description |
|---|---|
scale_image |
Scale to exact dimensions |
scale_to_fit |
Scale within bounding box (aspect-safe) |
crop_to_rect |
Crop to rectangle |
crop_to_selection |
Crop canvas to the current selection bounds |
rotate_image |
Rotate 90/180/270 or arbitrary angle |
flip_image |
Flip horizontal or vertical |
resize_canvas |
Resize canvas without scaling content |
warp_region |
Warp / liquify a region by pushing pixels in a direction |
✂️ Selections
| Tool | Description |
|---|---|
select_rectangle |
Rectangular marquee |
select_ellipse |
Elliptical marquee |
select_by_color |
Select by color (global) |
select_all / select_none |
Select all / deselect |
invert_selection |
Invert selection |
modify_selection |
Grow, shrink, feather, or border |
🗂️ Layers
| Tool | Description |
|---|---|
create_layer |
New empty layer |
duplicate_layer |
Duplicate active layer |
delete_layer |
Delete named layer |
rename_layer |
Rename layer |
set_layer_properties |
Opacity, blend mode, visibility |
reorder_layer |
Move layer in stack |
merge_visible_layers |
Flatten visible to one layer |
flatten_image |
Flatten all layers |
list_layers |
List all layers with properties |
🖌️ Drawing & Fill
| Tool | Description |
|---|---|
fill_layer |
Fill entire layer with color |
fill_selection |
Fill selection (foreground/background/transparent) |
fill_rectangle |
Fill a rectangle region |
fill_ellipse |
Fill an ellipse region |
draw_line |
Draw a line (pencil or paintbrush) |
draw_rectangle |
Draw a rectangle outline |
draw_ellipse |
Draw an ellipse outline |
gradient_fill |
Apply linear or radial gradient |
set_colors |
Set foreground/background colors |
🔤 Text
| Tool | Description |
|---|---|
add_text |
Add a text layer |
edit_text |
Edit existing text layer |
list_fonts |
List available fonts |
✨ Filters & Effects
| Tool | Description |
|---|---|
apply_gaussian_blur |
Gaussian blur filter |
apply_pixelate |
Pixelate/mosaic effect |
apply_emboss |
Emboss effect |
apply_vignette |
Vignette darkening |
apply_noise |
Add noise/grain |
apply_drop_shadow |
Drop shadow effect |
📁 File Operations
| Tool | Description |
|---|---|
open_image |
Open image file |
export_image |
Export to PNG, JPEG, BMP, TIFF |
save_xcf |
Save as GIMP XCF (preserves layers and metadata) |
new_canvas |
Create blank canvas |
close_image |
Close image |
list_images |
List open images |
set_active_image |
Bring a specific open image to the front |
📦 Batch & Multi-Format Export
| Tool | Description |
|---|---|
batch_export |
Export all open images (or one) to a directory |
batch_resize |
Resize all open images to a common size |
export_web_optimized |
Export as JPEG and PNG, keeping the smaller |
export_icon_sizes |
Export a full Android or iOS icon set |
export_social_media_kit |
Export resized versions for social media platforms |
export_sprite_sheet |
Combine frames into a sprite sheet PNG |
↩️ History
| Tool | Description |
|---|---|
undo |
Undo one or more operations on an image |
redo |
Redo previously undone operations |
🔍 Info & Context
| Tool | Description |
|---|---|
get_image_metadata |
Image size, mode, layers, filename |
get_gimp_info |
GIMP version, platform, capabilities |
get_context_state |
Current colors, brush, opacity, mode |
get_pixel_color |
Color value at a specific pixel |
get_histogram |
Histogram data for a channel |
get_selection_bounds |
Current selection bounds |
🔌 Connection & Raw API
| Tool | Description |
|---|---|
check_server |
Check the GIMP plugin socket is reachable and that the plugin version matches the server |
restart_server |
Drop and re-establish the connection to the plugin |
call_api |
Run arbitrary Python-Fu code inside GIMP (escape hatch for anything not covered above) |
AI Agent Feedback Loop
The get_state_snapshot tool enables a pattern where the AI loops until a goal is visually confirmed:
┌─────────────┐
│ Apply edit │
└──────┬──────┘
│
▼
┌─────────────────┐
│ get_state_ │ ← AI sees live PNG, no disk save needed
│ snapshot() │
└──────┬──────────┘
│
▼
┌─────────────────┐ ┌──────────────────┐
│ Goal achieved? │─ No─▶ Adjust & retry │
└──────┬──────────┘ └──────────────────┘
│ Yes
▼
┌─────────────┐
│ Export │
└─────────────┘
Example: Iterative Background Removal
See bg_remove_iterative.py for a complete example. The AI:
- Removes the background using edge-seeded contiguous select
- Takes a snapshot to check the result
- Scans for remaining background-colored pixels
- Runs targeted removal passes with progressively finer grids (25px → 1px)
- Runs a final despeckle pass for isolated pixels
- Loops until no background pixels remain
Example Scripts
| Script | Description |
|---|---|
run_tests.py |
59-test suite — run against your GIMP to verify all tools work |
bg_remove_iterative.py |
Iterative BG removal with snapshot checkpoints |
bg_remove.py |
Simple single-pass background removal |
agent_edit_demo.py |
Full pipeline: open → remove BG → edit expression → export |
tests/test_add_text_metadata.py |
Regression test: add_text returns real layer metadata |
tests/continuous_edit_test/continuous_edit_test.py |
End-to-end agent editing loop: BG removal, selective recolor, composite |
Run the test suite to verify your setup:
python run_tests.py
# Expected: 59/59 PASSED
Technical Architecture
Plugin ↔ Server Communication
AI Client (Claude, etc.)
│ MCP (stdio)
▼
gimp_mcp_server.py ← MCP tool definitions
│ TCP JSON :9877
▼
gimp-mcp-plugin.py ← Runs inside GIMP process
│ PyGObject
▼
GIMP 3.2 (gi.repository.Gimp)
- MCP server translates tool calls into JSON commands sent to the plugin over TCP
- Plugin executes operations directly in the GIMP process via PyGObject
- Two message formats:
{"type": "...", "params": {...}}for named tools,{"cmds": ["python..."]}for arbitrary exec
GIMP 3.2 Compatibility Notes
GIMP 3.x introduced breaking API changes from GIMP 2.x. Key fixes included in this release:
| Issue | Fix |
|---|---|
layer.copy(False) → error |
layer.copy() takes no args in GIMP 3.2 |
Gimp.text_fontname() removed |
Use PDB gimp-text-fontname |
gimp-blend removed |
Use GEGL gegl:linear-gradient / gegl:radial-gradient |
GimpDoubleArray TypeError in curves |
Use drawable.curves_spline() directly |
Gimp.fonts_get_list() returns Font objects |
Convert via .get_name() before JSON serialization |
image.select_none() removed |
Use PDB gimp-selection-none |
layer.get_pixel() returns Gegl.Color |
Use .get_rgba() to extract float components |
Troubleshooting
"Could not connect to GIMP"
- GIMP must be running with an image open
- Start the MCP server: Tools > MCP > Start MCP Server, or enable autostart in Tools > MCP > MCP Server Settings...
- If you changed the port in GIMP, set
GIMP_MCP_PORTto the same value in your MCP client config - Check port 9877 (or your custom port) is not blocked by firewall
"GIMP did not reply within 300 s"
- The command took longer than the MCP server waits. Raise
GIMP_MCP_TIMEOUT(seconds) in your MCP client config; see Timeout for long commands - GIMP may still be running the command: check the image before retrying
Plugin Not Visible in GIMP
- Look under Tools > MCP (the plugin adds an
MCPsubmenu, not a top-levelToolsentry) - Confirm the plugin file is in the correct directory:
uvx gimp-mcp-plugin@latest install-plugin --dry-runshows where it goes - Upgraded GIMP recently? A minor upgrade (e.g. 3.0 → 3.2) moves the per-user config folder to a new version directory; re-run
uvx gimp-mcp-plugin@latest install-plugin(use--dry-runto see which folder it picks). Verify the active path via Edit > Preferences > Folders > Plug-ins. - On Linux/macOS: ensure the file has execute permission (
chmod +x) - Restart GIMP after installation
- Check Filters > Script-Fu > Console for error messages
Tests Failing
Run the test suite and check the failure list:
python run_tests.py
Each failure includes the tool name and error — most issues on GIMP 3.2 are covered by the fixes above.
Example Output
"Draw me a face and a sheep" — generated entirely through natural language via GIMP MCP
Future Enhancements
- 📚 Recipe Collection: Reusable workflow templates (portrait cleanup, product photo, etc.)
- 🚀 Dynamic Discovery: Auto-generate MCP tools from GIMP's full PDB procedure database
- 🔒 Security: Sandboxed execution for untrusted command inputs
- ⚡ Performance: Optimized bitmap transfer for large images
- 🌐 Remote Access: Network-accessible GIMP instances
Contributing
Contributions are welcome — bug fixes, new tools, documentation, or example scripts. Open a PR or issue on GitHub.
Development Setup
Install dev dependencies and activate the pre-commit hook so ruff runs on every commit:
uv sync
uv run pre-commit install
After this, ruff checks staged files on each git commit (with --fix applied automatically). The same check runs in CI, so the hook is just a fast local safety net.
To bump the pinned hook versions later:
uv run pre-commit autoupdate
License
GPL-3.0-or-later. See LICENSE.
Metadata
Release files for gimp-mcp-plugin 0.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| gimp_mcp_plugin-0.3.0.tar.gz | 107.7 kB | With provenance | Details for gimp_mcp_plugin-0.3.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| gimp_mcp_plugin-0.3.0-py3-none-any.whl | Python 3 | none | any | Details for gimp_mcp_plugin-0.3.0-py3-none-any.whl |
Total release size: 194.5 kB
Release files / gimp_mcp_plugin-0.3.0.tar.gz
| Download URL | gimp_mcp_plugin-0.3.0.tar.gz |
|---|---|
| Size | 107.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
bccc46a3e9bb7cd37708ec45dd55b33ff8458520a7223712fd3b91d406da0a2e
|
|
BLAKE2b-256 checksum How to use checksums |
e14f23b58928022df65f222644a4ad625e5ac5e0a96f1e81e1efd7bc9d97be09
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 12, 2026.
Transparency logRelease files / gimp_mcp_plugin-0.3.0-py3-none-any.whl
| Download URL | gimp_mcp_plugin-0.3.0-py3-none-any.whl |
|---|---|
| Size | 86.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
7cd48b09098890ffb3d84769178f8a83f29ab1a24930666f015bd064e65955c6
|
|
BLAKE2b-256 checksum How to use checksums |
f7e3c8ca9575839e0434c09cd02849825f3ad92b1b3de758bbf522e6a9c71aa5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 12, 2026.
Transparency logSecurity for gimp-mcp-plugin 0.3.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
Both files in this release have been uploaded with provenance metadata.
Attestation for gimp_mcp_plugin-0.3.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 12, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.