tomo2chin2 commited on
Commit
0b26f38
·
verified ·
1 Parent(s): 672d01c

Upload 9 files

Browse files
Files changed (3) hide show
  1. README.md +2 -1
  2. app.py +45 -7
  3. mcp_client.py +10 -8
README.md CHANGED
@@ -81,7 +81,8 @@ Add this configuration to your Claude Code settings:
81
  **Returns:**
82
  - `success` (boolean): Whether generation was successful
83
  - `message` (string): Status message
84
- - `image_base64` (string): Base64-encoded PNG image (if successful)
 
85
 
86
  ## Requirements
87
 
 
81
  **Returns:**
82
  - `success` (boolean): Whether generation was successful
83
  - `message` (string): Status message
84
+ - `image_url` (string): URL to access the generated image (if successful)
85
+ - `image_path` (string): Local file path of the generated image (if successful)
86
 
87
  ## Requirements
88
 
app.py CHANGED
@@ -10,9 +10,14 @@ import logging
10
  import traceback
11
  from typing import Optional
12
  from fastapi import FastAPI, Request
13
- from fastapi.responses import JSONResponse, RedirectResponse
14
  from fastapi.middleware.cors import CORSMiddleware
 
15
  import uvicorn
 
 
 
 
16
 
17
  # ログ設定
