malek-messaoudii commited on
Commit
b36d7d0
·
1 Parent(s): f171734

Refactor MCP tool handling to use hardcoded tool definitions and improve return value handling in health check and tool calls

Browse files
Files changed (2) hide show
  1. routes/mcp_routes.py +135 -18
  2. services/mcp_service.py +9 -2
routes/mcp_routes.py CHANGED
@@ -86,8 +86,15 @@ class GenerateArgumentRequest(BaseModel):
86
  async def mcp_health():
87
  """Health check pour le serveur MCP"""
88
  try:
89
- tools = mcp_server.list_tools()
90
- tool_names = [tool.name for tool in tools] if tools else []
 
 
 
 
 
 
 
91
  return {
92
  "status": "healthy",
93
  "tools": tool_names,
@@ -101,15 +108,78 @@ async def mcp_health():
101
  async def list_mcp_tools():
102
  """Liste tous les outils MCP disponibles"""
103
  try:
104
- tools = mcp_server.list_tools()
105
- tool_list = []
106
- for tool in tools:
107
- tool_info = ToolInfo(
108
- name=tool.name,
109
- description=tool.description or "",
110
- input_schema=tool.inputSchema if hasattr(tool, 'inputSchema') else {}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
111
  )
112
- tool_list.append(tool_info)
113
 
114
  return ToolListResponse(tools=tool_list, count=len(tool_list))
115
  except Exception as e:
@@ -121,12 +191,25 @@ async def call_mcp_tool(request: ToolCallRequest):
121
  """Appelle un outil MCP par son nom avec des arguments"""
122
  try:
123
  result = mcp_server.call_tool(request.tool_name, request.arguments)
124
- # Convertir en dict si nécessaire
125
- if not isinstance(result, dict):
126
- result = {"result": result}
 
 
 
 
 
 
 
 
 
 
 
 
 
127
  return ToolCallResponse(
128
  success=True,
129
- result=result,
130
  tool_name=request.tool_name
131
  )
132
  except Exception as e:
@@ -144,13 +227,20 @@ async def call_mcp_tool(request: ToolCallRequest):
144
  async def mcp_detect_stance(request: DetectStanceRequest) -> Dict[str, Any]:
145
  """Détecte si un argument est PRO ou CON pour un topic donné"""
146
  try:
 
147
  result = mcp_server.call_tool("detect_stance", {
148
  "topic": request.topic,
149
  "argument": request.argument
150
  })
151
- # S'assurer que le résultat est un dict
152
  if isinstance(result, dict):
153
  return result
 
 
 
 
 
 
154
  return {"result": result}
155
  except Exception as e:
156
  logger.error(f"Error in detect_stance: {e}")
@@ -164,8 +254,14 @@ async def mcp_match_keypoint(request: MatchKeypointRequest) -> Dict[str, Any]:
164
  "argument": request.argument,
165
  "key_point": request.key_point
166
  })
 
167
  if isinstance(result, dict):
168
  return result
 
 
 
 
 
169
  return {"result": result}
170
  except Exception as e:
171
  logger.error(f"Error in match_keypoint_argument: {e}")
@@ -178,9 +274,13 @@ async def mcp_transcribe_audio(request: TranscribeAudioRequest) -> Dict[str, str
178
  result = mcp_server.call_tool("transcribe_audio", {
179
  "audio_path": request.audio_path
180
  })
181
- # Le résultat est déjà une string
182
  if isinstance(result, str):
183
  return {"text": result}
 
 
 
 
184
  return {"text": str(result)}
185
  except Exception as e:
186
  logger.error(f"Error in transcribe_audio: {e}")
@@ -195,9 +295,13 @@ async def mcp_generate_speech(request: GenerateSpeechRequest) -> Dict[str, str]:
195
  "voice": request.voice,
196
  "format": request.format
197
  })
198
- # Le résultat est déjà une string (chemin du fichier)
199
  if isinstance(result, str):
200
  return {"audio_path": result}
 
 
 
 
201
  return {"audio_path": str(result)}
202
  except Exception as e:
203
  logger.error(f"Error in generate_speech: {e}")
@@ -211,9 +315,13 @@ async def mcp_generate_argument(request: GenerateArgumentRequest) -> Dict[str, s
211
  "user_input": request.user_input,
212
  "conversation_id": request.conversation_id
213
  })
214
- # Le résultat est déjà une string
215
  if isinstance(result, str):
216
  return {"argument": result}
 
 
 
 
217
  return {"argument": str(result)}
218
  except Exception as e:
219
  logger.error(f"Error in generate_argument: {e}")
@@ -224,8 +332,17 @@ async def mcp_tool_health_check() -> Dict[str, Any]:
224
  """Health check via l'outil MCP"""
225
  try:
226
  result = mcp_server.call_tool("health_check", {})
 
227
  if isinstance(result, dict):
228
  return result
 
 
 
 
 
 
 
 
229
  return {"result": result}
230
  except Exception as e:
231
  logger.error(f"Error in health_check tool: {e}")
 
86
  async def mcp_health():
87
  """Health check pour le serveur MCP"""
88
  try:
