Repository navigation
Description
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_threadstarts 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 inGimp.get_images(), so while one exists, another client'simage_index 8000 =0resolves 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_colorsor selection can change what another client'sfill_selectionor 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
- Start the plug-in in GIMP and open one image.
- From one client, call
get_image_bitmapwithmax_width/max_heightrepeatedly on a large image. Onmain, scaling duplicates the image into a temporary one, and a large image keeps it alive longer. - At the same time, from a second client, call a drawing tool such as
fill_rectangleonimage_index=0. - Expected from the code, not yet confirmed: some fills report success but never appear on the image.
Activity
fix: plugin crash after client-side timeout (#82)