18
  logging.basicConfig(
@@ -41,6 +46,28 @@ app.add_middleware(
41
  allow_headers=["*"],
42
  )
43
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44
  # Gemini APIクライアントの初期化
45
  def get_gemini_client():
46
  api_key = os.environ.get("GEMINI_API_KEY")
@@ -210,20 +237,31 @@ async def mcp_call_tool(request: Request):
210
  if tool_name == "generate_image":
211
  prompt = arguments.get("prompt", "")
212
 
 
 
 
213
  # 画像生成を実行
214
  image, message = generate_image(prompt)
215
 
216
  if image:
217
- # 画像をbase64エンコ
218
- buffered = io.BytesIO()
219
- image.save(buffered, format="PNG")
220
- img_str = base64.b64encode(buffered.getvalue()).decode()
 
 
 
 
 
 
 
221
 
222
- logger.info("MCP画像生成成功")
223
  return JSONResponse({
224
  "success": True,
225
  "message": message,
226
- "image_base64": img_str
 
227
  })
228
  else:
229
  logger.warning(f"MCP画像生成失敗: {message}")
 
10
  import traceback
11
  from typing import Optional
12
  from fastapi import FastAPI, Request
13
+ from fastapi.responses import JSONResponse, RedirectResponse, FileResponse
14
  from fastapi.middleware.cors import CORSMiddleware
15
+ from fastapi.staticfiles import StaticFiles
16
  import uvicorn
17
+ import tempfile
18
+ import uuid
19
+ from datetime import datetime, timedelta
20
+ import shutil
21
 
22
  # ログ設定
23
  logging.basicConfig(
 
46
  allow_headers=["*"],
47
  )
48
 
49
+ # 画像ファイル保存用ディレクトリ
50
+ IMAGES_DIR = tempfile.mkdtemp(prefix="mcp_images_")
51
+ os.makedirs(IMAGES_DIR, exist_ok=True)
52
+
53
+ # 静的ファイルのマウント
54
+ app.mount("/images", StaticFiles(directory=IMAGES_DIR), name="images")
55
+
56
+ # 画像ファイルのクリーンアップ(古いファイルを削除)
57
+ def cleanup_old_images():
58
+ """24時間以上経過した画像ファイルを削除"""
59
+ try:
60
+ now = datetime.now()
61
+ for filename in os.listdir(IMAGES_DIR):
62
+ filepath = os.path.join(IMAGES_DIR, filename)
63
+ if os.path.isfile(filepath):
64
+ file_time = datetime.fromtimestamp(os.path.getmtime(filepath))
65
+ if now - file_time > timedelta(hours=24):
66
+ os.remove(filepath)
67
+ logger.info(f"古い画像を削除: {filename}")
68
+ except Exception as e:
69
+ logger.error(f"画像クリーンアップエラー: {str(e)}")
70
+
71
  # Gemini APIクライアントの初期化
72
  def get_gemini_client():
73
  api_key = os.environ.get("GEMINI_API_KEY")
 
237
  if tool_name == "generate_image":
238
  prompt = arguments.get("prompt", "")
239
 
240
+ # 古い画像をクリーンアップ
241
+ cleanup_old_images()
242
+
243
  # 画像生成を実行
244
  image, message = generate_image(prompt)
245
 
246
  if image:
247
+ # ユニクなファイル名を生成
248
+ filename = f"generated_{uuid.uuid4()}.png"
249
+ filepath = os.path.join(IMAGES_DIR, filename)
250
+
251
+ # 画像を保存
252
+ image.save(filepath, format="PNG")
253
+ logger.info(f"画像を保存: {filepath}")
254
+
255
+ # Hugging Face SpacesのベースURLを取得
256
+ base_url = str(request.base_url).rstrip('/')
257
+ image_url = f"{base_url}/images/{filename}"
258
 
259
+ logger.info(f"MCP画像生成成功: {image_url}")
260
  return JSONResponse({
261
  "success": True,
262
  "message": message,
263
+ "image_url": image_url,
264
+ "image_path": filepath
265
  })
266
  else:
267
  logger.warning(f"MCP画像生成失敗: {message}")
mcp_client.py CHANGED
@@ -21,7 +21,7 @@ class ImageGenMCPClient:
21
  response = requests.post(f"{self.base_url}/mcp/list_tools")
22
  return response.json()
23
 
24
- def generate_image(self, prompt: str) -> tuple[Image.Image, str]:
25
  """
26
  画像を生成する
27
 
@@ -29,7 +29,7 @@ class ImageGenMCPClient:
29
  prompt: 生成したい画像の説明
30
 
31
  Returns:
32
- 生成された画像メッセージ
33
  """
34
  payload = {
35
  "name": "generate_image",
@@ -42,12 +42,13 @@ class ImageGenMCPClient:
42
  result = response.json()
43
 
44
  if result.get("success"):
45
- # base64デコードして画像を取得
46
- img_data = base64.b64decode(result["image_base64"])
47
- image = Image.open(io.BytesIO(img_data))
48
- return image, result["message"]
 
49
  else:
50
- return None, result["message"]
51
 
52
  def health_check(self):
53
  """ヘルスチェック"""
@@ -67,9 +68,10 @@ if __name__ == "__main__":
67
  print("Available tools:", tools)
68
 
69
  # 画像生成
70
- image, message = client.generate_image("美しい夕日の風景")
71
  if image:
72
  print(f"Success: {message}")
 
73
  image.save("generated_image.png")
74
  else:
75
  print(f"Error: {message}")
 
21
  response = requests.post(f"{self.base_url}/mcp/list_tools")
22
  return response.json()
23
 
24
+ def generate_image(self, prompt: str) -> tuple[Image.Image, str, str]:
25
  """
26
  画像を生成する
27
 
 
29
  prompt: 生成したい画像の説明
30
 
31
  Returns:
32
+ 生成された画像メッセージ、画像URL
33
  """
34
  payload = {
35
  "name": "generate_image",
 
42
  result = response.json()
43
 
44
  if result.get("success"):
45
+ # 画像URLから画像を取得
46
+ image_url = result["image_url"]
47
+ img_response = requests.get(image_url)
48
+ image = Image.open(io.BytesIO(img_response.content))
49
+ return image, result["message"], image_url
50
  else:
51
+ return None, result["message"], None
52
 
53
  def health_check(self):
54
  """ヘルスチェック"""
 
68
  print("Available tools:", tools)
69
 
70
  # 画像生成
71
+ image, message, image_url = client.generate_image("美しい夕日の風景")
72
  if image:
73
  print(f"Success: {message}")
74
+ print(f"Image URL: {image_url}")
75
  image.save("generated_image.png")
76
  else:
77
  print(f"Error: {message}")