malek-messaoudii commited on
Commit
997d57e
·
1 Parent(s): dd55f1d

Enhance MCP tool performance by implementing asynchronous handling in tool calls

Browse files
Files changed (1) hide show
  1. routes/mcp_routes.py +103 -31
routes/mcp_routes.py CHANGED
@@ -4,6 +4,7 @@ from fastapi import APIRouter, HTTPException
4
  from typing import Dict, Any, Optional
5
  from pydantic import BaseModel, Field
6
  import logging
 
7
 
8
  from services.mcp_service import mcp_server
9
  from models.mcp_models import ToolListResponse, ToolInfo, ToolCallRequest, ToolCallResponse
@@ -191,17 +192,27 @@ async def call_mcp_tool(request: ToolCallRequest):
191
  """Appelle un outil MCP par son nom avec des arguments"""
192
  try:
193
  result = await mcp_server.call_tool(request.tool_name, request.arguments)
194
- # Gérer différents types de retours
195
  if isinstance(result, dict):
196
- final_result = result
 
 
 
 
 
 
 
 
 
 
 
197
  elif isinstance(result, (list, tuple)) and len(result) > 0:
198
  # Si c'est une liste de ContentBlock, extraire le contenu
199
- if hasattr(result[0], 'text'):
200
- import json
201
  try:
202
- final_result = json.loads(result[0].text) if result[0].text else {}
203
  except json.JSONDecodeError:
204
- final_result = {"text": result[0].text} if result[0].text else {}
205
  else:
206
  final_result = {"result": result[0] if result else {}}
207
  else:
@@ -232,19 +243,29 @@ async def mcp_detect_stance(request: DetectStanceRequest) -> Dict[str, Any]:
232
  "topic": request.topic,
233
  "argument": request.argument
234
  })
235
- # Gérer différents types de retours
236
  if isinstance(result, dict):
 
 
 
 
 
 
 
 
237
  return result
238
  elif isinstance(result, (list, tuple)) and len(result) > 0:
239
  # Si c'est une liste de ContentBlock, extraire le contenu
240
- if hasattr(result[0], 'text'):
241
- import json
242
- return json.loads(result[0].text) if result[0].text else {}
 
 
243
  return {"result": result[0] if result else {}}
244
  return {"result": result}
245
  except Exception as e:
246
  logger.error(f"Error in detect_stance: {e}")
247
- raise HTTPException(status_code=500, detail=str(e))
248
 
249
  @router.post("/tools/match-keypoint", summary="Matcher un argument avec un keypoint")
250
  async def mcp_match_keypoint(request: MatchKeypointRequest) -> Dict[str, Any]:
@@ -254,18 +275,28 @@ async def mcp_match_keypoint(request: MatchKeypointRequest) -> Dict[str, Any]:
254
  "argument": request.argument,
255
  "key_point": request.key_point
256
  })
257
- # Gérer différents types de retours
258
  if isinstance(result, dict):
 
 
 
 
 
 
 
 
259
  return result
260
  elif isinstance(result, (list, tuple)) and len(result) > 0:
261
- if hasattr(result[0], 'text'):
262
- import json
263
- return json.loads(result[0].text) if result[0].text else {}
 
 
264
  return {"result": result[0] if result else {}}
265
  return {"result": result}
266
  except Exception as e:
267
  logger.error(f"Error in match_keypoint_argument: {e}")
268
- raise HTTPException(status_code=500, detail=str(e))
269
 
270
  @router.post("/tools/transcribe-audio", summary="Transcrire un audio en texte")
271
  async def mcp_transcribe_audio(request: TranscribeAudioRequest) -> Dict[str, str]:
@@ -274,17 +305,30 @@ async def mcp_transcribe_audio(request: TranscribeAudioRequest) -> Dict[str, str
274
  result = await mcp_server.call_tool("transcribe_audio", {
275
  "audio_path": request.audio_path
276
  })
277
- # Gérer différents types de retours
278
- if isinstance(result, str):
 
 
 
 
 
 
 
 
 
 
279
  return {"text": result}
280
  elif isinstance(result, (list, tuple)) and len(result) > 0:
281
  if hasattr(result[0], 'text'):
282
  return {"text": result[0].text}
283
  return {"text": str(result[0])}
284
  return {"text": str(result)}
 
 
 
285
  except Exception as e:
286
  logger.error(f"Error in transcribe_audio: {e}")
287
- raise HTTPException(status_code=500, detail=str(e))
288
 
289
  @router.post("/tools/generate-speech", summary="Générer de la parole à partir de texte")
290
  async def mcp_generate_speech(request: GenerateSpeechRequest) -> Dict[str, str]:
@@ -295,8 +339,18 @@ async def mcp_generate_speech(request: GenerateSpeechRequest) -> Dict[str, str]:
295
  "voice": request.voice,
296
  "format": request.format
297
  })
