LiamKhoaLe commited on
Commit
6e8bf5a
·
1 Parent(s): 8d74e9c

Use MCP defaults

Browse files
Files changed (1) hide show
  1. app.py +85 -44
app.py CHANGED
@@ -197,14 +197,74 @@ global_whisper_model = None
197
  global_tts_model = None
198
 
199
  # MCP client storage
200
- global_mcp_client = None
201
- global_mcp_context = None # Store the context manager
 
202
  # MCP server configuration via environment variables
203
  # Example: MCP_SERVER_COMMAND="python" MCP_SERVER_ARGS="-m duckduckgo_mcp_server"
204
  # Or: MCP_SERVER_COMMAND="npx" MCP_SERVER_ARGS="-y @modelcontextprotocol/server-duckduckgo"
205
  MCP_SERVER_COMMAND = os.environ.get("MCP_SERVER_COMMAND", "python")
206
  MCP_SERVER_ARGS = os.environ.get("MCP_SERVER_ARGS", "-m duckduckgo_mcp_server").split() if os.environ.get("MCP_SERVER_ARGS") else ["-m", "duckduckgo_mcp_server"]
207
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
208
  def initialize_translation_model():
209
  """Initialize DeepSeek-R1 model for translation purposes"""
210
  global global_translation_model, global_translation_tokenizer
@@ -310,18 +370,17 @@ def initialize_tts_model():
310
 
311
  async def transcribe_audio_mcp(audio_path: str) -> str:
312
  """Transcribe audio using MCP Whisper tool"""
313
- global global_mcp_client
314
-
315
  if not MCP_AVAILABLE:
316
  return ""
317
 
318
  try:
319
- # Initialize MCP client if needed
320
- if global_mcp_client is None:
 
321
  return ""
322
 
323
  # Find Whisper tool
324
- tools = await global_mcp_client.list_tools()
325
  whisper_tool = None
326
  for tool in tools.tools:
327
  if "whisper" in tool.name.lower() or "transcribe" in tool.name.lower() or "speech" in tool.name.lower():
@@ -330,7 +389,7 @@ async def transcribe_audio_mcp(audio_path: str) -> str:
330
  break
331
 
332
  if whisper_tool:
333
- result = await global_mcp_client.call_tool(
334
  whisper_tool.name,
335
  arguments={"audio_path": audio_path, "language": "en"}
336
  )
@@ -406,18 +465,17 @@ def transcribe_audio(audio):
406
 
407
  async def generate_speech_mcp(text: str) -> str:
408
  """Generate speech using MCP TTS tool"""
409
- global global_mcp_client
410
-
411
  if not MCP_AVAILABLE:
412
  return None
413
 
414
  try:
415
- # Initialize MCP client if needed
416
- if global_mcp_client is None:
 
417
  return None
418
 
419
  # Find TTS tool
420
- tools = await global_mcp_client.list_tools()
421
  tts_tool = None
422
  for tool in tools.tools:
423
  if "tts" in tool.name.lower() or "speech" in tool.name.lower() or "synthesize" in tool.name.lower():
@@ -426,7 +484,7 @@ async def generate_speech_mcp(text: str) -> str:
426
  break
427
 
428
  if tts_tool:
429
- result = await global_mcp_client.call_tool(
430
  tts_tool.name,
431
  arguments={"text": text, "language": "en"}
432
  )
@@ -538,18 +596,17 @@ def detect_language(text: str) -> str:
538
 
539
  async def translate_text_mcp(text: str, target_lang: str = "en", source_lang: str = None) -> str:
540
  """Translate text using MCP translation tool"""
541
- global global_mcp_client
542
-
543
  if not MCP_AVAILABLE:
544
  return ""
545
 
546
  try:
547
- # Initialize MCP client if needed
548
- if global_mcp_client is None:
 
549
  return ""
550
 
551
  # Find translation tool
552
- tools = await global_mcp_client.list_tools()
553
  translate_tool = None
554
  for tool in tools.tools:
555
  if "translate" in tool.name.lower() or "translation" in tool.name.lower():
