Merge pull request #170 from openqj/feat-image-edit-mcp

feat: 图片改图 MCP 工具 image_edit
This commit is contained in:
openqj authored and GitHub committed 2026-10-30 04:12:46 +08:00
commit 0787496427
4 files changed
+236 -30

No files matched your search

+44
View File
@@ -87,11 +87,55 @@ class ImageGenTests(unittest.TestCase):
self.assertIn("404", str(ctx.exception))
self.assertNotIn("k", str(ctx.exception))
def test_edit_multipart_writes_new_file(self):
with open(os.path.join(self._tmp.name, "in.png"), "wb") as fh:
fh.write(PNG_1x1)
seen = {}
def fake_multipart(url, key, body, content_type):
seen["url"] = url
seen["body"] = body
seen["content_type"] = content_type
self.assertTrue(url.endswith("/v1/images/edits"))
self.assertIn(b"Change the background", body)
self.assertIn(PNG_1x1, body)
return 200, {"data": [{"url": "https://cdn.example/e.png",
"revised_prompt": "blue bg"}],
"usage": {"total_tokens": 2727}}
out = imagegen.edit(
"Change the background to blue", "in.png",
output_filename="out.png",
request_multipart=fake_multipart,
download=lambda url: PNG_1x1, cwd=self._tmp.name)
self.assertEqual(out["filename"], "out.png")
self.assertEqual(out["input_filename"], "in.png")
self.assertEqual(out["format"], "png")
self.assertTrue(seen["content_type"].startswith(
"multipart/form-data; boundary="))
# Input untouched, output is a separate file.
with open(os.path.join(self._tmp.name, "in.png"), "rb") as fh:
self.assertEqual(fh.read(), PNG_1x1)
self.assertTrue(os.path.exists(
os.path.join(self._tmp.name, "out.png")))
def test_edit_missing_input_and_same_output_rejected(self):
with self.assertRaises(ImageGenError):
imagegen.edit("x", "nope.png", cwd=self._tmp.name)
with open(os.path.join(self._tmp.name, "in.png"), "wb") as fh:
fh.write(PNG_1x1)
with self.assertRaises(ImageGenError):
imagegen.edit("x", "in.png", output_filename="in.png",
cwd=self._tmp.name)
with self.assertRaises(ImageGenError):
imagegen.edit("x", "../in.png", cwd=self._tmp.name)
def test_mcp_tools_list_and_call(self):
listed = handle_request({"jsonrpc": "2.0", "id": 1,
"method": "tools/list"})
names = [t["name"] for t in listed["result"]["tools"]]
self.assertIn("image_generate", names)
self.assertIn("image_edit", names)
called = handle_request(
{"jsonrpc": "2.0", "id": 2, "method": "tools/call",
"params": {"name": "image_generate",