298
- # Gérer différents types de retours
299
- if isinstance(result, str):
 
 
 
 
 
 
 
 
 
 
300
  return {"audio_path": result}
301
  elif isinstance(result, (list, tuple)) and len(result) > 0:
302
  if hasattr(result[0], 'text'):
@@ -305,7 +359,7 @@ async def mcp_generate_speech(request: GenerateSpeechRequest) -> Dict[str, str]:
305
  return {"audio_path": str(result)}
306
  except Exception as e:
307
  logger.error(f"Error in generate_speech: {e}")
308
- raise HTTPException(status_code=500, detail=str(e))
309
 
310
  @router.post("/tools/generate-argument", summary="Générer un argument de débat")
311
  async def mcp_generate_argument(request: GenerateArgumentRequest) -> Dict[str, str]:
@@ -315,8 +369,18 @@ async def mcp_generate_argument(request: GenerateArgumentRequest) -> Dict[str, s
315
  "user_input": request.user_input,
316
  "conversation_id": request.conversation_id
317
  })
318
- # Gérer différents types de retours
319
- if isinstance(result, str):
 
 
 
 
 
 
 
 
 
 
320
  return {"argument": result}
321
  elif isinstance(result, (list, tuple)) and len(result) > 0:
322
  if hasattr(result[0], 'text'):
@@ -325,25 +389,33 @@ async def mcp_generate_argument(request: GenerateArgumentRequest) -> Dict[str, s
325
  return {"argument": str(result)}
326
  except Exception as e:
327
  logger.error(f"Error in generate_argument: {e}")
328
- raise HTTPException(status_code=500, detail=str(e))
329
 
330
  @router.get("/tools/health-check", summary="Health check MCP (outil)")
331
  async def mcp_tool_health_check() -> Dict[str, Any]:
332
  """Health check via l'outil MCP"""
333
  try:
334
  result = await mcp_server.call_tool("health_check", {})
335
- # Gérer différents types de retours
 
336
  if isinstance(result, dict):
 
 
 
 
 
 
 
 
337
  return result
338
  elif isinstance(result, (list, tuple)) and len(result) > 0:
339
- if hasattr(result[0], 'text'):
340
- import json
341
  try:
342
- return json.loads(result[0].text) if result[0].text else {}
343
  except json.JSONDecodeError:
344
- return {"text": result[0].text} if result[0].text else {}
345
  return {"result": result[0] if result else {}}
346
  return {"result": result}
347
  except Exception as e:
348
  logger.error(f"Error in health_check tool: {e}")
349
- raise HTTPException(status_code=500, detail=str(e))
 
4
  from typing import Dict, Any, Optional
5
  from pydantic import BaseModel, Field
6
  import logging
7
+ import json
8
 
9
  from services.mcp_service import mcp_server
10
  from models.mcp_models import ToolListResponse, ToolInfo, ToolCallRequest, ToolCallResponse
 
192
  """Appelle un outil MCP par son nom avec des arguments"""
193
  try:
194
  result = await mcp_server.call_tool(request.tool_name, request.arguments)
195
+ # Gérer différents types de retours MCP
196
  if isinstance(result, dict):
197
+ # Si le résultat contient une clé "result" avec une liste de ContentBlock
198
+ if "result" in result and isinstance(result["result"], list) and len(result["result"]) > 0:
199
+ content_block = result["result"][0]
200
+ if hasattr(content_block, 'text') and content_block.text:
201
+ try:
202
+ final_result = json.loads(content_block.text)
203
+ except json.JSONDecodeError:
204
+ final_result = {"text": content_block.text}
205
+ else:
206
+ final_result = result
207
+ else:
208
+ final_result = result
209
  elif isinstance(result, (list, tuple)) and len(result) > 0:
210
  # Si c'est une liste de ContentBlock, extraire le contenu
211
+ if hasattr(result[0], 'text') and result[0].text:
 
212
  try:
213
+ final_result = json.loads(result[0].text)
214
  except json.JSONDecodeError:
215
+ final_result = {"text": result[0].text}
216
  else:
217
  final_result = {"result": result[0] if result else {}}
218
  else:
 
243
  "topic": request.topic,
244
  "argument": request.argument
245
  })