@@ -562,7 +619,7 @@ async def translate_text_mcp(text: str, target_lang: str = "en", source_lang: st
562
  if source_lang:
563
  args["source_language"] = source_lang
564
 
565
- result = await global_mcp_client.call_tool(
566
  translate_tool.name,
567
  arguments=args
568
  )
@@ -637,36 +694,20 @@ def translate_text(text: str, target_lang: str = "en", source_lang: str = None)
637
 
638
  async def search_web_mcp(query: str, max_results: int = 5) -> list:
639
  """Search web using MCP tools"""
640
- global global_mcp_client, global_mcp_context
641
-
642
  if not MCP_AVAILABLE:
643
  logger.warning("MCP not available, falling back to direct search")
644
  return search_web_fallback(query, max_results)
645
 
646
  try:
647
- # Initialize MCP client if not already initialized
648
- if global_mcp_client is None:
649
- logger.info(f"Initializing MCP client with command: {MCP_SERVER_COMMAND} {MCP_SERVER_ARGS}")
650
- # Try to connect to MCP server
651
- # This assumes MCP server is running via stdio
652
- server_params = StdioServerParameters(
653
- command=MCP_SERVER_COMMAND,
654
- args=MCP_SERVER_ARGS
655
- )
656
- try:
657
- global_mcp_client = await stdio_client(server_params)
658
- await global_mcp_client.__aenter__()
659
- logger.info("MCP client initialized successfully")
660
- except Exception as e:
661
- logger.error(f"Failed to initialize MCP client: {e}")
662
- logger.info("Falling back to direct search. To use MCP, ensure MCP server is installed and configured.")
663
- global_mcp_client = None
664
- global_mcp_context = None
665
- return search_web_fallback(query, max_results)
666
 
667
  # Call MCP search tool
668
  try:
669
- tools = await global_mcp_client.list_tools()
670
  except Exception as e:
671
  logger.error(f"Failed to list MCP tools: {e}")
672
  return search_web_fallback(query, max_results)
@@ -681,7 +722,7 @@ async def search_web_mcp(query: str, max_results: int = 5) -> list:
681
  if search_tool:
682
  # Execute search via MCP
683
  try:
684
- result = await global_mcp_client.call_tool(
685
  search_tool.name,
686
  arguments={"query": query, "max_results": max_results}
687
  )
@@ -734,7 +775,7 @@ async def search_web_mcp(query: str, max_results: int = 5) -> list:
734
  if not item.get('url'):
735
  continue
736
  try:
737
- fetch_result = await global_mcp_client.call_tool(
738
  fetch_tool.name,
739
  arguments={"url": item['url']}
740
  )
 
197
  global_tts_model = None
198
 
199
  # MCP client storage
200
+ global_mcp_session = None
201
+ global_mcp_stdio_ctx = None # Store stdio context to keep it alive
202
+ global_mcp_lock = threading.Lock() # Lock for thread-safe session access
203
  # MCP server configuration via environment variables
204
  # Example: MCP_SERVER_COMMAND="python" MCP_SERVER_ARGS="-m duckduckgo_mcp_server"
205
  # Or: MCP_SERVER_COMMAND="npx" MCP_SERVER_ARGS="-y @modelcontextprotocol/server-duckduckgo"
206
  MCP_SERVER_COMMAND = os.environ.get("MCP_SERVER_COMMAND", "python")
207
  MCP_SERVER_ARGS = os.environ.get("MCP_SERVER_ARGS", "-m duckduckgo_mcp_server").split() if os.environ.get("MCP_SERVER_ARGS") else ["-m", "duckduckgo_mcp_server"]
208
 
209
+ async def get_mcp_session():
210
+ """Get or create MCP client session with proper context management"""
211
+ global global_mcp_session, global_mcp_stdio_ctx
212
+
213
+ if not MCP_AVAILABLE:
214
+ return None
215
+
216
+ # Check if session exists and is still valid
217
+ if global_mcp_session is not None:
218
+ try:
219
+ # Test if session is still alive by listing tools
220
+ await global_mcp_session.list_tools()
221
+ return global_mcp_session
222
+ except Exception as e:
223
+ logger.debug(f"Existing MCP session invalid, recreating: {e}")
224
+ # Clean up old session
225
+ try:
226
+ if global_mcp_session is not None:
227
+ await global_mcp_session.__aexit__(None, None, None)
228
+ except:
229
+ pass
230
+ try:
231
+ if global_mcp_stdio_ctx is not None:
232
+ await global_mcp_stdio_ctx.__aexit__(None, None, None)
233
+ except:
234
+ pass
235
+ global_mcp_session = None
236
+ global_mcp_stdio_ctx = None
237
+
238
+ # Create new session using correct MCP SDK pattern
239
+ try:
240
+ logger.info(f"Creating MCP client session with command: {MCP_SERVER_COMMAND} {MCP_SERVER_ARGS}")
241
+ server_params = StdioServerParameters(
242
+ command=MCP_SERVER_COMMAND,
243
+ args=MCP_SERVER_ARGS
244
+ )
245
+
246
+ # Correct MCP SDK usage: stdio_client is an async context manager
247
+ # that yields (read, write) streams
248
+ stdio_ctx = stdio_client(server_params)
249
+ read, write = await stdio_ctx.__aenter__()
250
+
251
+ # Create ClientSession from the streams
252
+ session = ClientSession(read, write)
253
+ await session.__aenter__()
254
+
255
+ # Store both the session and stdio context to keep them alive
256
+ global_mcp_session = session
257
+ global_mcp_stdio_ctx = stdio_ctx
258
+ logger.info("MCP client session created successfully")
259
+ return session
260
+ except Exception as e:
261
+ logger.error(f"Failed to create MCP client session: {e}")
262
+ import traceback
263
+ logger.debug(traceback.format_exc())
264
+ global_mcp_session = None
265
+ global_mcp_stdio_ctx = None
266
+ return None
267
+
268
  def initialize_translation_model():
269
  """Initialize DeepSeek-R1 model for translation purposes"""
270
  global global_translation_model, global_translation_tokenizer
 
370
 
371
  async def transcribe_audio_mcp(audio_path: str) -> str:
372
  """Transcribe audio using MCP Whisper tool"""
 
 
373
  if not MCP_AVAILABLE:
374
  return ""
375
 
376
  try:
377
+ # Get MCP session
378
+ session = await get_mcp_session()
379
+ if session is None:
380
  return ""
381
 
382
  # Find Whisper tool
383
+ tools = await session.list_tools()
384
  whisper_tool = None
385
  for tool in tools.tools:
386
  if "whisper" in tool.name.lower() or "transcribe" in tool.name.lower() or "speech" in tool.name.lower():
 
389
  break
390
 
391
  if whisper_tool:
392
+ result = await session.call_tool(
393
  whisper_tool.name,
394
  arguments={"audio_path": audio_path, "language": "en"}
395
  )
 
465
 
466
  async def generate_speech_mcp(text: str) -> str:
467
  """Generate speech using MCP TTS tool"""
 
 
468
  if not MCP_AVAILABLE:
469
  return None
470
 
471
  try:
472
+ # Get MCP session
473
+ session = await get_mcp_session()
474
+ if session is None:
475
  return None
476
 
477
  # Find TTS tool
478
+ tools = await session.list_tools()
479
  tts_tool = None
480
  for tool in tools.tools:
481
  if "tts" in tool.name.lower() or "speech" in tool.name.lower() or "synthesize" in tool.name.lower():
 
484
  break
485
 
486
  if tts_tool:
487
+ result = await session.call_tool(
488
  tts_tool.name,
489
  arguments={"text": text, "language": "en"}
490
  )
 
596
 
597
  async def translate_text_mcp(text: str, target_lang: str = "en", source_lang: str = None) -> str:
598
  """Translate text using MCP translation tool"""
 
 
599
  if not MCP_AVAILABLE:
600
  return ""
601
 
602
  try:
603
+ # Get MCP session
604
+ session = await get_mcp_session()
605
+ if session is None:
606
  return ""
607
 
608
  # Find translation tool
609
+ tools = await session.list_tools()
610
  translate_tool = None
611
  for tool in tools.tools:
612
  if "translate" in tool.name.lower() or "translation" in tool.name.lower():
 
619
  if source_lang:
620
  args["source_language"] = source_lang
621
 
622
+ result = await session.call_tool(
623
  translate_tool.name,
624
  arguments=args
625
  )
 
694
 
695
  async def search_web_mcp(query: str, max_results: int = 5) -> list:
696
  """Search web using MCP tools"""
 
 
697
  if not MCP_AVAILABLE:
698
  logger.warning("MCP not available, falling back to direct search")
699
  return search_web_fallback(query, max_results)
700
 
701
  try:
702
+ # Get MCP session
703
+ session = await get_mcp_session()
704
+ if session is None:
705
+ logger.warning("Failed to get MCP session, falling back to direct search")
706
+ return search_web_fallback(query, max_results)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
707
 
708
  # Call MCP search tool
709
  try:
710
+ tools = await session.list_tools()
711
  except Exception as e:
712
  logger.error(f"Failed to list MCP tools: {e}")
713
  return search_web_fallback(query, max_results)
 
722
  if search_tool:
723
  # Execute search via MCP
724
  try:
725
+ result = await session.call_tool(
726
  search_tool.name,
727
  arguments={"query": query, "max_results": max_results}
728
  )
 
775
  if not item.get('url'):
776
  continue
777
  try:
778
+ fetch_result = await session.call_tool(
779
  fetch_tool.name,
780
  arguments={"url": item['url']}
781
  )