media-agent-mcp 2.6.13__tar.gz → 2.7.0__tar.gz

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.
Files changed (55) hide show
  1. {media_agent_mcp-2.6.13 → media_agent_mcp-2.7.0}/PKG-INFO +1 -1
  2. {media_agent_mcp-2.6.13 → media_agent_mcp-2.7.0}/pyproject.toml +1 -1
  3. {media_agent_mcp-2.6.13 → media_agent_mcp-2.7.0}/src/media_agent_mcp/__init__.py +2 -2
  4. {media_agent_mcp-2.6.13 → media_agent_mcp-2.7.0}/src/media_agent_mcp/ai_models/omni_human.py +2 -1
  5. {media_agent_mcp-2.6.13 → media_agent_mcp-2.7.0}/src/media_agent_mcp/async_server.py +2 -324
  6. {media_agent_mcp-2.6.13 → media_agent_mcp-2.7.0}/src/media_agent_mcp.egg-info/PKG-INFO +1 -1
  7. {media_agent_mcp-2.6.13 → media_agent_mcp-2.7.0}/README.md +0 -0
  8. {media_agent_mcp-2.6.13 → media_agent_mcp-2.7.0}/setup.cfg +0 -0
  9. {media_agent_mcp-2.6.13 → media_agent_mcp-2.7.0}/src/media_agent_mcp/ai_models/__init__.py +0 -0
  10. {media_agent_mcp-2.6.13 → media_agent_mcp-2.7.0}/src/media_agent_mcp/ai_models/openaiedit.py +0 -0
  11. {media_agent_mcp-2.6.13 → media_agent_mcp-2.7.0}/src/media_agent_mcp/ai_models/seed16.py +0 -0
  12. {media_agent_mcp-2.6.13 → media_agent_mcp-2.7.0}/src/media_agent_mcp/ai_models/seedance.py +0 -0
  13. {media_agent_mcp-2.6.13 → media_agent_mcp-2.7.0}/src/media_agent_mcp/ai_models/seededit.py +0 -0
  14. {media_agent_mcp-2.6.13 → media_agent_mcp-2.7.0}/src/media_agent_mcp/ai_models/seedream.py +0 -0
  15. {media_agent_mcp-2.6.13 → media_agent_mcp-2.7.0}/src/media_agent_mcp/ai_models/tts.py +0 -0
  16. {media_agent_mcp-2.6.13 → media_agent_mcp-2.7.0}/src/media_agent_mcp/async_wrapper.py +0 -0
  17. {media_agent_mcp-2.6.13 → media_agent_mcp-2.7.0}/src/media_agent_mcp/audio/combiner.py +0 -0
  18. {media_agent_mcp-2.6.13 → media_agent_mcp-2.7.0}/src/media_agent_mcp/audio/speed_controller.py +0 -0
  19. {media_agent_mcp-2.6.13 → media_agent_mcp-2.7.0}/src/media_agent_mcp/audio/tts.py +0 -0
  20. {media_agent_mcp-2.6.13 → media_agent_mcp-2.7.0}/src/media_agent_mcp/be/README.md +0 -0
  21. {media_agent_mcp-2.6.13 → media_agent_mcp-2.7.0}/src/media_agent_mcp/be/__init__.py +0 -0
  22. {media_agent_mcp-2.6.13 → media_agent_mcp-2.7.0}/src/media_agent_mcp/be/__pycache__/__init__.cpython-312.pyc +0 -0
  23. {media_agent_mcp-2.6.13 → media_agent_mcp-2.7.0}/src/media_agent_mcp/be/__pycache__/app.cpython-312.pyc +0 -0
  24. {media_agent_mcp-2.6.13 → media_agent_mcp-2.7.0}/src/media_agent_mcp/be/__pycache__/routes_media.cpython-312.pyc +0 -0
  25. {media_agent_mcp-2.6.13 → media_agent_mcp-2.7.0}/src/media_agent_mcp/be/__pycache__/routes_omni.cpython-312.pyc +0 -0
  26. {media_agent_mcp-2.6.13 → media_agent_mcp-2.7.0}/src/media_agent_mcp/be/__pycache__/routes_subtitles.cpython-312.pyc +0 -0
  27. {media_agent_mcp-2.6.13 → media_agent_mcp-2.7.0}/src/media_agent_mcp/be/__pycache__/utils.cpython-312.pyc +0 -0
  28. {media_agent_mcp-2.6.13 → media_agent_mcp-2.7.0}/src/media_agent_mcp/be/app.py +0 -0
  29. {media_agent_mcp-2.6.13 → media_agent_mcp-2.7.0}/src/media_agent_mcp/be/fonts/en/EduNSWACTCursive-VariableFont_wght.ttf +0 -0
  30. {media_agent_mcp-2.6.13 → media_agent_mcp-2.7.0}/src/media_agent_mcp/be/fonts/en/MozillaText-VariableFont_wght.ttf +0 -0
  31. {media_agent_mcp-2.6.13 → media_agent_mcp-2.7.0}/src/media_agent_mcp/be/fonts/en/Roboto_Condensed-Regular.ttf +0 -0
  32. {media_agent_mcp-2.6.13 → media_agent_mcp-2.7.0}/src/media_agent_mcp/be/fonts/zh/MaShanZheng-Regular.ttf +0 -0
  33. {media_agent_mcp-2.6.13 → media_agent_mcp-2.7.0}/src/media_agent_mcp/be/fonts/zh/NotoSerifSC-VariableFont_wght.ttf +0 -0
  34. {media_agent_mcp-2.6.13 → media_agent_mcp-2.7.0}/src/media_agent_mcp/be/fonts/zh/ZCOOLXiaoWei-Regular.ttf +0 -0
  35. {media_agent_mcp-2.6.13 → media_agent_mcp-2.7.0}/src/media_agent_mcp/be/pyproject.toml +0 -0
  36. {media_agent_mcp-2.6.13 → media_agent_mcp-2.7.0}/src/media_agent_mcp/be/routes_media.py +0 -0
  37. {media_agent_mcp-2.6.13 → media_agent_mcp-2.7.0}/src/media_agent_mcp/be/routes_subtitles.py +0 -0
  38. {media_agent_mcp-2.6.13 → media_agent_mcp-2.7.0}/src/media_agent_mcp/be/utils.py +0 -0
  39. {media_agent_mcp-2.6.13 → media_agent_mcp-2.7.0}/src/media_agent_mcp/be/uv.lock +0 -0
  40. {media_agent_mcp-2.6.13 → media_agent_mcp-2.7.0}/src/media_agent_mcp/install_tools/__init__.py +0 -0
  41. {media_agent_mcp-2.6.13 → media_agent_mcp-2.7.0}/src/media_agent_mcp/install_tools/installer.py +0 -0
  42. {media_agent_mcp-2.6.13 → media_agent_mcp-2.7.0}/src/media_agent_mcp/media_selectors/__init__.py +0 -0
  43. {media_agent_mcp-2.6.13 → media_agent_mcp-2.7.0}/src/media_agent_mcp/media_selectors/image_selector.py +0 -0
  44. {media_agent_mcp-2.6.13 → media_agent_mcp-2.7.0}/src/media_agent_mcp/media_selectors/video_selector.py +0 -0
  45. {media_agent_mcp-2.6.13 → media_agent_mcp-2.7.0}/src/media_agent_mcp/storage/__init__.py +0 -0
  46. {media_agent_mcp-2.6.13 → media_agent_mcp-2.7.0}/src/media_agent_mcp/storage/tos_client.py +0 -0
  47. {media_agent_mcp-2.6.13 → media_agent_mcp-2.7.0}/src/media_agent_mcp/video/__init__.py +0 -0
  48. {media_agent_mcp-2.6.13 → media_agent_mcp-2.7.0}/src/media_agent_mcp/video/processor.py +0 -0
  49. {media_agent_mcp-2.6.13 → media_agent_mcp-2.7.0}/src/media_agent_mcp/video/stack.py +0 -0
  50. {media_agent_mcp-2.6.13 → media_agent_mcp-2.7.0}/src/media_agent_mcp/video/subtitle.py +0 -0
  51. {media_agent_mcp-2.6.13 → media_agent_mcp-2.7.0}/src/media_agent_mcp.egg-info/SOURCES.txt +0 -0
  52. {media_agent_mcp-2.6.13 → media_agent_mcp-2.7.0}/src/media_agent_mcp.egg-info/dependency_links.txt +0 -0
  53. {media_agent_mcp-2.6.13 → media_agent_mcp-2.7.0}/src/media_agent_mcp.egg-info/entry_points.txt +0 -0
  54. {media_agent_mcp-2.6.13 → media_agent_mcp-2.7.0}/src/media_agent_mcp.egg-info/requires.txt +0 -0
  55. {media_agent_mcp-2.6.13 → media_agent_mcp-2.7.0}/src/media_agent_mcp.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: media-agent-mcp