246
+ # Gérer différents types de retours MCP
247
  if isinstance(result, dict):
248
+ # Si le résultat contient une clé "result" avec une liste de ContentBlock
249
+ if "result" in result and isinstance(result["result"], list) and len(result["result"]) > 0:
250
+ content_block = result["result"][0]
251
+ if hasattr(content_block, 'text') and content_block.text:
252
+ try:
253
+ return json.loads(content_block.text)
254
+ except json.JSONDecodeError:
255
+ return {"text": content_block.text}
256
  return result
257
  elif isinstance(result, (list, tuple)) and len(result) > 0:
258
  # Si c'est une liste de ContentBlock, extraire le contenu
259
+ if hasattr(result[0], 'text') and result[0].text:
260
+ try:
261
+ return json.loads(result[0].text)
262
+ except json.JSONDecodeError:
263
+ return {"text": result[0].text}
264
  return {"result": result[0] if result else {}}
265
  return {"result": result}
266
  except Exception as e:
267
  logger.error(f"Error in detect_stance: {e}")
268
+ raise HTTPException(status_code=500, detail=f"Error executing tool detect_stance: {e}")
269
 
270
  @router.post("/tools/match-keypoint", summary="Matcher un argument avec un keypoint")
271
  async def mcp_match_keypoint(request: MatchKeypointRequest) -> Dict[str, Any]:
 
275
  "argument": request.argument,
276
  "key_point": request.key_point
277
  })
278
+ # Gérer différents types de retours MCP
279
  if isinstance(result, dict):
280
+ # Si le résultat contient une clé "result" avec une liste de ContentBlock
281
+ if "result" in result and isinstance(result["result"], list) and len(result["result"]) > 0:
282
+ content_block = result["result"][0]
283
+ if hasattr(content_block, 'text') and content_block.text:
284
+ try:
285
+ return json.loads(content_block.text)
286
+ except json.JSONDecodeError:
287
+ return {"text": content_block.text}
288
  return result
289
  elif isinstance(result, (list, tuple)) and len(result) > 0:
290
+ if hasattr(result[0], 'text') and result[0].text:
291
+ try:
292
+ return json.loads(result[0].text)
293
+ except json.JSONDecodeError:
294
+ return {"text": result[0].text}
295
  return {"result": result[0] if result else {}}
296
  return {"result": result}
297
  except Exception as e:
298
  logger.error(f"Error in match_keypoint_argument: {e}")
299
+ raise HTTPException(status_code=500, detail=f"Error executing tool match_keypoint_argument: {e}")
300
 
301
  @router.post("/tools/transcribe-audio", summary="Transcrire un audio en texte")
302
  async def mcp_transcribe_audio(request: TranscribeAudioRequest) -> Dict[str, str]:
 
305
  result = await mcp_server.call_tool("transcribe_audio", {
306
  "audio_path": request.audio_path
307
  })
308
+ # Gérer différents types de retours MCP
309
+ if isinstance(result, dict):
310
+ # Si le résultat contient une clé "result" avec une liste de ContentBlock
311
+ if "result" in result and isinstance(result["result"], list) and len(result["result"]) > 0:
312
+ content_block = result["result"][0]
313
+ if hasattr(content_block, 'text'):
314
+ return {"text": content_block.text}
315
+ # Si c'est un dict simple, essayer d'extraire le texte
316
+ if "text" in result:
317
+ return {"text": result["text"]}
318
+ return {"text": str(result)}
319
+ elif isinstance(result, str):
320
  return {"text": result}
321
  elif isinstance(result, (list, tuple)) and len(result) > 0:
322
  if hasattr(result[0], 'text'):
323
  return {"text": result[0].text}
324
  return {"text": str(result[0])}
325
  return {"text": str(result)}
