diff --git a/src/mcp_synology_container/modules/images.py b/src/mcp_synology_container/modules/images.py index ee3c151..17dedfa 100644 --- a/src/mcp_synology_container/modules/images.py +++ b/src/mcp_synology_container/modules/images.py @@ -243,20 +243,17 @@ def register_images(mcp: FastMCP, config: AppConfig, client: DsmClient) -> None: f"Call delete_image(image_id={image_id!r}, confirmed=True) to confirm." ) - # Perform deletion using the resolved name+tag. - # N4S4 reference: SYNO.Docker.Image / delete, params: name, tag - delete_name = repo - delete_tag = img_tags[0] if img_tags else tag - sys.stderr.write( - f"[delete_image] api=SYNO.Docker.Image method=delete" - f" name={delete_name!r} tag={delete_tag!r}\n" - ) + # DSM requires the sha256 image ID for deletion, not name+tag. + if not img_hash: + return f"Cannot delete '{display_name}': image ID (sha256) not found in list." + + sys.stderr.write(f"[delete_image] api=SYNO.Docker.Image method=delete id={img_hash!r}\n") sys.stderr.flush() try: await client.request( "SYNO.Docker.Image", "delete", - params={"name": delete_name, "tag": delete_tag}, + params={"id": img_hash}, ) except Exception as e: code = getattr(e, "code", "?") diff --git a/tests/test_modules/test_images.py b/tests/test_modules/test_images.py index 944f187..6ee6122 100644 --- a/tests/test_modules/test_images.py +++ b/tests/test_modules/test_images.py @@ -225,6 +225,13 @@ async def test_delete_image_confirmed(): assert "redis:7" in result assert "freed" in result + # Delete must use the sha256 id, not name+tag + delete_call = next(c for c in client.request.call_args_list if c.args[1] == "delete") + params = delete_call.kwargs.get("params") or {} + assert params.get("id") == "sha256:cccc" + assert "name" not in params + assert "tag" not in params + @pytest.mark.asyncio async def test_delete_image_not_found(): @@ -330,11 +337,12 @@ async def test_delete_image_registry_prefixed_name(): assert "Deleted" in result assert "open-webui" in result - # Verify delete was called with correct split params (not "ghcr" as name) + # Verify delete was called with the sha256 ID, not name+tag delete_call = next(c for c in client.request.call_args_list if c.args[1] == "delete") params = delete_call.kwargs.get("params") or {} - assert params.get("name") == "ghcr.io/open-webui/open-webui" - assert params.get("tag") == "v0.8.10" + assert params.get("id") == "sha256:dddd" + assert "name" not in params + assert "tag" not in params @pytest.mark.asyncio