3
- Version: 2.6.13
3
+ Version: 2.7.0
4
4
  Summary: A Model Context Protocol server for media processing with AI tools
5
5
  Author-email: Media Agent Team <team@mediaagent.com>
6
6
  Keywords: mcp,ai,media,video,image,processing
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "media-agent-mcp"
3
- version = "2.6.13"
3
+ version = "2.7.0"
4
4
  description = "A Model Context Protocol server for media processing with AI tools"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.12"
@@ -1,8 +1,8 @@
1
1
  """Media Agent MCP Server - A Model Context Protocol server for media processing."""
2
2
 
3
3
  from . import ai_models, media_selectors, storage, video
4
- from .async_server import main
4
+ from .async_server import main as async_main
5
5
  from . import async_wrapper
6
6
 
7
7
  __version__ = "0.1.0"
8
- __all__ = ['ai_models', 'media_selectors', 'storage', 'video', 'main', 'async_wrapper']
8
+ __all__ = ['ai_models', 'media_selectors', 'storage', 'video', 'main', 'async_main', 'async_wrapper']
@@ -126,4 +126,5 @@ if __name__ == '__main__':
126
126
  audio_url="https://carey.tos-ap-southeast-1.bytepluses.com/media_agent/2025-08-30/a72d04349e81454c8065674792256a1d.mp3"