89
+ # Liste hardcodée des outils disponibles (plus fiable)
90
+ tool_names = [
91
+ "detect_stance",
92
+ "match_keypoint_argument",
93
+ "transcribe_audio",
94
+ "generate_speech",
95
+ "generate_argument",
96
+ "health_check"
97
+ ]
98
  return {
99
  "status": "healthy",
100
  "tools": tool_names,
 
108
  async def list_mcp_tools():
109
  """Liste tous les outils MCP disponibles"""
110
  try:
111
+ # Définir manuellement les outils avec leurs schémas
112
+ tool_list = [
113
+ ToolInfo(
114
+ name="detect_stance",
115
+ description="Détecte si un argument est PRO ou CON pour un topic donné",
116
+ input_schema={
117
+ "type": "object",
118
+ "properties": {
119
+ "topic": {"type": "string", "description": "Le sujet du débat"},
120
+ "argument": {"type": "string", "description": "L'argument à analyser"}
121
+ },
122
+ "required": ["topic", "argument"]
123
+ }
124
+ ),
125
+ ToolInfo(
126
+ name="match_keypoint_argument",
127
+ description="Détermine si un argument correspond à un keypoint",
128
+ input_schema={
129
+ "type": "object",
130
+ "properties": {
131
+ "argument": {"type": "string", "description": "L'argument à évaluer"},
132
+ "key_point": {"type": "string", "description": "Le keypoint de référence"}
133
+ },
134
+ "required": ["argument", "key_point"]
135
+ }
136
+ ),
137
+ ToolInfo(
138
+ name="transcribe_audio",
139
+ description="Convertit un fichier audio en texte",
140
+ input_schema={
141
+ "type": "object",
142
+ "properties": {
143
+ "audio_path": {"type": "string", "description": "Chemin vers le fichier audio"}
144
+ },
145
+ "required": ["audio_path"]
146
+ }
147
+ ),
148
+ ToolInfo(
149
+ name="generate_speech",
150
+ description="Convertit du texte en fichier audio",
151
+ input_schema={
152
+ "type": "object",
153
+ "properties": {
154
+ "text": {"type": "string", "description": "Texte à convertir en parole"},
155
+ "voice": {"type": "string", "description": "Voix à utiliser", "default": "Aaliyah-PlayAI"},
156
+ "format": {"type": "string", "description": "Format audio", "default": "wav"}
157
+ },
158
+ "required": ["text"]
159
+ }
160
+ ),
161
+ ToolInfo(
162
+ name="generate_argument",
163
+ description="Génère un argument de débat à partir d'un input utilisateur",
164
+ input_schema={
165
+ "type": "object",
166
+ "properties": {
167
+ "user_input": {"type": "string", "description": "Input utilisateur pour générer l'argument"},
168
+ "conversation_id": {"type": "string", "description": "ID de conversation (optionnel)"}
169
+ },
170
+ "required": ["user_input"]
171
+ }
172
+ ),
173
+ ToolInfo(
174
+ name="health_check",
175
+ description="Health check pour le serveur MCP",
176
+ input_schema={
177
+ "type": "object",
178
+ "properties": {},
179
+ "required": []
180
+ }
181
  )
182
+ ]
183
 
184
  return ToolListResponse(tools=tool_list, count=len(tool_list))
185
  except Exception as e:
 
191
  """Appelle un outil MCP par son nom avec des arguments"""
192
  try:
193
  result = 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:
208
+ final_result = {"result": result}
209
+
210
  return ToolCallResponse(
211
  success=True,
212
+ result=final_result,
213
  tool_name=request.tool_name
214
  )
215
  except Exception as e:
 
227
  async def mcp_detect_stance(request: DetectStanceRequest) -> Dict[str, Any]:
228
  """Détecte si un argument est PRO ou CON pour un topic donné"""
229
  try:
230
+ # Appeler directement via call_tool
231
  result = mcp_server.call_tool("detect_stance", {
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}")
 
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}")
 
274
  result = 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}")
 
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'):
303
+ return {"audio_path": result[0].text}
304
+ return {"audio_path": str(result[0])}
305
  return {"audio_path": str(result)}
306
  except Exception as e:
307
  logger.error(f"Error in generate_speech: {e}")
 
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'):
323
+ return {"argument": result[0].text}
324
+ return {"argument": str(result[0])}
325
  return {"argument": str(result)}
326
  except Exception as e:
327
  logger.error(f"Error in generate_argument: {e}")
 
332
  """Health check via l'outil MCP"""
333
  try:
334
  result = 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}")
services/mcp_service.py CHANGED
@@ -63,8 +63,15 @@ def get_debate_prompt() -> str:
63
  def health_check() -> Dict[str, Any]:
64
  """Health check pour le serveur MCP"""
65
  try:
66
- tools = mcp_server.list_tools()
67
- tool_names = [tool.name for tool in tools] if tools else []
 
 
 
 
 
 
 
68
  except Exception:
69
  tool_names = []
70
  return {"status": "healthy", "tools": tool_names}
 
63
  def health_check() -> Dict[str, Any]:
64
  """Health check pour le serveur MCP"""
65
  try:
66
+ # Liste hardcodée pour éviter les problèmes avec list_tools()
67
+ tool_names = [
68
+ "detect_stance",
69
+ "match_keypoint_argument",
70
+ "transcribe_audio",
71
+ "generate_speech",
72
+ "generate_argument",
73
+ "health_check"
74
+ ]
75
  except Exception:
76
  tool_names = []
77
  return {"status": "healthy", "tools": tool_names}