media-agent-mcp 2.6.2__py3-none-any.whl → 2.6.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- media_agent_mcp/ai_models/openaiedit.py +35 -21
- media_agent_mcp/async_server.py +14 -1
- media_agent_mcp/server.py +14 -1
- {media_agent_mcp-2.6.2.dist-info → media_agent_mcp-2.6.4.dist-info}/METADATA +1 -1
- {media_agent_mcp-2.6.2.dist-info → media_agent_mcp-2.6.4.dist-info}/RECORD +8 -8
- {media_agent_mcp-2.6.2.dist-info → media_agent_mcp-2.6.4.dist-info}/WHEEL +0 -0
- {media_agent_mcp-2.6.2.dist-info → media_agent_mcp-2.6.4.dist-info}/entry_points.txt +0 -0
- {media_agent_mcp-2.6.2.dist-info → media_agent_mcp-2.6.4.dist-info}/top_level.txt +0 -0
@@ -183,33 +183,47 @@ def google_edit(image_urls: List[str], prompt: str) -> Dict[str, Any]:
|
|
183
183
|
|
184
184
|
contents = pil_images + [prompt]
|
185
185
|
|
186
|
-
# model = genai.GenerativeModel("gemini-1.5-flash-latest")
|
187
|
-
# response = model.generate_content(contents)
|
188
186
|
client = genai.Client(
|
189
187
|
api_key=api_key,
|
190
188
|
)
|
191
189
|
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
190
|
+
# 最多尝试3次
|
191
|
+
max_retries = 3
|
192
|
+
for attempt in range(max_retries):
|
193
|
+
try:
|
194
|
+
response = client.models.generate_content(
|
195
|
+
model="gemini-2.5-flash-image-preview",
|
196
|
+
contents=contents
|
197
|
+
)
|
196
198
|
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
199
|
+
image_data = None
|
200
|
+
if response.candidates and response.candidates[0].content and response.candidates[0].content.parts:
|
201
|
+
image_parts = [
|
202
|
+
part.inline_data.data
|
203
|
+
for part in response.candidates[0].content.parts
|
204
|
+
if part.inline_data
|
205
|
+
]
|
206
|
+
if image_parts:
|
207
|
+
image_data = image_parts[0]
|
206
208
|
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
209
|
+
# 如果获取到了图片数据,跳出重试循环
|
210
|
+
if image_data:
|
211
|
+
break
|
212
|
+
|
213
|
+
# 如果是最后一次尝试且仍然没有图片数据,返回错误
|
214
|
+
if attempt == max_retries - 1:
|
215
|
+
return {
|
216
|
+
"status": "error",
|
217
|
+
"data": None,
|
218
|
+
"message": f"Google API response did not contain image data after {max_retries} attempts."
|
219
|
+
}
|
220
|
+
|
221
|
+
except Exception as api_error:
|
222
|
+
# 如果是最后一次尝试,抛出异常
|
223
|
+
if attempt == max_retries - 1:
|
224
|
+
raise api_error
|
225
|
+
# 否则继续下一次尝试
|
226
|
+
continue
|
213
227
|
|
214
228
|
with tempfile.NamedTemporaryFile(delete=False, suffix='.png') as temp_edited_file:
|
215
229
|
temp_edited_file.write(image_data)
|
media_agent_mcp/async_server.py
CHANGED
@@ -24,6 +24,7 @@ from typing import List, Optional
|
|
24
24
|
import json
|
25
25
|
from dotenv import load_dotenv
|
26
26
|
import uvicorn
|
27
|
+
import anyio
|
27
28
|
from functools import wraps
|
28
29
|
|
29
30
|
def async_retry(max_retries=3, delay=2):
|
@@ -80,6 +81,18 @@ from media_agent_mcp.async_wrapper import (
|
|
80
81
|
logging.basicConfig(level=logging.INFO)
|
81
82
|
logger = logging.getLogger(__name__)
|
82
83
|
|
84
|
+
# Swallow ClosedResourceError from AnyIO (e.g., SSE client disconnected)
|
85
|
+
class IgnoreClosedResourceErrorMiddleware:
|
86
|
+
def __init__(self, app):
|
87
|
+
self.app = app
|
88
|
+
|
89
|
+
async def __call__(self, scope, receive, send):
|
90
|
+
try:
|
91
|
+
await self.app(scope, receive, send)
|
92
|
+
except anyio.ClosedResourceError:
|
93
|
+
logger.warning("SSE client disconnected (ClosedResourceError). Ignoring.")
|
94
|
+
return
|
95
|
+
|
83
96
|
# Initialize FastMCP server (will be configured in main function)
|
84
97
|
load_dotenv()
|
85
98
|
mcp = FastMCP("Media-Agent-MCP-Async")
|
@@ -524,7 +537,7 @@ def main():
|
|
524
537
|
mcp.settings.port = args.port
|
525
538
|
# Use uvicorn to run SSE app with extended keep-alive timeout (5 minutes)
|
526
539
|
uvicorn.run(
|
527
|
-
mcp.sse_app(),
|
540
|
+
IgnoreClosedResourceErrorMiddleware(mcp.sse_app()),
|
528
541
|
host=args.host,
|
529
542
|
port=args.port,
|
530
543
|
timeout_keep_alive=300
|
media_agent_mcp/server.py
CHANGED
@@ -20,6 +20,7 @@ from typing import Optional, Dict, Any
|
|
20
20
|
import json
|
21
21
|
from dotenv import load_dotenv
|
22
22
|
import uvicorn
|
23
|
+
import anyio
|
23
24
|
|
24
25
|
from mcp.server.fastmcp import FastMCP
|
25
26
|
|
@@ -39,6 +40,18 @@ from media_agent_mcp.media_selectors.video_selector import select_best_video
|
|
39
40
|
logging.basicConfig(level=logging.INFO)
|
40
41
|
logger = logging.getLogger(__name__)
|
41
42
|
|
43
|
+
# Swallow ClosedResourceError from AnyIO (e.g., SSE client disconnected)
|
44
|
+
class IgnoreClosedResourceErrorMiddleware:
|
45
|
+
def __init__(self, app):
|
46
|
+
self.app = app
|
47
|
+
|
48
|
+
async def __call__(self, scope, receive, send):
|
49
|
+
try:
|
50
|
+
await self.app(scope, receive, send)
|
51
|
+
except anyio.ClosedResourceError:
|
52
|
+
logger.warning("SSE client disconnected (ClosedResourceError). Ignoring.")
|
53
|
+
return
|
54
|
+
|
42
55
|
# Initialize FastMCP server (will be configured in main function)
|
43
56
|
load_dotenv()
|
44
57
|
mcp = FastMCP("Media-Agent-MCP")
|
@@ -577,7 +590,7 @@ def main():
|
|
577
590
|
# Configure and run the server
|
578
591
|
if args.transport == 'sse':
|
579
592
|
# SSE transport
|
580
|
-
uvicorn.run(mcp.create_sse_app(), host=args.host, port=args.port)
|
593
|
+
uvicorn.run(IgnoreClosedResourceErrorMiddleware(mcp.create_sse_app()), host=args.host, port=args.port)
|
581
594
|
else:
|
582
595
|
# STDIO transport (default)
|
583
596
|
mcp.run()
|
@@ -1,10 +1,10 @@
|
|
1
1
|
media_agent_mcp/__init__.py,sha256=4kV5u8kHrsdjpMHDNUhc8h4U6AwOyw1mNptFPd2snrQ,365
|
2
|
-
media_agent_mcp/async_server.py,sha256=
|
2
|
+
media_agent_mcp/async_server.py,sha256=rZJXfC9Htx1fk2smyCyxflAdaUV8tILvvviUDE9IsnA,20339
|
3
3
|
media_agent_mcp/async_wrapper.py,sha256=hiiBhhz9WeVDfSBWVh6ovhf5jeP5ZbsieBbz9P-KPn0,15351
|
4
|
-
media_agent_mcp/server.py,sha256=
|
4
|
+
media_agent_mcp/server.py,sha256=hZ_m7HodF_ct_q3FXuCrjE6_tw6rXOim38q2sSdTI9I,19976
|
5
5
|
media_agent_mcp/ai_models/__init__.py,sha256=2kHzTYwjQw89U4QGDq0e2WqJScqDkDNlDaWHGak5JeY,553
|
6
6
|
media_agent_mcp/ai_models/omni_human.py,sha256=s_Ja4gEmHG_bgii1x4SoeV73lz0Zg_3iBRvu36goxVA,4643
|
7
|
-
media_agent_mcp/ai_models/openaiedit.py,sha256=
|
7
|
+
media_agent_mcp/ai_models/openaiedit.py,sha256=uu4d2BgXSrjWRdNPs_SryI9muxO93pItVtEze9nDhjc,9776
|
8
8
|
media_agent_mcp/ai_models/seed16.py,sha256=_rPBfgDASxb2_5-mydus-SLK-6XGy2Cy5lLh5ORBtN8,5078
|
9
9
|
media_agent_mcp/ai_models/seedance.py,sha256=ni7LtXn4jTn5wX2NtcWDMj5Eea8LoP1QLYgwSx_GvBs,9014
|
10
10
|
media_agent_mcp/ai_models/seededit.py,sha256=2f0GiQPqH5IJKsZyW0h5WNA99DX--9oOKiD6vqg8Urk,2091
|
@@ -44,8 +44,8 @@ media_agent_mcp/video/__init__.py,sha256=tfz22XEeFSeuKa3AggYCE0vCDt4IwXRCKW6avof
|
|
44
44
|
media_agent_mcp/video/processor.py,sha256=twfqmN5DbVryjDawZUcqTUcnglcBJYpUbAnApqHgD0c,12787
|
45
45
|
media_agent_mcp/video/stack.py,sha256=pyoJiJ9NhU1tjy2l3kARI9sWFoC00Fj97psxYOBi2NU,1736
|
46
46
|
media_agent_mcp/video/subtitle.py,sha256=TlrWVhWJqYTUJpnVz7eccwMAn8ixfrRzRxS6ETMY-DM,16323
|
47
|
-
media_agent_mcp-2.6.
|
48
|
-
media_agent_mcp-2.6.
|
49
|
-
media_agent_mcp-2.6.
|
50
|
-
media_agent_mcp-2.6.
|
51
|
-
media_agent_mcp-2.6.
|
47
|
+
media_agent_mcp-2.6.4.dist-info/METADATA,sha256=rqUYSncUPBBUiTQtMTWEax03GEBSCs5JyLC7ErZ_VAw,11310
|
48
|
+
media_agent_mcp-2.6.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
49
|
+
media_agent_mcp-2.6.4.dist-info/entry_points.txt,sha256=qhOUwR-ORVf9GO7emhhl7Lgd6MISgqbZr8bEuSH_VdA,70
|
50
|
+
media_agent_mcp-2.6.4.dist-info/top_level.txt,sha256=WEa0YfchpTxZgiKn8gdxYgs-dir5HepJaTOrxAGx9nY,16
|
51
|
+
media_agent_mcp-2.6.4.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|