127
127
  ))
128
128
 
129
- print(time.time() - time1)
129
+ print(time.time() - time1)
130
+ # 16452282602934202024
@@ -26,12 +26,6 @@ from dotenv import load_dotenv
26
26
  import uvicorn
27
27
  import anyio
28
28
  from functools import wraps
29
- import uuid
30
- import weakref
31
- from starlette.applications import Starlette
32
- from starlette.middleware.base import BaseHTTPMiddleware
33
- from starlette.requests import Request
34
- from starlette.responses import Response
35
29
 
36
30
  def async_retry(max_retries=3, delay=2):
37
31
  def decorator(func):
@@ -50,20 +44,6 @@ def async_retry(max_retries=3, delay=2):
50
44
  await asyncio.sleep(delay)
51
45
  continue
52
46
  return result
53
- except anyio.ClosedResourceError as e:
54
- logger.warning(f"ClosedResourceError in {func.__name__} (attempt {attempt + 1}): {e}")
55
- # For ClosedResourceError, we should handle it gracefully
56
- if attempt < max_retries - 1:
57
- logger.info(f"Retrying {func.__name__} after ClosedResourceError...")
58
- await asyncio.sleep(delay)
59
- continue
60
- else:
61
- # On final attempt, return a structured error response
62
- return {
63
- "status": "error",
64
- "data": None,
65
- "message": f"Session expired during {func.__name__} execution. Please retry with a new session."
66
- }
67
47
  except Exception as e:
68
48
  last_exception = str(e)
69
49
  logger.error(f"Attempt {attempt + 1} of {max_retries} failed for {func.__name__} with exception: {e}. Retrying in {delay}s...")
@@ -77,46 +57,6 @@ def async_retry(max_retries=3, delay=2):
77
57
  return wrapper
78
58
  return decorator
79
59
 
80
- def session_aware_retry(max_retries=3, delay=2):
81
- """Enhanced retry decorator that handles session expiration specifically."""
82
- def decorator(func):
83
- @wraps(func)
84
- async def wrapper(*args, **kwargs):
85
- for attempt in range(max_retries):
86
- try:
87
- result = await func(*args, **kwargs)
88
- return result
89
- except anyio.ClosedResourceError as e:
90
- logger.warning(f"Session expired during {func.__name__} execution (attempt {attempt + 1}): {e}")
91
-
92
- if attempt < max_retries - 1:
93
- # Generate new session for retry
94
- new_session_id = session_manager.generate_session_id()
95
- logger.info(f"Generated new session {new_session_id} for retry of {func.__name__}")
96
- await asyncio.sleep(delay)
97
- continue
98
- else:
99
- return {
100
- "status": "error",
101
- "data": None,
102
- "message": f"Session expired during {func.__name__} execution. A new session has been generated. Please retry your request."
103
- }
104
- except Exception as e:
105
- logger.error(f"Unexpected error in {func.__name__} (attempt {attempt + 1}): {e}")
106
- if attempt < max_retries - 1:
107
- await asyncio.sleep(delay)
108
- continue
109
- else:
110
- return {
111
- "status": "error",
112
- "data": None,
113
- "message": f"Function {func.__name__} failed: {str(e)}"
114
- }
115
-
116
- return {"status": "error", "data": None, "message": f"Function {func.__name__} failed after {max_retries} retries"}
117
- return wrapper
118
- return decorator
119
-
120
60
  from mcp.server.fastmcp import FastMCP
