# GIMP 3 MCP (pypi · gimp3-mcp)

Let AI assistants paint, edit and export images in a running GIMP 3, with 80 tools.

- Trust score: 65/100 (medium)
- Registry status: active
- Liveness: live
- Owner verified: no
- Last scored: 2026-09-21

## Components

- pypi · `gimp3-mcp`: 65/100 (this document), [markdown](https://verifymcp.io/servers/tifyr-gimp3-mcp/gimp3-mcp.md), [page](https://verifymcp.io/servers/tifyr-gimp3-mcp/gimp3-mcp)

## Channel facts

- Registry: `pypi`
- Package: `gimp3-mcp`
- Version: `0.2.0`
- Transport: `stdio`

## Trust breakdown

How this component scores in each security and reliability category. Every signal is checked automatically from public evidence about the published package, including repeated runs of it in an isolated sandbox, and we only credit what we can confirm. Scores are 0–100 per category. Scoring method: https://verifymcp.io/docs/scoring (what has changed: https://verifymcp.io/docs/scoring/changelog)

Scored 2026-09-21.

- **Supply Chain Security**: 100/100
  - No malware found by supply-chain analysis.
  - No known CVEs affecting this package version or its production dependencies.
  - Runs hatchling.build at install time, a recognised native-build step with no shell scripting around it.
  - 0 of 29 dependencies flagged as unhealthy.
- **Provenance & Transparency**: 32/100
  - Source repository is publicly reachable at the declared URL.
  - Provenance check failed: no build-provenance attestation is published.
  - License check failed: no license is declared.
  - Actively maintained (last published 4 days ago).
  - Disclosure check failed: no security disclosure policy was found in the source repository.
- **Schema Quality & AI Usability**: 79/100
  - 100% of prompts and resources have a non-trivial description (not blank, and not just the item's name).
  - AI-judged instruction clarity (excellent).
  - Context-footprint check failed: tool/resource definitions use about 13732 tokens (~171/item across 80 items; 80 tools + 0 resources), over budget; trim descriptions and params.
  - Usage-examples check failed: none of the tools include examples.
- **Stability & Change Management**: 0/100
  - Stability not yet verified: not enough scan history yet (needs a 30-day window).
- **Tool Coverage**: 71/100
  - 100% of tools have a non-trivial description (not blank, and not just the tool's name).
  - 0% of tool parameters carry a description.
  - Structured output schemas are declared (1% of tools); any adoption earns full credit.
- **Tool Safety**: 75/100
  - No prompt-injection markers were found in the server instructions, tool names or descriptions we captured.
  - 0 of 5 tool(s) whose name or description implies an irreversible operation declare an MCP destructiveHint annotation; "restart_server" implies "drop" and declares no destructiveHint at all, which the MCP spec reads as destructive by default.
  - An AI judge read all 81 captured unit(s) of tool text and found none that tries to manipulate the model reading it.
- **Capabilities**: 100/100
  - Implements a supported MCP spec version (2025-11-25); the latest is 2026-07-28.

**Unverified: 1 category.** A category scored 0 because we could not verify it: a data source with nothing on this package, evidence we could not reach, or a check we could not run. We only credit what we can confirm.

## Install

### How do I install the GIMP 3 MCP server?

GIMP 3 MCP runs locally as a PyPI package, launched with uvx gimp3-mcp. Ready-made configuration for Claude, Cursor, VS Code, Codex and 5 more is on this page, copied from each client's own documentation.

### Claude

```bash
claude mcp add tifyr-gimp3-mcp -- uvx gimp3-mcp
```

### Cursor

```json
{
  "mcpServers": {
    "tifyr-gimp3-mcp": {
      "command": "uvx",
      "args": [
        "gimp3-mcp"
      ]
    }
  }
}
```

### VS Code

```json
{
  "servers": {
    "tifyr-gimp3-mcp": {
      "command": "uvx",
      "args": [
        "gimp3-mcp"
      ]
    }
  }
}
```

### Codex

```bash
codex mcp add tifyr-gimp3-mcp -- uvx gimp3-mcp
```

### opencode

```json
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "tifyr-gimp3-mcp": {
      "type": "local",
      "command": [
        "uvx",
        "gimp3-mcp"
      ],
      "enabled": true
    }
  }
}
```

### OpenClaw

```bash
openclaw mcp add tifyr-gimp3-mcp --command uvx --arg gimp3-mcp
```

### Hermes

```yaml
mcp_servers:
  tifyr-gimp3-mcp:
    command: "uvx"
    args: ["gimp3-mcp"]
```

### Netclaw

```json
{
  "McpServers": {
    "tifyr-gimp3-mcp": {
      "Transport": "stdio",
      "Command": "uvx",
      "Arguments": [
        "gimp3-mcp"
      ]
    }
  }
}
```

### Vellum

```bash
assistant mcp add tifyr-gimp3-mcp -t stdio -c uvx -a gimp3-mcp
```

### Other

```json
{
  "mcpServers": {
    "tifyr-gimp3-mcp": {
      "command": "uvx",
      "args": [
        "gimp3-mcp"
      ]
    }
  }
}
```

## Changelog

Every change recorded for this component, newest first. Days that predate change tracking, or that we cannot explain, say so: "we were watching and nothing happened" and "we were not watching" are different claims.

### 2026-09-17 (score 65, +15)

- [security improvement] Malware scan: unverified → pass

### 2026-09-16 (score 50)

First indexed and scored.

## MCP tools (80)

### `check_server` (~89 tokens)

Check whether the GIMP MCP plugin socket is reachable and responding.

Returns a status dict:
\- connected: bool
\- host / port: where it tried
\- gimp_version: if connected successfully
\- error: description if not connected

Use this before any other operation to verify the GIMP plugin is running.
If not connected, open GIMP and run Tools > MCP > Start MCP Server.

### `restart_server` (~72 tokens)

Drop and re-establish the connection to the GIMP MCP plugin.

Use this when:
\- GIMP was restarted after the MCP client was already running
\- The socket connection dropped mid-session
\- check_server() shows not connected but GIMP is open

Returns the new connection status (same format as check_server).

### `new_canvas` (~313 tokens)

Create a new blank canvas in GIMP and open it in a display window.

Parameters:
\- width: Canvas width in pixels
\- height: Canvas height in pixels
\- name: Image name reported by list_images, also used for the background layer
  (default: "Untitled")
\- color_mode: "RGB" (default), "RGBA", "GRAY", "GRAYA"
\- fill: Background: "white" (default), "transparent", or a color as hex "#rrggbb" or a basic name (black, white, gray, silver, red, maroon, yellow,
  olive, lime, green, aqua, teal, blue, navy, fuchsia, purple)
\- resolution: DPI resolution (default: 72)

Returns:
\- image_id: internal GIMP image ID
\- name: the image name
\- width / height: confirmed dimensions
\- color_mode: confirmed mode
\- display_opened: whether a GIMP window was opened

Examples:
\- new_canvas(1024, 1024) — white 1024x1024 RGB canvas
\- new_canvas(1920, 1080, name="Background", fill="black")
\- new_canvas(512, 512, color_mode="RGBA", fill="transparent")

Input parameters:

- `color_mode` (string)
- `fill` (string)
- `height` (integer, required)
- `name` (string)
- `resolution` (integer)
- `width` (integer, required)

### `get_image_bitmap` (~366 tokens)

Get an open image in GIMP as an Image object with optional scaling and region selection.

Renders the image data (all visible layers), independent of GIMP's zoom or scroll.
No size restrictions — pass any max_width/max_height you need.
For large images, omit max_width/max_height to get the full resolution.

Supports two main use cases:
1\. Full image with optional scaling (pass max_width/max_height)
2\. Region extraction with optional scaling (pass region dict)

Parameters:
\- max_width, max_height: Box to scale the image into, preserving aspect ratio
  (smaller images are enlarged). Omit for full resolution.
\- region: Dictionary with keys (image pixel coordinates, integers):
    - origin_x, origin_y: Top-left corner of region to extract
    - width, height: Dimensions of region to extract
    - max_width, max_height: Optional box to scale the region into (small regions are enlarged)
    Other keys (such as x/y) are rejected.
\- image_index: Which open image to render (default 0 = most recently opened;
  see list_images)

Examples:
\- Full image at full res: get_image_bitmap()
\- Full image scaled: get_image_bitmap(max_width=2048, max_height=2048)
\- Region: get_image_bitmap(region={"origin_x": 0, "origin_y": 0, "width": 512, "height": 512})

get_state_snapshot is a shorter way to ask for the same image.

Returns: the image as PNG. Fails if no image is open, the region is invalid, or export fails.

Input parameters:

- `image_index` (integer)
- `max_height`
- `max_width`
- `region`

### `get_image_metadata` (~147 tokens)

Get metadata about an open image in GIMP without the bitmap data.

Parameters:
\- image_index: Which open image to describe (default 0 = most recently opened; see list_images)

Returns detailed information about the image including:
\- Image dimensions (width, height)
\- Color mode and base type
\- Number of layers and channels
\- File information if available
\- Layer structure and properties

This is much faster than get_image_bitmap() since it doesn't export the actual image data.
Perfect for when you only need to know image properties for decision making.

Returns:
\- Dictionary containing comprehensive image metadata
\- Raises exception if no images are open

Input parameters:

- `image_index` (integer)

### `get_gimp_info` (~111 tokens)

Get comprehensive information about the GIMP installation and environment.

Returns detailed information about GIMP that AI assistants need to understand
the current environment, including:
\- GIMP version and build information
\- Installation paths and directories
\- Available plugins and procedures
\- System configuration
\- Runtime environment details

This information helps AI assistants provide better support and troubleshooting
by understanding the specific GIMP setup they're working with.

Returns:
\- Dictionary containing comprehensive GIMP environment information
\- Raises exception if GIMP connection fails

### `get_state_snapshot` (~343 tokens)

Return a live visual snapshot of the current image state — no file save needed.

A shortcut for get_image_bitmap with a single max_size and x/y region keys.

AI agents call this to get immediate visual feedback after any edit operation,
letting them verify results and decide next steps without saving to disk.

Parameters:
\- image_index: Which open image to snapshot (default: 0 = most recent)
\- max_size: Longest side of the returned PNG in pixels (default: 512). The image or
  region is scaled to fit, so small regions are enlarged: positions in the snapshot
  are not image coordinates (multiply by region width / snapshot width).
\- region: Optional dict {x, y, width, height} in image pixels to zoom into an area
          e.g. {"x": 200, "y": 300, "width": 100, "height": 80} for mouth area
\- label: Optional annotation label (logged but not drawn — for agent bookkeeping)

Returns:
\- PNG image of the current GIMP canvas state (with alpha if present)

Typical agent workflow:
    1. open_image / new_canvas
    2. <edit operations>
    3. get_state_snapshot()          ← see result, decide next step
    4. <more edits>
    5. get_state_snapshot(region={"x":200,"y":300,"width":100,"height":80})
    6. export_image when satisfied

Input parameters:

- `image_index` (integer)
- `label` (string)
- `max_size` (integer)
- `region`

### `get_context_state` (~195 tokens)

Get the current GIMP context state (colors, brush, settings).

IMPORTANT: Context state can be changed by the user in GIMP UI at any time.
Check context state before operations that depend on specific settings.

Returns information about:
\- Foreground and background colors as sRGB hex ("#rrggbb", as tools accept) and alpha 0-1
\- Current brush and its properties
\- Opacity setting (0-100%)
\- Paint mode, named like set_layer_properties blend modes (e.g. "NORMAL")
\- Feather state and radius [x, y]
\- Antialiasing state

Use cases:
\- Verify colors before drawing operations
\- Check if feathering is enabled (avoid unwanted blurry edges)
\- Ensure correct opacity and blend mode
\- Detect if user changed settings in GIMP UI

Returns:
\- Dictionary containing current context state
\- Raises exception if unable to get context state

### `call_api` (~1229 tokens)

Call GIMP 3.2 API methods through PyGObject console.

GIMP MCP Protocol:
\- Use api_path="exec" to execute Python code in GIMP
\- args[0] should be "pyGObject-console" for executing commands
\- args[1] should be array of Python code strings to execute
\- Each array item runs as its own exec(): put a multi-line block (for/if/def)
  in ONE item with embedded newlines, not split across items
\- Only print() output is returned (one string per item); bare expressions are
  not echoed. To get values back, use args[0] = "pyGObject-eval" with a list of
  expressions, e.g. ["pyGObject-eval", ["len(Gimp.get_images())"]]
\- Commands execute in persistent context - imports and variables persist
\- Always call Gimp.displays_flush() after drawing operations

For image operations, use get_image_bitmap()
which return proper MCP Image objects that Claude can process directly.

GUIDANCE PROMPTS:
\- For common operations and best practices, invoke the 'gimp_best_practices' prompt
\- For complex multi-element drawings with layers, invoke the 'gimp_iterative_workflow' prompt

Optional Initialization Pattern:
["images = Gimp.get_images()", "image1 = images[0]",
 "layers = image1.get_layers()", "layer1 = layers[0]", "drawable1 = layer1"]

Common Operations:
\- Draw line: ["Gimp.pencil(drawable1, [0, 0, 200, 200])", "Gimp.displays_flush()"]
\- Set color: ["from gi.repository import Gegl", "red_color = Gegl.Color.new('red')", 
              "Gimp.context_set_foreground(red_color)"]
\- Draw ellipse: ["Gimp.Image.select_ellipse(image1, Gimp.ChannelOps.REPLACE, 100, 100, 30, 20)",
                 "Gimp.Drawable.edit_fill(drawable1, Gimp.FillType.FOREGROUND)",
                 "Gimp.Selection.none(image1)", "Gimp.displays_flush()"]
\- Paint curve: ["Gimp.paintbrush_default(drawable1, [50.0, 50.0, 150.0, 200.0, 250.0, 50.0, 350.0, 200.0])", 
                "Gimp.displays_flush()"]
\- Draw bezier curve: ["path = Gimp.Path.new(image1, 'my_bezier_path')", 
                      "image1.insert_path(path, None,…

Input parameters:

- `api_path` (string, required)
- `args`
- `kwargs`

Output parameters:

- `result` (string)

### `open_image` (~110 tokens)

Open an image file in GIMP and create a display window.

Parameters:
\- file_path: Absolute path to the image file to open (PNG, JPEG, TIFF, etc.)

Returns:
\- image_id: internal GIMP image ID
\- width / height: image dimensions in pixels
\- color_mode: RGB / Grayscale / Indexed
\- num_layers: number of layers in the image
\- display_opened: whether a GIMP display window was created

Input parameters:

- `file_path` (string, required)

### `save_xcf` (~102 tokens)

Save the current image as a GIMP XCF file (preserves all layers and metadata).

Parameters:
\- file_path: Absolute path for the output .xcf file
\- image_index: Index of the image to save (default 0 = most recently opened; see list_images)

Returns:
\- status: "success" or "error"
\- file_path: confirmed output path

Input parameters:

- `file_path` (string, required)
- `image_index` (integer)

### `export_image` (~163 tokens)

Export the current image to a raster file (PNG, JPEG, WEBP, TIFF).

Parameters:
\- file_path: Absolute path for the output file
\- format: Output format — "png" (default), "jpeg", "webp", "tiff"
\- quality: JPEG/WEBP quality 1-100 (default 90; ignored for PNG/TIFF)
\- flatten: Flatten all layers before export (default True)
\- image_index: Index of the image to export (default 0)

Returns:
\- status, file_path, format, file_size_bytes

Input parameters:

- `file_path` (string, required)
- `flatten` (boolean)
- `format` (string)
- `image_index` (integer)
- `quality` (integer)

### `batch_export` (~180 tokens)

Export all open images (or a specific one) to a directory.

Parameters:
\- output_dir: Directory to write exported files into
\- format: "png", "jpeg", "webp", "tiff" (default "png")
\- quality: JPEG/WEBP quality (default 90)
\- name_pattern: Filename template — use {name} for image name, {index} for position
\- image_index: If set, export only that image; omit to export all open images

Returns:
\- exported: list of {file_path, name, width, height}
\- count: number of files written
\- errors: list of any export errors

Input parameters:

- `format` (string)
- `image_index`
- `name_pattern` (string)
- `output_dir` (string, required)
- `quality` (integer)

### `auto_levels` (~74 tokens)

Automatically stretch the tonal range of an image (auto levels / auto stretch contrast).

Parameters:
\- image_index: Index of the target image (default 0)
\- layer_name: Name of the layer to adjust; defaults to active layer

Returns status dict.

Input parameters:

- `image_index` (integer)
- `layer_name`

### `adjust_curves` (~147 tokens)

Adjust tonal curves for a layer.

Parameters:
\- preset: Built-in curve shape — "s_curve" (default), "lighten", "darken", "contrast"
\- points: Custom control points as [[input, output], ...] override (overrides preset)
\- channel: "value" (all), "red", "green", "blue", "alpha"
\- image_index: Target image index (default 0)
\- layer_name: Layer to adjust; defaults to active layer

Returns status dict.

Input parameters:

- `channel` (string)
- `image_index` (integer)
- `layer_name`
- `points`
- `preset` (string)

### `adjust_brightness_contrast` (~104 tokens)

Adjust brightness and contrast of a layer.

Parameters:
\- brightness: -127 to +127 (default 0)
\- contrast: -127 to +127 (default 0)
\- image_index: Target image index (default 0)
\- layer_name: Layer to adjust; defaults to active layer

Returns status dict.

Input parameters:

- `brightness` (integer)
- `contrast` (integer)
- `image_index` (integer)
- `layer_name`

### `adjust_hue_saturation` (~177 tokens)

Adjust hue, saturation, and lightness of a layer.

Parameters:
\- hue: Hue rotation -180 to +180 (default 0)
\- saturation: Saturation shift -100 to +100 (default 0)
\- lightness: Lightness shift -100 to +100 (default 0)
\- color_range: "all", "red", "yellow", "green", "cyan", "blue", "magenta" (default "all")
\- image_index: Target image index (default 0)
\- layer_name: Layer to adjust; defaults to active layer

Returns status dict.

Input parameters:

- `color_range` (string)
- `hue` (number)
- `image_index` (integer)
- `layer_name`
- `lightness` (number)
- `saturation` (number)

### `adjust_color_balance` (~171 tokens)

Adjust color balance (shadows / midtones / highlights) of a layer.

Parameters:
\- cyan_red: -100 to +100 (negative = cyan, positive = red; default 0)
\- magenta_green: -100 to +100 (default 0)
\- yellow_blue: -100 to +100 (default 0)
\- range: "shadows", "midtones" (default), "highlights"
\- image_index: Target image index (default 0)
\- layer_name: Layer to adjust; defaults to active layer

Returns status dict.

Input parameters:

- `cyan_red` (number)
- `image_index` (integer)
- `layer_name`
- `magenta_green` (number)
- `range` (string)
- `yellow_blue` (number)

### `sharpen` (~131 tokens)

Sharpen a layer using unsharp mask.

Parameters:
\- amount: Sharpening strength 0-500 (default 50.0)
\- radius: Blur radius for the mask in pixels (default 3.0)
\- threshold: Minimum difference before sharpening is applied (default 0)
\- image_index: Target image index (default 0)
\- layer_name: Layer to sharpen; defaults to active layer

Returns status dict.

Input parameters:

- `amount` (number)
- `image_index` (integer)
- `layer_name`
- `radius` (number)
- `threshold` (integer)

### `blur` (~124 tokens)

Apply Gaussian blur to a layer.

Same as apply_gaussian_blur, but with separate horizontal and vertical radii.

Parameters:
\- radius_x: Horizontal blur radius in pixels (default 5.0)
\- radius_y: Vertical blur radius in pixels (default 5.0)
\- image_index: Target image index (default 0)
\- layer_name: Layer to blur; defaults to active layer

Returns status dict.

Input parameters:

- `image_index` (integer)
- `layer_name`
- `radius_x` (number)
- `radius_y` (number)

### `denoise` (~88 tokens)

Reduce noise in a layer using GEGL noise-reduction.

Parameters:
\- strength: Noise reduction strength 0-100 (default 50)
\- image_index: Target image index (default 0)
\- layer_name: Layer to denoise; defaults to active layer

Returns status dict.

Input parameters:

- `image_index` (integer)
- `layer_name`
- `strength` (integer)

### `desaturate` (~99 tokens)

Convert a layer to grayscale (desaturate).

Parameters:
\- mode: Desaturation algorithm — "luminosity" (default), "luma", "average", "lightness"
\- image_index: Target image index (default 0)
\- layer_name: Layer to desaturate; defaults to active layer

Returns status dict.

Input parameters:

- `image_index` (integer)
- `layer_name`
- `mode` (string)

### `invert_colors` (~65 tokens)

Invert all colors in a layer (create a negative).

Parameters:
\- image_index: Target image index (default 0)
\- layer_name: Layer to invert; defaults to active layer

Returns status dict.

Input parameters:

- `image_index` (integer)
- `layer_name`

### `scale_image` (~100 tokens)

Scale an image to exact pixel dimensions.

Parameters:
\- width: Target width in pixels
\- height: Target height in pixels
\- interpolation: "cubic" (default), "linear", "none"
\- image_index: Target image index (default 0)

Returns: {status, width, height}

Input parameters:

- `height` (integer, required)
- `image_index` (integer)
- `interpolation` (string)
- `width` (integer, required)

### `scale_to_fit` (~119 tokens)

Scale an image to fit within a bounding box, preserving aspect ratio.

Parameters:
\- max_width: Maximum allowed width in pixels
\- max_height: Maximum allowed height in pixels
\- interpolation: "cubic" (default), "linear", "none"
\- image_index: Target image index (default 0)

Returns: {status, width, height} — final dimensions after scaling

Input parameters:

- `image_index` (integer)
- `interpolation` (string)
- `max_height` (integer, required)
- `max_width` (integer, required)

### `crop_to_selection` (~87 tokens)

Crop the image canvas to the current selection bounds.

Parameters:
\- autocrop: If True, auto-detect crop bounds instead of using selection (default False)
\- image_index: Target image index (default 0)

Returns: {status, x, y, width, height} — crop region applied

Input parameters:

- `autocrop` (boolean)
- `image_index` (integer)

### `crop_to_rect` (~105 tokens)

Crop the image canvas to an explicit rectangle.

Parameters:
\- x, y: Top-left corner of the crop rectangle
\- width, height: Dimensions of the crop rectangle
\- image_index: Target image index (default 0)

Returns: {status, x, y, width, height}

Input parameters:

- `height` (integer, required)
- `image_index` (integer)
- `width` (integer, required)
- `x` (integer, required)
- `y` (integer, required)

### `rotate_image` (~90 tokens)

Rotate the entire image.

Parameters:
\- angle: Rotation in degrees — 90, 180, 270 use lossless GIMP rotation;
         other values rotate all layers about the center with interpolation,
         enlarge the canvas to fit, and flatten
\- image_index: Target image index (default 0)

Returns status dict.

Input parameters:

- `angle` (number, required)
- `image_index` (integer)

### `flip_image` (~62 tokens)

Flip the entire image horizontally or vertically.

Parameters:
\- direction: "horizontal" (default) or "vertical"
\- image_index: Target image index (default 0)

Returns status dict.

Input parameters:

- `direction` (string)
- `image_index` (integer)

### `resize_canvas` (~235 tokens)

Resize the image canvas without scaling the content.

Parameters:
\- width, height: New canvas dimensions in pixels
\- anchor: Position of existing content — "center" (default), "top-left", "top",
          "top-right", "left", "right", "bottom-left", "bottom", "bottom-right"
\- fill: New canvas areas: "transparent" (default) or a color as hex "#rrggbb" or a basic name (black, white, gray, silver, red, maroon, yellow,
  olive, lime, green, aqua, teal, blue, navy, fuchsia, purple). A color is painted on a new
  bottom layer named "Canvas fill"; existing layers and the selection are left as they are
\- image_index: Target image index (default 0)

Returns: {status, width, height, offset_x, offset_y, fill_layer (its name, or null)}

Input parameters:

- `anchor` (string)
- `fill` (string)
- `height` (integer, required)
- `image_index` (integer)
- `width` (integer, required)

### `select_rectangle` (~137 tokens)

Create a rectangular selection.

Parameters:
\- x, y: Top-left corner of the selection
\- width, height: Dimensions of the selection
\- operation: "replace" (default), "add", "subtract", "intersect"
\- feather: Feather radius in pixels (default 0 = no feather)
\- image_index: Target image index (default 0)

Returns status dict.

Input parameters:

- `feather` (number)
- `height` (integer, required)
- `image_index` (integer)
- `operation` (string)
- `width` (integer, required)
- `x` (integer, required)
- `y` (integer, required)

### `select_ellipse` (~135 tokens)

Create an elliptical selection.

Parameters:
\- x, y: Top-left corner of the bounding box
\- width, height: Bounding box dimensions
\- operation: "replace" (default), "add", "subtract", "intersect"
\- feather: Feather radius in pixels (default 0)
\- image_index: Target image index (default 0)

Returns status dict.

Input parameters:

- `feather` (number)
- `height` (integer, required)
- `image_index` (integer)
- `operation` (string)
- `width` (integer, required)
- `x` (integer, required)
- `y` (integer, required)

### `select_by_color` (~168 tokens)

Select regions by color similarity.

Parameters:
\- color: Target color as hex "#rrggbb" or a basic name (black, white, gray, silver, red, maroon, yellow,
  olive, lime, green, aqua, teal, blue, navy, fuchsia, purple)
\- threshold: Color similarity tolerance 0-255 (default 15)
\- operation: "replace" (default), "add", "subtract", "intersect"
\- image_index: Target image index (default 0)
\- layer_name: Layer to sample from; defaults to active layer

Returns status dict.

Input parameters:

- `color` (string, required)
- `image_index` (integer)
- `layer_name`
- `operation` (string)
- `threshold` (integer)

### `select_all` (~40 tokens)

Select the entire image canvas.

Parameters:
\- image_index: Target image index (default 0)

Returns status dict.

Input parameters:

- `image_index` (integer)

### `select_none` (~41 tokens)

Remove / deselect all selections.

Parameters:
\- image_index: Target image index (default 0)

Returns status dict.

Input parameters:

- `image_index` (integer)

### `invert_selection` (~46 tokens)

Invert the current selection (select what is not selected).

Parameters:
\- image_index: Target image index (default 0)

Returns status dict.

Input parameters:

- `image_index` (integer)

### `modify_selection` (~103 tokens)

Grow, shrink, feather, border, or sharpen the current selection.

Parameters:
\- operation: "grow", "shrink", "feather", "border", "sharpen"
\- amount: Pixel radius for grow/shrink/feather/border; ignored for sharpen
\- image_index: Target image index (default 0)

Returns status dict.

Input parameters:

- `amount` (number, required)
- `image_index` (integer)
- `operation` (string, required)

### `create_layer` (~293 tokens)

Create and insert a new layer into an image.

Parameters:
\- name: Layer name (default "New Layer")
\- width, height: Layer dimensions; defaults to image dimensions
\- fill: "transparent" (default) or a color as hex "#rrggbb" or a basic name (black, white, gray, silver, red, maroon, yellow,
  olive, lime, green, aqua, teal, blue, navy, fuchsia, purple)
\- opacity: Layer opacity 0-100 (default 100)
\- blend_mode: NORMAL (default), MULTIPLY, SCREEN, OVERLAY, DARKEN, LIGHTEN, DODGE,
  BURN, HARD_LIGHT, SOFT_LIGHT, DIFFERENCE, HUE, SATURATION, COLOR, LUMINOSITY or
  DISSOLVE (case-insensitive; other names are rejected)
\- position: Stack index, 0 = top of the stack; -1 (default) = directly above the active layer
\- image_index: Target image index (default 0)

Returns: {layer_name, layer_id, width, height, position}

Input parameters:

- `blend_mode` (string)
- `fill` (string)
- `height`
- `image_index` (integer)
- `name` (string)
- `opacity` (number)
- `position` (integer)
- `width`

### `duplicate_layer` (~71 tokens)

Duplicate a layer and insert the copy above it.

Parameters:
\- layer_name: Name of the layer to duplicate; defaults to active layer
\- image_index: Target image index (default 0)

Returns: {layer_name, layer_id}

Input parameters:

- `image_index` (integer)
- `layer_name`

### `delete_layer` (~95 tokens)

Delete a layer from an image.

Parameters:
\- layer_name: Name of the layer to delete
\- layer_index: Position index of the layer (alternative to layer_name)
\- image_index: Target image index (default 0)

Provide either layer_name or layer_index. Defaults to active layer if neither given.

Returns status dict.

Input parameters:

- `image_index` (integer)
- `layer_index`
- `layer_name`

### `rename_layer` (~96 tokens)

Rename a layer.

Parameters:
\- new_name: New name for the layer
\- old_name: Current name of the layer to rename
\- layer_index: Position index alternative to old_name
\- image_index: Target image index (default 0)

Returns: {old_name, new_name}

Input parameters:

- `image_index` (integer)
- `layer_index`
- `new_name` (string, required)
- `old_name`

### `set_layer_properties` (~192 tokens)

Set properties on an existing layer.

Parameters:
\- layer_name / layer_index: Identify the layer (defaults to active layer)
\- opacity: New opacity 0-100 (omit to leave unchanged)
\- blend_mode: Omit to leave unchanged, or one of NORMAL (default), MULTIPLY, SCREEN, OVERLAY, DARKEN, LIGHTEN, DODGE,
  BURN, HARD_LIGHT, SOFT_LIGHT, DIFFERENCE, HUE, SATURATION, COLOR, LUMINOSITY or
  DISSOLVE (case-insensitive; other names are rejected)
\- visible: True/False visibility (omit to leave unchanged)
\- image_index: Target image index (default 0)

Returns status dict.

Input parameters:

- `blend_mode`
- `image_index` (integer)
- `layer_index`
- `layer_name`
- `opacity`
- `visible`

### `reorder_layer` (~98 tokens)

Move a layer to a new stack position.

Parameters:
\- new_position: Target stack index, 0 = top (same order as list_layers)
\- layer_name / layer_index: Identify the layer (defaults to active layer)
\- image_index: Target image index (default 0)

Returns status dict.

Input parameters:

- `image_index` (integer)
- `layer_index`
- `layer_name`
- `new_position` (integer, required)

### `flatten_image` (~43 tokens)

Flatten all layers into a single background layer.

Parameters:
\- image_index: Target image index (default 0)

Returns status dict.

Input parameters:

- `image_index` (integer)

### `merge_visible_layers` (~49 tokens)

Merge all visible layers into a single layer.

Parameters:
\- image_index: Target image index (default 0)

Returns: {layer_name, layer_id}

Input parameters:

- `image_index` (integer)

### `list_layers` (~117 tokens)

List all layers in an image with their properties.

Parameters:
\- image_index: Target image index (default 0)

Returns: {layers: [{index, name, id, visible, opacity, blend_mode, width, height,
          has_alpha, offsets, active}], count}. Index 0 is the top layer; active marks the
layer that tools use when layer_name is omitted. blend_mode uses set_layer_properties
names (e.g. "NORMAL"); offsets is [x, y].

Input parameters:

- `image_index` (integer)

### `fill_layer` (~121 tokens)

Fill an entire layer with a solid color.

Parameters:
\- color: Fill color as hex "#rrggbb" or a basic name (black, white, gray, silver, red, maroon, yellow,
  olive, lime, green, aqua, teal, blue, navy, fuchsia, purple)
\- layer_name: Layer to fill; defaults to active layer
\- image_index: Target image index (default 0)

Returns status dict.

Input parameters:

- `color` (string, required)
- `image_index` (integer)
- `layer_name`

### `fill_selection` (~181 tokens)

Fill the current selection with a color or fill type.

Parameters:
\- color: Fill color as hex "#rrggbb" or a basic name (black, white, gray, silver, red, maroon, yellow,
  olive, lime, green, aqua, teal, blue, navy, fuchsia, purple) (used when fill_type is omitted)
\- fill_type: Instead of color: "foreground" or "background" (GIMP's current colors, see
  set_colors), "pattern", or "transparent" (clears the selection). Give color or fill_type.
\- image_index: Target image index (default 0)
\- layer_name: Target layer; defaults to active layer

Returns status dict.

Input parameters:

- `color`
- `fill_type`
- `image_index` (integer)
- `layer_name`

### `set_colors` (~113 tokens)

Set the GIMP foreground and/or background color.

Parameters:
\- foreground: New foreground color as hex "#rrggbb" or a basic name (black, white, gray, silver, red, maroon, yellow,
  olive, lime, green, aqua, teal, blue, navy, fuchsia, purple); omit to leave unchanged
\- background: New background color, same formats; omit to leave unchanged

Returns: {foreground, background} confirmation dict.

Input parameters:

- `background`
- `foreground`

### `draw_line` (~225 tokens)

Draw a straight line on a layer.

Parameters:
\- x1, y1: Start point
\- x2, y2: End point
\- color: Stroke color as hex "#rrggbb" or a basic name (black, white, gray, silver, red, maroon, yellow,
  olive, lime, green, aqua, teal, blue, navy, fuchsia, purple); uses current foreground if omitted
\- width: Stroke width in pixels (default 2.0)
\- tool: "pencil" (default, hard edge) or "paintbrush" (soft edge)
\- layer_name: Target layer; defaults to active layer
\- image_index: Target image index (default 0)

Returns status dict.

Input parameters:

- `color`
- `image_index` (integer)
- `layer_name`
- `tool` (string)
- `width` (number)
- `x1` (number, required)
- `x2` (number, required)
- `y1` (number, required)
- `y2` (number, required)

### `draw_rectangle` (~195 tokens)

Draw a rectangle outline (stroke only) on a layer.

Parameters:
\- x, y: Top-left corner
\- width, height: Rectangle dimensions
\- color: Stroke color as hex "#rrggbb" or a basic name (black, white, gray, silver, red, maroon, yellow,
  olive, lime, green, aqua, teal, blue, navy, fuchsia, purple); uses current foreground if omitted
\- line_width: Stroke width in pixels (default 2.0)
\- layer_name: Target layer; defaults to active layer
\- image_index: Target image index (default 0)

Returns status dict.

Input parameters:

- `color`
- `height` (integer, required)
- `image_index` (integer)
- `layer_name`
- `line_width` (number)
- `width` (integer, required)
- `x` (integer, required)
- `y` (integer, required)

### `draw_ellipse` (~201 tokens)

Draw an ellipse outline (stroke only) on a layer.

Parameters:
\- x, y: Top-left corner of the bounding box
\- width, height: Bounding box dimensions
\- color: Stroke color as hex "#rrggbb" or a basic name (black, white, gray, silver, red, maroon, yellow,
  olive, lime, green, aqua, teal, blue, navy, fuchsia, purple); uses current foreground if omitted
\- line_width: Stroke width in pixels (default 2.0)
\- layer_name: Target layer; defaults to active layer
\- image_index: Target image index (default 0)

Returns status dict.

Input parameters:

- `color`
- `height` (integer, required)
- `image_index` (integer)
- `layer_name`
- `line_width` (number)
- `width` (integer, required)
- `x` (integer, required)
- `y` (integer, required)

### `fill_rectangle` (~165 tokens)

Fill a rectangular region with a solid color.

Parameters:
\- x, y: Top-left corner
\- width, height: Rectangle dimensions
\- color: Fill color as hex "#rrggbb" or a basic name (black, white, gray, silver, red, maroon, yellow,
  olive, lime, green, aqua, teal, blue, navy, fuchsia, purple)
\- layer_name: Target layer; defaults to active layer
\- image_index: Target image index (default 0)

Returns status dict.

Input parameters:

- `color` (string, required)
- `height` (integer, required)
- `image_index` (integer)
- `layer_name`
- `width` (integer, required)
- `x` (integer, required)
- `y` (integer, required)

### `fill_ellipse` (~171 tokens)

Fill an elliptical region with a solid color.

Parameters:
\- x, y: Top-left corner of the bounding box
\- width, height: Bounding box dimensions
\- color: Fill color as hex "#rrggbb" or a basic name (black, white, gray, silver, red, maroon, yellow,
  olive, lime, green, aqua, teal, blue, navy, fuchsia, purple)
\- layer_name: Target layer; defaults to active layer
\- image_index: Target image index (default 0)

Returns status dict.

Input parameters:

- `color` (string, required)
- `height` (integer, required)
- `image_index` (integer)
- `layer_name`
- `width` (integer, required)
- `x` (integer, required)
- `y` (integer, required)

### `gradient_fill` (~266 tokens)

Fill a layer or selection with a gradient.

With an active selection, only the selected part of the layer is filled.

Parameters:
\- color1: Start color as hex "#rrggbb" or a basic name (black, white, gray, silver, red, maroon, yellow,
  olive, lime, green, aqua, teal, blue, navy, fuchsia, purple); default "black"
\- color2: End color, same formats; default "white"
\- x1, y1: Gradient start point in image pixels (default 0, 0)
\- x2, y2: Gradient end point in image pixels (default: the image's bottom-right corner);
  must differ from the start point
\- gradient_type: "linear" (default) or "radial"
\- layer_name: Target layer; defaults to active layer
\- image_index: Target image index (default 0)

Returns status dict.

Input parameters:

- `color1` (string)
- `color2` (string)
- `gradient_type` (string)
- `image_index` (integer)
- `layer_name`
- `x1` (number)
- `x2`
- `y1` (number)
- `y2`

### `paint_stroke` (~889 tokens)

Paint a batch of brush strokes, working in rounds like a painter.

Paints on an open image. To start a new painting, first call
new_canvas(width, height) (white by default), or open a file with open_image.

Paint a few strokes (typically 3-30), look at the result (preview=True or
get_state_snapshot), then paint the next batch. All strokes in one call
land on one layer and form a single undo step in GIMP's own history.
To be able to discard a round, paint it on a new layer (create_layer)
and remove it with delete_layer. Every stroke is validated before
anything is painted.

Parameters:
\- strokes: 1-50 stroke objects. Only "points" is required:
    - points: [[x, y], ...] in image pixels, 1-2000 points (one point paints a dab).
      3-12 points are enough for a curve.
    - tool: "paintbrush" (default), "pencil" (hard edge), "airbrush", "eraser", "smudge"
    - brush: Brush name from list_brushes (default "2. Hardness 050")
    - size: Brush size in pixels, 1-10000 (default 20)
    - color: Hex "#rrggbb", "#rgb" or "#rrggbbaa", or a basic name like "white"
      (default: current foreground). rgb() and other names are rejected.
      Ignored by eraser and smudge.
    - opacity: 0-100 (default 100)
    - hardness: 0-1 (default: the brush's own)
    - angle: -180 to 180 degrees (default 0); aspect_ratio: -20 to 20 (default 0)
    - spacing: Distance between dabs as a fraction of brush size, 0.01-50 (default: the brush's own)
    - pressure: "taper" (default; thin ends like a real stroke), "none" (even width),
      or a list of 0-1 values spread evenly along the stroke, e.g. [0.2, 1, 0.5]
      (paintbrush, pencil and airbrush only)
    - taper_affects: "size" (default) or "opacity" (ends fade instead of thinning)
    - smooth: true (default) turns the points into a smooth curve; false draws straight segments
    - mode: Blend mode, e.g. "normal" (default), "multiply", "screen", "overlay", "soft_light"
    - strength: 0-100 (default 50) for airbrush and smudge; applie…

Input parameters:

- `image_index` (integer)
- `layer_name`
- `preview` (boolean)
- `preview_max_size` (integer)
- `strokes` (array, required)

### `list_brushes` (~164 tokens)

List brushes available to paint_stroke.

Parameters:
\- filter: Optional regular expression matched against brush names, e.g. "Oils|Bristles"

Brushes that paint well: "2. Hardness 025" to "100" (plain round), "Acrylic 01"/"03"
(dry, textured), "Bristles 01" to "03" (streaky), "Oils 01" to "03" (soft blending),
"Charcoal 01"/"Chalk 01" (grainy), "Pencil 02" (sketchy line), "Sponge 01" (soft texture).

Returns: {brushes: [name, ...], count}

Input parameters:

- `filter`

### `sample_color` (~197 tokens)

Pick a color from the canvas, like a painter's eyedropper.

Same as get_pixel_color, plus optional averaging over a radius.

Parameters:
\- x, y: Image coordinates in pixels
\- radius: Average the color over this many pixels around the point (default 0 = one pixel)
\- sample_merged: true (default) samples what is visible across all layers; false samples one layer
\- layer_name: Layer to sample when sample_merged is false; defaults to the active layer
\- image_index: Target image index (default 0)

Returns: {color_hex: "#rrggbb" (sRGB, usable as a paint_stroke color), alpha: 0-1}

Input parameters:

- `image_index` (integer)
- `layer_name`
- `radius` (number)
- `sample_merged` (boolean)
- `x` (number, required)
- `y` (number, required)

### `add_text` (~215 tokens)

Add a text layer to an image.

Parameters:
\- text: The text string to render
\- x, y: Position of the text layer's top-left corner (default 0, 0)
\- font: Font family name — "Sans" (default), "Serif", etc.
\- size: Font size in pixels (default 24)
\- color: Text color as hex "#rrggbb" or a basic name (black, white, gray, silver, red, maroon, yellow,
  olive, lime, green, aqua, teal, blue, navy, fuchsia, purple); default "black"
\- image_index: Target image index (default 0)

Returns: {layer_name, layer_id, text_width, text_height, position}

Input parameters:

- `color` (string)
- `font` (string)
- `image_index` (integer)
- `size` (integer)
- `text` (string, required)
- `x` (integer)
- `y` (integer)

### `edit_text` (~228 tokens)

Edit an existing text layer's content or formatting.

Parameters:
\- layer_name: Name of the text layer to edit
\- text: New text content (omit to leave unchanged)
\- font: New font family (omit to leave unchanged)
\- size: New font size in pixels (omit to leave unchanged)
\- color: New text color as hex "#rrggbb" or a basic name (black, white, gray, silver, red, maroon, yellow,
  olive, lime, green, aqua, teal, blue, navy, fuchsia, purple) (omit to leave unchanged)
\- image_index: Target image index (default 0)

All values are checked before anything changes. A font name GIMP does not have falls back to
a similar or default font, so check the returned font.

Returns: {layer_name (it can change with the text), text, font, size}

Input parameters:

- `color`
- `font`
- `image_index` (integer)
- `layer_name` (string, required)
- `size`
- `text`

### `list_fonts` (~110 tokens)

List fonts installed in GIMP.

Parameters:
\- filter: Optional text matched against font names, case-insensitive (e.g. "sans")
\- limit: Maximum number of names to return (default 100). There can be thousands of
  fonts: if truncated is true, narrow with filter instead of assuming a font is missing.

Returns: {fonts: [font_name, ...], count (returned), total (matching filter), truncated}

Input parameters:

- `filter`
- `limit` (integer)

### `apply_drop_shadow` (~201 tokens)

Apply a drop shadow effect to a layer.

Parameters:
\- offset_x, offset_y: Shadow offset in pixels (default 5, 5)
\- blur_radius: Shadow softness radius (default 10)
\- color: Shadow color as hex "#rrggbb" or a basic name (black, white, gray, silver, red, maroon, yellow,
  olive, lime, green, aqua, teal, blue, navy, fuchsia, purple); default "black"
\- opacity: Shadow opacity 0-100 (default 60)
\- layer_name: Target layer; defaults to active layer
\- image_index: Target image index (default 0)

Returns status dict.

Input parameters:

- `blur_radius` (number)
- `color` (string)
- `image_index` (integer)
- `layer_name`
- `offset_x` (integer)
- `offset_y` (integer)
- `opacity` (number)

### `apply_gaussian_blur` (~96 tokens)

Apply Gaussian blur as a destructive filter operation.

Same as blur with equal horizontal and vertical radii.

Parameters:
\- radius: Blur radius in pixels (default 5.0)
\- layer_name: Target layer; defaults to active layer
\- image_index: Target image index (default 0)

Returns status dict.

Input parameters:

- `image_index` (integer)
- `layer_name`
- `radius` (number)

### `apply_pixelate` (~87 tokens)

Pixelate a layer using a mosaic/block effect.

Parameters:
\- block_size: Size of each mosaic block in pixels (default 10)
\- layer_name: Target layer; defaults to active layer
\- image_index: Target image index (default 0)

Returns status dict.

Input parameters:

- `block_size` (integer)
- `image_index` (integer)
- `layer_name`

### `apply_emboss` (~142 tokens)

Apply an emboss (bas-relief) effect to a layer.

Parameters:
\- azimuth: Light direction in degrees 0-360 (default 315 = top-left)
\- elevation: Light elevation angle 0-90 (default 45)
\- depth: Effect depth/intensity, whole number 1-100 (default 2)
\- layer_name: Target layer; defaults to active layer
\- image_index: Target image index (default 0)

Returns status dict.

Input parameters:

- `azimuth` (number)
- `depth` (number)
- `elevation` (number)
- `image_index` (integer)
- `layer_name`

### `apply_vignette` (~128 tokens)

Apply a vignette darkening effect around the edges of a layer.

Parameters:
\- softness: Edge softness / fade width, 0.0-1.0 (default 0.8)
\- shape: "circle" (default), "square", "diamond", "horizontal" or "vertical"
\- layer_name: Target layer; defaults to active layer
\- image_index: Target image index (default 0)

Returns status dict.

Input parameters:

- `image_index` (integer)
- `layer_name`
- `shape` (string)
- `softness` (number)

### `apply_noise` (~87 tokens)

Add noise/grain to a layer.

Parameters:
\- amount: Noise intensity 0.0-1.0 (default 0.2)
\- layer_name: Target layer; defaults to active layer
\- image_index: Target image index (default 0)

Returns status dict.

Input parameters:

- `amount` (number)
- `image_index` (integer)
- `layer_name`

### `export_icon_sizes` (~222 tokens)

Export an image as a complete icon set for Android or iOS.

Android sizes: 48 (mdpi), 72 (hdpi), 96 (xhdpi), 144 (xxhdpi),
               192 (xxxhdpi), 512 (Play Store)
iOS sizes: 20x1/2/3, 29x1/2/3, 40x2/3, 60x2/3, 76x1/2, 83.5x2, 1024x1

Parameters:
\- output_dir: Directory to write icon files into
\- platform: "android" (default) or "ios"
\- source_image_index: Image to use as source (default 0)
\- format: Output format — "png" (default)

Returns: {exported: [{size, file_path}], count, platform}

Input parameters:

- `format` (string)
- `output_dir` (string, required)
- `platform` (string)
- `source_image_index` (integer)

### `export_web_optimized` (~163 tokens)

Export an image as both JPEG and PNG, choosing the smaller format.

Parameters:
\- output_dir: Directory to write output files
\- jpeg_quality: JPEG quality 1-100 (default 85)
\- png_compression: PNG compression level, 0 (fastest, largest) to 9 (smallest; default)
\- max_width / max_height: Optional scaling before export
\- image_index: Source image index (default 0)

Returns: {jpeg_path, jpeg_size, png_path, png_size, recommendation}

Input parameters:

- `image_index` (integer)
- `jpeg_quality` (integer)
- `max_height`
- `max_width`
- `output_dir` (string, required)
- `png_compression` (integer)

### `warp_region` (~338 tokens)

Disabled: always returns an error and leaves the image unchanged.

On GIMP 3.2 this erased the whole layer instead of warping it, and GIMP 3.2 gives
plug-ins no working warp operation. Use GIMP's Warp Transform tool by hand.

Parameters:
\- vectors: List of warp stroke dicts, each with:
    - x, y      : center of the warp influence (pixels)
    - dx, dy    : push direction — negative dy = push upward
    - radius    : influence radius in pixels (default: 40)
    - amount    : deform strength 0–1 (default: 0.3)
\- image_index: Which open image to edit (default: 0)
\- layer_name: Target layer; omit to use the active/top layer

Examples — make a character smile:
    warp_region(vectors=[
        {"x": 215, "y": 355, "dx":  5, "dy": -8, "radius": 18, "amount": 0.45},
        {"x": 295, "y": 355, "dx": -5, "dy": -8, "radius": 18, "amount": 0.45},
        {"x": 255, "y": 370, "dx":  0, "dy": -4, "radius": 22, "amount": 0.30},
    ])

Returns: {"warped_vectors": N}

Input parameters:

- `image_index` (integer)
- `layer_name`
- `vectors` (array, required)

### `batch_resize` (~129 tokens)

Resize all open images to a common target size.

Parameters:
\- width / height: Target dimensions in pixels (provide one or both)
\- scale_factor: Proportional scale (e.g. 0.5 = 50%); overrides width/height if set
\- maintain_aspect: Preserve aspect ratio when only one dimension is given (default True)

Returns: {results: [{image_id, old_width, old_height, new_width, new_height}], count}

Input parameters:

- `height`
- `maintain_aspect` (boolean)
- `scale_factor`
- `width`

### `export_sprite_sheet` (~188 tokens)

Combine multiple frames into a sprite sheet PNG.

Parameters:
\- output_path: Absolute path for the output PNG file
\- columns: Number of columns in the grid (defaults to square root of frame count)
\- padding: Pixel gap between frames (default 0)
\- source: "layers" (each layer is a frame, in list_layers order; default) or "images"
  (each open image's visible result, in list_images order)
\- image_index: Source image when source="layers" (default 0)

Each cell is the size of the first frame; bigger frames are cropped. Transparency is kept.

Returns: {file_path, columns, rows, frame_width, frame_height, count}

Input parameters:

- `columns`
- `image_index` (integer)
- `output_path` (string, required)
- `padding` (integer)
- `source` (string)

### `export_social_media_kit` (~157 tokens)

Export an image resized for multiple social media platforms.

Platform sizes (all in pixels):
\- instagram_square: 1080x1080
\- instagram_story: 1080x1920
\- twitter_header: 1500x500
\- facebook_cover: 820x312
\- youtube_thumbnail: 1280x720

Parameters:
\- output_dir: Directory to write output files
\- platforms: List of platform names to export (omit for all five)
\- image_index: Source image index (default 0)

Returns: {exported: [{platform, file_path, width, height}], count}

Input parameters:

- `image_index` (integer)
- `output_dir` (string, required)
- `platforms`

### `list_images` (~100 tokens)

List all images currently open in GIMP.

Index 0 is the most recently opened or created image, and indices shift when
images are opened or closed; image_id stays the same for an image's lifetime.
Every image_index parameter uses this order.

Returns:
\- images: list of {index, image_id, name, width, height, color_mode,
                   num_layers, file_path, is_dirty}
\- count: total number of open images

### `set_active_image` (~100 tokens)

Raise a specific image's window to the front in GIMP.

Works for images opened with new_canvas or open_image. GIMP 3 gives plug-ins
no way to find windows opened from GIMP's own menus, so those return an error;
every other tool still works on them by image_index.

Parameters:
\- image_index: Index of the image to activate (from list_images)

Returns status dict.

Input parameters:

- `image_index` (integer, required)

### `convert_color_mode` (~112 tokens)

Convert an image to a different color mode.

Parameters:
\- mode: "RGB", "RGBA", "GRAY", "GRAYA" (the A forms also add alpha to every layer) or "INDEXED"
\- num_colors: Number of colors for INDEXED mode, 1-256 (default 256)
\- image_index: Target image index (default 0)

Returns status dict.

Input parameters:

- `image_index` (integer)
- `mode` (string, required)
- `num_colors` (integer)

### `close_image` (~226 tokens)

Close an image, optionally saving as XCF first.

Closes images opened with new_canvas or open_image, and images that have no
window. GIMP 3 gives plug-ins no way to close a window opened from GIMP's own
menus, so for those images this returns an error and they must be closed in GIMP.

Parameters:
\- image_index: Index of the image to close (default 0 = most recently opened)
\- save_first: If True, save as XCF before closing (default False). An image opened from
  an XCF file is saved over that file. Any other image is saved as a new .xcf next to the
  file it came from (in the temp directory if it has none), named name-2.xcf, name-3.xcf, ...
  instead of overwriting an existing file. Without save_first, unsaved changes are discarded.

Returns: {closed_image_id, saved_to (XCF path, or null)}

Input parameters:

- `image_index` (integer)
- `save_first` (boolean)

### `get_selection_bounds` (~54 tokens)

Get the bounding rectangle of the current selection.

Parameters:
\- image_index: Target image index (default 0)

Returns: {has_selection, x, y, width, height}

Input parameters:

- `image_index` (integer)

### `get_pixel_color` (~180 tokens)

Get the color of a single pixel.

sample_color does the same and can average over a radius; it reports alpha as 0-1,
this tool as 0-255.

Parameters:
\- x, y: Image pixel coordinates
\- image_index: Target image index (default 0)
\- layer_name: Layer to sample when sample_merged is false; defaults to active layer
\- sample_merged: true (default) samples what is visible across all layers;
  false samples only one layer

Returns: {color_hex (sRGB), color_rgb: [r, g, b], alpha (0-255), sampled (what was read)}

Input parameters:

- `image_index` (integer)
- `layer_name`
- `sample_merged` (boolean)
- `x` (integer, required)
- `y` (integer, required)

### `get_histogram` (~131 tokens)

Get histogram statistics for one channel of a layer.

Parameters:
\- channel: "value" (all; default), "red", "green", "blue", "alpha"
\- image_index: Target image index (default 0)
\- layer_name: Layer to measure; defaults to the active layer

Returns: {layer, mean, std_dev, median (on a 0-255 scale), pixels (in the layer),
count (pixels in range), percentile (fraction of pixels in range)}

Input parameters:

- `channel` (string)
- `image_index` (integer)
- `layer_name`

## Diagnostics

Captured diagnostic sections: Provenance, Install scripts, Dependencies. The full working is on the page: https://verifymcp.io/servers/tifyr-gimp3-mcp/gimp3-mcp#diagnostics

## Score history

- 2026-09-21: 65
- 2026-09-20: 65
- 2026-09-19: 65
- 2026-09-18: 65
- 2026-09-17: 65
- 2026-09-16: 50

## Common questions

### What is the GIMP 3 MCP server?

GIMP 3 MCP is listed in the public MCP registry as io.github.tifyr/gimp3-mcp. Let AI assistants paint, edit and export images in a running GIMP 3, with 80 tools. This page covers its PyPI package (gimp3-mcp).

### Is the GIMP 3 MCP server safe to use?

GIMP 3 MCP scores 65 out of 100 on VerifyMCP. We found no known CVEs affecting it as of 21 September 2026. That is a record of what we were able to check automatically, not an endorsement. The category breakdown on this page shows every signal behind the number, including the ones we could not confirm.

### What tools does the GIMP 3 MCP server expose?

GIMP 3 MCP exposes 80 tools: check_server, restart_server, new_canvas, get_image_bitmap, get_image_metadata, and 75 more. Their descriptions and schemas cost roughly 13,404 tokens of context every time the server is loaded.

### Is the GIMP 3 MCP server still maintained?

GIMP 3 MCP is still listed as active in the MCP registry. We last reached this channel on 21 September 2026. Those dates come from our own scans of the registry and the channel itself, not from anything the publisher announced.

## Links

- PyPI project: https://pypi.org/project/gimp3-mcp/
- Socket report: https://socket.dev/pypi/package/gimp3-mcp
- Repository: https://github.com/tifyr/gimp3-mcp
- Changelog RSS feed: https://verifymcp.io/servers/tifyr-gimp3-mcp/gimp3-mcp.xml
- Changelog JSON feed: https://verifymcp.io/servers/tifyr-gimp3-mcp/gimp3-mcp.json
- HTML version of this page: https://verifymcp.io/servers/tifyr-gimp3-mcp/gimp3-mcp
