media-agent-mcp 2.6.13__py3-none-any.whl → 2.6.14__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.
@@ -163,15 +163,15 @@ class SessionManager:
163
163
  """Get session object by ID."""
164
164
  return self._sessions.get(session_id)
165
165
 
166
- def remove_session(self, session_id: str):
166
+ def remove_session(self, session_id: str, remove_route_mapping: bool = True):
167
167
  """Remove a session."""
168
168
  if session_id in self._sessions:
169
169
  del self._sessions[session_id]
170
- if session_id in self._session_routes:
170
+ if remove_route_mapping and session_id in self._session_routes:
171
171
  del self._session_routes[session_id]
172
172
  if session_id in self._session_timestamps:
173
173
  del self._session_timestamps[session_id]
174
- logger.info(f"Removed session: {session_id}")
174
+ logger.info(f"Removed session: {session_id} (route_mapping_removed: {remove_route_mapping})")
175
175
 
176
176
  def cleanup_expired_sessions(self, max_age_seconds: int = 3600):
177
177
  """Clean up sessions older than max_age_seconds."""
@@ -209,70 +209,25 @@ class SessionManager:
209
209
  # Global session manager
210
210
  session_manager = SessionManager()
211
211
 
212
- class SessionErrorHandlingMiddleware(BaseHTTPMiddleware):
213
- """Middleware to handle ClosedResourceError and auto-regenerate sessions."""
212
+ def _extract_session_id_from_url(url: str) -> Optional[str]:
213
+ """Extract session_id from URL."""
214
+ import re
215
+ from urllib.parse import urlparse, parse_qs
214
216
 
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
217
+ # Parse the URL
218
+ parsed = urlparse(url)
219
+
220
+ # Try to get from query parameters
221
+ query_params = parse_qs(parsed.query)
222
+ if 'session_id' in query_params:
223
+ return query_params['session_id'][0]
224
+
225
+ # Try to extract from URL path using regex
226
+ match = re.search(r'session_id=([a-f0-9]+)', url)
227
+ if match:
228
+ return match.group(1)
229
+
230
+ return None
276
231
 
277
232
  # Global exception handler for ClosedResourceError
278
233
  async def handle_closed_resource_error(request, exc):
@@ -288,7 +243,7 @@ async def handle_closed_resource_error(request, exc):
288
243
  # Generate new session ID
289
244
  new_session_id = session_manager.generate_session_id()
290
245
  session_manager.add_route_mapping(session_id, new_session_id)
291
- session_manager.remove_session(session_id)
246
+ session_manager.remove_session(session_id, remove_route_mapping=False)
292
247
 
293
248
  logger.info(f"Global handler: Generated new session {new_session_id} to replace {session_id}")
294
249
 
@@ -834,16 +789,13 @@ def main():
834
789
  mcp.settings.host = args.host
835
790
  mcp.settings.port = args.port
836
791
 
837
- # Get the SSE app and add session error handling middleware
792
+ # Get the SSE app and add global exception handler
838
793
  sse_app = mcp.sse_app()
839
794
 
840
- # Add session error handling middleware
841
- sse_app.add_middleware(SessionErrorHandlingMiddleware)
842
-
843
795
  # Add global exception handler for ClosedResourceError
844
796
  sse_app.add_exception_handler(anyio.ClosedResourceError, handle_closed_resource_error)
845
797
 
846
- logger.info("Added SessionErrorHandlingMiddleware and global ClosedResourceError handler for automatic session recovery")
798
+ logger.info("Added global ClosedResourceError handler for automatic session recovery")
847
799
 
848
800
  # Use uvicorn to run SSE app with extended keep-alive timeout (5 minutes)
849
801
  uvicorn.run(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: media-agent-mcp
3
- Version: 2.6.13
3
+ Version: 2.6.14
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,5 +1,5 @@
1
1
  media_agent_mcp/__init__.py,sha256=4GfH0flV1CGHefl-eNXt-Gidk7aDXA6Jlh2uVDOXGSo,312
2
- media_agent_mcp/async_server.py,sha256=eNw2sC7WT5AOjb_KIvfQobVYZ_h68vg_3en9zSfenrM,33332
2
+ media_agent_mcp/async_server.py,sha256=3y1Xse4lavfzuNKUD9AU-REzhlAc3Po42GNn2el6Pn8,31091
3
3
  media_agent_mcp/async_wrapper.py,sha256=hiiBhhz9WeVDfSBWVh6ovhf5jeP5ZbsieBbz9P-KPn0,15351
4
4
  media_agent_mcp/ai_models/__init__.py,sha256=2kHzTYwjQw89U4QGDq0e2WqJScqDkDNlDaWHGak5JeY,553
5
5
  media_agent_mcp/ai_models/omni_human.py,sha256=s_Ja4gEmHG_bgii1x4SoeV73lz0Zg_3iBRvu36goxVA,4643
@@ -43,8 +43,8 @@ media_agent_mcp/video/__init__.py,sha256=tfz22XEeFSeuKa3AggYCE0vCDt4IwXRCKW6avof
43
43
  media_agent_mcp/video/processor.py,sha256=twfqmN5DbVryjDawZUcqTUcnglcBJYpUbAnApqHgD0c,12787
44
44
  media_agent_mcp/video/stack.py,sha256=pyoJiJ9NhU1tjy2l3kARI9sWFoC00Fj97psxYOBi2NU,1736
45
45
  media_agent_mcp/video/subtitle.py,sha256=TlrWVhWJqYTUJpnVz7eccwMAn8ixfrRzRxS6ETMY-DM,16323
46
- media_agent_mcp-2.6.13.dist-info/METADATA,sha256=3Qo4BxxgAXZppQmTEZQpBazbpCUmYt6ssbnZeHMb5oU,11306
47
- media_agent_mcp-2.6.13.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
48
- media_agent_mcp-2.6.13.dist-info/entry_points.txt,sha256=qhOUwR-ORVf9GO7emhhl7Lgd6MISgqbZr8bEuSH_VdA,70
49
- media_agent_mcp-2.6.13.dist-info/top_level.txt,sha256=WEa0YfchpTxZgiKn8gdxYgs-dir5HepJaTOrxAGx9nY,16
50
- media_agent_mcp-2.6.13.dist-info/RECORD,,
46
+ media_agent_mcp-2.6.14.dist-info/METADATA,sha256=OrIMFu2iuILwbJ2sjRQp15v4Qm0_MnutbD7ocHDf5CU,11306
47
+ media_agent_mcp-2.6.14.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
48
+ media_agent_mcp-2.6.14.dist-info/entry_points.txt,sha256=qhOUwR-ORVf9GO7emhhl7Lgd6MISgqbZr8bEuSH_VdA,70
49
+ media_agent_mcp-2.6.14.dist-info/top_level.txt,sha256=WEa0YfchpTxZgiKn8gdxYgs-dir5HepJaTOrxAGx9nY,16
50
+ media_agent_mcp-2.6.14.dist-info/RECORD,,