121
61
 
122
62
  # Import async wrappers
@@ -141,178 +81,6 @@ from media_agent_mcp.async_wrapper import (
141
81
  logging.basicConfig(level=logging.INFO)
142
82
  logger = logging.getLogger(__name__)
143
83
 
144
- # Session management for handling expired sessions
145
- class SessionManager:
146
- def __init__(self):
147
- self._sessions = {} # Changed from WeakValueDictionary to regular dict
148
- self._session_routes = {}
149
- self._session_timestamps = {} # Track session creation times
150
-
151
- def generate_session_id(self) -> str:
152
- """Generate a new unique session ID."""
153
- return str(uuid.uuid4()).replace('-', '')
154
-
155
- def register_session(self, session_id: str, session_obj):
156
- """Register a session object."""
157
- import time
158
- self._sessions[session_id] = session_obj
159
- self._session_timestamps[session_id] = time.time()
160
- logger.info(f"Registered session: {session_id}")
161
-
162
- def get_session(self, session_id: str):
163
- """Get session object by ID."""
164
- return self._sessions.get(session_id)
165
-
166
- def remove_session(self, session_id: str):
167
- """Remove a session."""
168
- if session_id in self._sessions:
169
- del self._sessions[session_id]
170
- if session_id in self._session_routes:
171
- del self._session_routes[session_id]
172
- if session_id in self._session_timestamps:
173
- del self._session_timestamps[session_id]
174
- logger.info(f"Removed session: {session_id}")
175
-
176
- def cleanup_expired_sessions(self, max_age_seconds: int = 3600):
177
- """Clean up sessions older than max_age_seconds."""
178
- import time
179
- current_time = time.time()
180
- expired_sessions = []
181
-
182
- for session_id, timestamp in self._session_timestamps.items():
183
- if current_time - timestamp > max_age_seconds:
184
- expired_sessions.append(session_id)
185
-
186
- for session_id in expired_sessions:
187
- self.remove_session(session_id)
188
- logger.info(f"Cleaned up expired session: {session_id}")
189
-
190
- return len(expired_sessions)
191
-
192
- def get_session_count(self) -> int:
193
- """Get the number of active sessions."""
194
- return len(self._sessions)
195
-
196
- def get_route_count(self) -> int:
197
- """Get the number of route mappings."""
198
- return len(self._session_routes)
199
-
200
- def add_route_mapping(self, old_session_id: str, new_session_id: str):
201
- """Add route mapping for session forwarding."""
202
- self._session_routes[old_session_id] = new_session_id
203
- logger.info(f"Added route mapping: {old_session_id} -> {new_session_id}")
204
-
205
- def get_route_mapping(self, session_id: str) -> Optional[str]:
206
- """Get route mapping for a session."""
207
- return self._session_routes.get(session_id)
208
-
209
- # Global session manager
210
- session_manager = SessionManager()
211
-
212
- class SessionErrorHandlingMiddleware(BaseHTTPMiddleware):
213
- """Middleware to handle ClosedResourceError and auto-regenerate sessions."""
214
-
215
- async def dispatch(self, request: Request, call_next):
216
- try:
217
- response = await call_next(request)
218
- return response
219
- except anyio.ClosedResourceError as e:
220
- logger.warning(f"ClosedResourceError detected: {e}")
221
-
222
- # Extract session_id from request
223
- session_id = self._extract_session_id(request)
224
- if session_id:
225
- # Generate new session ID
226
- new_session_id = session_manager.generate_session_id()
227
-
228
- # Add route mapping
229
- session_manager.add_route_mapping(session_id, new_session_id)
230
-
231
- # Remove old session
232
- session_manager.remove_session(session_id)
233
-
234
- logger.info(f"Auto-generated new session {new_session_id} to replace expired session {session_id}")
235
-
236
- # Create a JSON response with new session information
237
- new_url = str(request.url).replace(f"session_id={session_id}", f"session_id={new_session_id}")
238
-
239
- from starlette.responses import JSONResponse
240
- return JSONResponse(
241
- status_code=410, # Gone - indicates the resource is no longer available
242
- content={
243
- "error": "session_expired",
244
- "message": "Session expired, please use the new session ID",
245
- "old_session_id": session_id,
246
- "new_session_id": new_session_id,
247
- "redirect_url": new_url
248
- }
249
- )
250
-
251
- # If no session_id found, re-raise the error
252
- raise e
253
- except Exception as e:
254
- logger.error(f"Unexpected error in middleware: {e}")
255
- raise e
256
-
257
- def _extract_session_id(self, request: Request) -> Optional[str]:
258
- """Extract session_id from request URL or headers."""
259
- # Try to get from query parameters
260
- session_id = request.query_params.get('session_id')
261
- if session_id:
262
- return session_id
263
-
264
- # Try to get from path parameters
265
- if hasattr(request, 'path_params') and 'session_id' in request.path_params:
266
- return request.path_params['session_id']
267
-
268
- # Try to extract from URL path
269
- import re
270
- path = str(request.url.path)
271
- match = re.search(r'session_id=([a-f0-9]+)', str(request.url))
272
- if match:
273
- return match.group(1)
274
-
275
- return None
276
-
277
- # Global exception handler for ClosedResourceError
278
- async def handle_closed_resource_error(request, exc):
279
- """Global handler for ClosedResourceError exceptions."""
280
- logger.error(f"Global ClosedResourceError handler triggered: {exc}")
281
-
282
- # Extract session_id from request if possible
283
- session_id = None
284
- if hasattr(request, 'query_params'):
285
- session_id = request.query_params.get('session_id')
286
-
287
- if session_id:
288
- # Generate new session ID
289
- new_session_id = session_manager.generate_session_id()
290
- session_manager.add_route_mapping(session_id, new_session_id)
291
- session_manager.remove_session(session_id)
292
-
293
- logger.info(f"Global handler: Generated new session {new_session_id} to replace {session_id}")
294
-
295
- from starlette.responses import JSONResponse
296
- return JSONResponse(
297
- status_code=410, # Gone - indicates the resource is no longer available
298
- content={
299
- "error": "session_expired",
300
- "message": "Session has expired. A new session has been generated.",
301
- "old_session_id": session_id,
302
- "new_session_id": new_session_id,
303
- "action": "retry_with_new_session"
304
- }
305
- )
306
-
307
- from starlette.responses import JSONResponse
308
- return JSONResponse(
309
- status_code=500,
310
- content={
311
- "error": "internal_server_error",
312
- "message": "An internal server error occurred. Please try again."
313
- }
314
- )
315
-
316
84
  # Initialize FastMCP server (will be configured in main function)
317
85
  load_dotenv()
318
86
  mcp = FastMCP("Media-Agent-MCP-Async")
@@ -668,76 +436,6 @@ async def tts_tool(text: str, speaker_id: str) -> dict:
668
436
  return result
669
437
 
670
438
 
671
- @mcp.tool()
672
- async def get_session_status() -> dict:
673
- """
674
- Get current session management status and statistics.
675
-
676
- Returns:
677
- Dictionary with session statistics and status information
678
- """
679
- try:
680
- active_sessions = session_manager.get_session_count()
681
- route_mappings = session_manager.get_route_count()
682
-
683
- # Clean up expired sessions (older than 1 hour)
684
- cleaned_sessions = session_manager.cleanup_expired_sessions(3600)
685
-
686
- return {
687
- "status": "success",
688
- "data": {
689
- "active_sessions": active_sessions,
690
- "route_mappings": route_mappings,
691
- "cleaned_sessions": cleaned_sessions,
692
- "session_manager_enabled": True,
693
- "features": [
694
- "automatic_session_recovery",
695
- "closed_resource_error_handling",
696
- "request_forwarding",
697
- "session_route_mapping",
698
- "automatic_session_cleanup"
699
- ]
700
- },
701
- "message": f"Session management is active. Cleaned {cleaned_sessions} expired sessions."
702
- }
703
- except Exception as e:
704
- logger.error(f"Error getting session status: {e}")
705
- return {
706
- "status": "error",
707
- "data": None,
708
- "message": f"Failed to get session status: {str(e)}"
709
- }
710
-
711
-
712
- @mcp.tool()
713
- async def generate_new_session() -> dict:
714
- """
715
- Manually generate a new session ID for testing or recovery purposes.
716
-
717
- Returns:
718
- Dictionary with new session ID
719
- """
720
- try:
721
- new_session_id = session_manager.generate_session_id()
722
- logger.info(f"Manually generated new session: {new_session_id}")
723
-
724
- return {
725
- "status": "success",
726
- "data": {
727
- "session_id": new_session_id,
728
- "timestamp": asyncio.get_event_loop().time()
729
- },
730
- "message": f"New session generated: {new_session_id}"
731
- }
732
- except Exception as e:
733
- logger.error(f"Error generating new session: {e}")
734
- return {
735
- "status": "error",
736
- "data": None,
737
- "message": f"Failed to generate new session: {str(e)}"
738
- }
739
-
740
-
741
439
  def main():
742
440
  """Main entry point for the Async MCP server."""
743
441
  import os
@@ -799,11 +497,6 @@ def main():
799
497
  logger.info(f"Transport: {args.transport}")
800
498
  if args.transport == 'sse':
801
499
  logger.info(f"SSE Server will run on {args.host}:{args.port}")
802
- logger.info("Session management features enabled:")
803
- logger.info(" - Automatic session expiration detection")
804
- logger.info(" - Auto-generation of new session IDs")
805
- logger.info(" - Request forwarding with route mapping")
806
- logger.info(" - ClosedResourceError handling")
807
500
 
808
501
  logger.info("Available async tools:")
809
502
  logger.info(" 1. video_last_frame_tool_async - Extract last frame from video and upload to TOS")
@@ -821,11 +514,8 @@ def main():
821
514
  logger.info(" 13. install_tools_plugin_async - Install development tools (ffmpeg and ffprobe)")
822
515
  logger.info(" 14. omni_human_tool_async - Generate a video using Omni Human AI model")
823
516
  logger.info(" 15. google_edit_tool_async - Edit images with Google Gemini (async)")
824
- logger.info(" 16. get_session_status - Get current session management status and statistics")
825
- logger.info(" 17. generate_new_session - Manually generate a new session ID")
826
517
  logger.info("")
827
518
  logger.info("All tools support concurrent execution using asyncio.gather() or run_multiple_tools_concurrently()")
828
- logger.info("Session management tools (16-17) help monitor and manage connection sessions")
829
519
 
830
520
  try:
831
521
  # Start the server with specified transport
@@ -833,24 +523,12 @@ def main():
833
523
  logger.info(f"Starting async SSE server on {args.host}:{args.port}")
834
524
  mcp.settings.host = args.host
835
525
  mcp.settings.port = args.port
836
-
837
- # Get the SSE app and add session error handling middleware
838
- sse_app = mcp.sse_app()
839
-
840
- # Add session error handling middleware
841
- sse_app.add_middleware(SessionErrorHandlingMiddleware)
842
-
843
- # Add global exception handler for ClosedResourceError
844
- sse_app.add_exception_handler(anyio.ClosedResourceError, handle_closed_resource_error)
845
-
846
- logger.info("Added SessionErrorHandlingMiddleware and global ClosedResourceError handler for automatic session recovery")
847
-
848
526
  # Use uvicorn to run SSE app with extended keep-alive timeout (5 minutes)
849
527
  uvicorn.run(
850
- sse_app,
528
+ mcp.sse_app(),
851
529
  host=args.host,
852
530
  port=args.port,
853
- timeout_keep_alive=300
531
+ timeout_keep_alive=1200
854
532
  )
855
533
  else:
856
534
  # Default stdio transport
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: media-agent-mcp
3
- Version: 2.6.13
3
+ Version: 2.7.0
4
4
  Summary: A Model Context Protocol server for media processing with AI tools
5
5
  Author-email: Media Agent Team <team@mediaagent.com>
6
6
  Keywords: mcp,ai,media,video,image,processing