8000 Concurrent clients' commands run in parallel in the plug-in and can act on the wrong image · Issue #81 · gimp-mcp/gimp-mcp · GitHub
[go: up one dir, main page]

Skip to content

Concurrent clients' commands run in parallel in the plug-in and can act on the wrong image #81

Closed

Description

@tomerkon

Problem

The plug-in runs commands from different connections at the same time, on separate threads, with no lock. When two MCP clients use GIMP at once, their commands can interleave inside GIMP and act on the wrong image or state while still returning status: success. Examples are Claude Desktop together with Claude Code, or two Claude Code sessions.

Priority

Low. Supporting several clients on the same GIMP at once is itself a low priority for this project, and the usual setup of one client isn't affected (see below). This issue records the problem so it's known and can be referenced, not because it needs fixing soon.

Cause

  • _start_server_thread starts a new thread for every accepted connection (gimp-mcp-plugin.py:154), and the MCP server opens a new connection for every command.
  • execute_command (gimp-mcp-plugin.py:250) runs on that client thread. Nothing serialises it, and nothing hands it to the GLib main loop, despite its docstring ("Execute commands in GIMP's main thread").

A single MCP server process isn't affected on its own. Its tools are synchronous, and FastMCP calls them directly on its event loop, so one client sends one request at a time. The problem appears only with two or more clients connected to the same GIMP.

Possible effects

These come from reading the code; I haven't reproduced them yet.

  • Edits on a temporary image. Several commands create a temporary image: get_image_bitmap (in Render the visible composite in get_image_bitmap and honour image_index #68), batch_export, export_web_optimized, the social media kit and the sprite sheet. A new image goes first in Gimp.get_images(), so while one exists, another client's image_index 8000 =0 resolves to it. That client's edit then lands on an image that's about to be deleted, and it still reports success.
  • Shared context changes. Foreground and background colours, brush settings and selections are global GIMP state. One client's set_colors or selection can change what another client's fill_selection or drawing call does halfway through.
  • libgimp called from two threads at once. It's unclear whether the plug-in's connection to GIMP is safe for this.

Proposed fix

Hold one threading.Lock around the body of execute_command, so GIMP runs one command at a time. Concurrent clients then queue instead of interleaving. Also fix the docstring. Commands are short, so the queueing should go unnoticed. A long batch_export would make the other client wait, which is the correct behaviour.

That would also make the temporary-image tagging in #68 (TEMP_IMAGE_PARASITE, _open_images()) unnecessary. See the review there.

To reproduce

  1. Start the plug-in in GIMP and open one image.
  2. From one client, call get_image_bitmap with max_width/max_height repeatedly on a large image. On main, scaling duplicates the image into a temporary one, and a large image keeps it alive longer.
  3. At the same time, from a second client, call a drawing tool such as fill_rectangle on image_index=0.
  4. Expected from the code, not yet confirmed: some fills report success but never appear on the image.

Activity

  1. added a commit that references this issue on Nov 8, 2026
    df8089a
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions

      0