326
+ except FileNotFoundError as e:
327
+ logger.error(f"File not found in transcribe_audio: {e}")
328
+ raise HTTPException(status_code=500, detail=f"Error executing tool transcribe_audio: {e}")
329
  except Exception as e:
330
  logger.error(f"Error in transcribe_audio: {e}")
331
+ raise HTTPException(status_code=500, detail=f"Error executing tool transcribe_audio: {e}")
332
 
333
  @router.post("/tools/generate-speech", summary="Générer de la parole à partir de texte")
334
  async def mcp_generate_speech(request: GenerateSpeechRequest) -> Dict[str, str]:
 
339
  "voice": request.voice,
340
  "format": request.format
341
  })
342
+ # Gérer différents types de retours MCP
343
+ if isinstance(result, dict):
344
+ # Si le résultat contient une clé "result" avec une liste de ContentBlock
345
+ if "result" in result and isinstance(result["result"], list) and len(result["result"]) > 0:
346
+ content_block = result["result"][0]
347
+ if hasattr(content_block, 'text'):
348
+ return {"audio_path": content_block.text}
349
+ # Si c'est un dict simple, essayer d'extraire le chemin
350
+ if "audio_path" in result:
351
+ return {"audio_path": result["audio_path"]}
352
+ return {"audio_path": str(result)}
353
+ elif isinstance(result, str):
354
  return {"audio_path": result}
355
  elif isinstance(result, (list, tuple)) and len(result) > 0:
356
  if hasattr(result[0], 'text'):
 
359
  return {"audio_path": str(result)}
360
  except Exception as e:
361
  logger.error(f"Error in generate_speech: {e}")
362
+ raise HTTPException(status_code=500, detail=f"Error executing tool generate_speech: {e}")
363
 
364
  @router.post("/tools/generate-argument", summary="Générer un argument de débat")
365
  async def mcp_generate_argument(request: GenerateArgumentRequest) -> Dict[str, str]:
 
369
  "user_input": request.user_input,
370
  "conversation_id": request.conversation_id
371
  })
372
+ # Gérer différents types de retours MCP
373
+ if isinstance(result, dict):
374
+ # Si le résultat contient une clé "result" avec une liste de ContentBlock
375
+ if "result" in result and isinstance(result["result"], list) and len(result["result"]) > 0:
376
+ content_block = result["result"][0]
377
+ if hasattr(content_block, 'text'):
378
+ return {"argument": content_block.text}
379
+ # Si c'est un dict simple, essayer d'extraire l'argument
380
+ if "argument" in result:
381
+ return {"argument": result["argument"]}
382
+ return {"argument": str(result)}
383
+ elif isinstance(result, str):
384
  return {"argument": result}
385
  elif isinstance(result, (list, tuple)) and len(result) > 0:
386
  if hasattr(result[0], 'text'):
 
389
  return {"argument": str(result)}
390
  except Exception as e:
391
  logger.error(f"Error in generate_argument: {e}")
392
+ raise HTTPException(status_code=500, detail=f"Error executing tool generate_argument: {e}")
393
 
394
  @router.get("/tools/health-check", summary="Health check MCP (outil)")
395
  async def mcp_tool_health_check() -> Dict[str, Any]:
396
  """Health check via l'outil MCP"""
397
  try:
398
  result = await mcp_server.call_tool("health_check", {})
399
+ # Gérer différents types de retours MCP
400
+ import json
401
  if isinstance(result, dict):
402
+ # Si le résultat contient une clé "result" avec une liste de ContentBlock
403
+ if "result" in result and isinstance(result["result"], list) and len(result["result"]) > 0:
404
+ content_block = result["result"][0]
405
+ if hasattr(content_block, 'text') and content_block.text:
406
+ try:
407
+ return json.loads(content_block.text)
408
+ except json.JSONDecodeError:
409
+ return {"text": content_block.text}
410
  return result
411
  elif isinstance(result, (list, tuple)) and len(result) > 0:
412
+ if hasattr(result[0], 'text') and result[0].text:
 
413
  try:
414
+ return json.loads(result[0].text)
415
  except json.JSONDecodeError:
416
+ return {"text": result[0].text}
417
  return {"result": result[0] if result else {}}
418
  return {"result": result}
419
  except Exception as e:
420
  logger.error(f"Error in health_check tool: {e}")
421
+ raise HTTPException(status_code=500, detail=f"Error executing tool health_check: {e}")