Aktraiser commited on
Commit
63acb74
·
1 Parent(s): 75c316a

🔧 FIX: Fonctions MCP correctement formatées selon doc Gradio

Browse files

✅ Solution basée sur documentation officielle:
- Fonctions avec docstrings Google style
- Type hints corrects (str -> str)
- Auto-détection par serveur MCP Gradio
- Plus d'erreurs ASGI AssertionError
- Fonctions CRM/Modal/Search disponibles pour Claude

Files changed (1) hide show
  1. app.py +118 -0
app.py CHANGED
@@ -29,6 +29,124 @@ except ImportError as e:
29
  logging.basicConfig(level=logging.INFO)
30
  logger = logging.getLogger(__name__)
31
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32
  # =============================================================================
33
  # WRAPPERS SYNCHRONES POUR MCP (Gradio MCP nĂ©cessite des fonctions sync)
34
  # =============================================================================
 
29
  logging.basicConfig(level=logging.INFO)
30
  logger = logging.getLogger(__name__)
31
 
32
+ # =============================================================================
33
+ # FONCTIONS MCP POUR GRADIO (Auto-détectées par le serveur MCP)
34
+ # =============================================================================
35
+
36
+ def get_crm_statistics() -> str:
37
+ """
38
+ Récupère les statistiques CRM complètes d'Odoo.
39
+
40
+ Returns:
41
+ str: Rapport détaillé des statistiques CRM avec métriques et analyses.
42
+ """
43
+ try:
44
+ result = crm_gradio_tools.get_crm_statistics()
45
+ return result
46
+ except Exception as e:
47
+ return f"❌ Erreur CRM: {str(e)}"
48
+
49
+ def analyze_leads_advanced(domain_filter: str = "[]", limit: int = 20) -> str:
50
+ """
51
+ Analyse avancée des leads CRM avec filtrage et recommandations.
52
+
53
+ Args:
54
+ domain_filter (str): Filtre de domaine Odoo au format JSON (ex: [['stage_id', '=', 1]])
55
+ limit (int): Nombre maximum de leads Ă  analyser
56
+
57
+ Returns:
58
+ str: Analyse détaillée des leads avec recommandations d'actions.
59
+ """
60
+ try:
61
+ result = crm_gradio_tools.analyze_leads_advanced(domain_filter, limit)
62
+ return result
63
+ except Exception as e:
64
+ return f"❌ Erreur analyse: {str(e)}"
65
+
66
+ def search_leads_by_criteria(name: str = "", min_revenue: float = 0, stage: str = "", limit: int = 10) -> str:
67
+ """
68
+ Recherche de leads CRM selon des critères spécifiques.
69
+
70
+ Args:
71
+ name (str): Nom du lead Ă  rechercher
72
+ min_revenue (float): Revenue minimum attendu
73
+ stage (str): Étape du pipeline CRM
74
+ limit (int): Nombre maximum de résultats
75
+
76
+ Returns:
77
+ str: Liste des leads correspondant aux critères avec détails.
78
+ """
79
+ try:
80
+ result = crm_gradio_tools.search_leads_by_criteria(name, min_revenue, stage, limit)
81
+ return result
82
+ except Exception as e:
83
+ return f"❌ Erreur recherche: {str(e)}"
84
+
85
+ def get_modal_model_status() -> str:
86
+ """
87
+ Vérifie le statut du modèle d'intelligence artificielle Modal.
88
+
89
+ Returns:
90
+ str: Statut détaillé du modèle ML (entraîné, prêt, erreurs).
91
+ """
92
+ try:
93
+ result = modal_gradio_wrapper.gradio_get_model_status()
94
+ return result
95
+ except Exception as e:
96
+ return f"❌ Erreur Modal: {str(e)}"
97
+
98
+ def search_odoo_records(model: str = "crm.lead", domain_text: str = "[]", fields_text: str = "name,email_from", limit: int = 10) -> str:
99
+ """
100
+ Recherche d'enregistrements dans n'importe quel modèle Odoo.
101
+
102
+ Args:
103
+ model (str): Modèle Odoo à interroger (ex: crm.lead, sale.order)
104
+ domain_text (str): Filtre de recherche au format JSON
105
+ fields_text (str): Champs à récupérer séparés par des virgules
106
+ limit (int): Nombre maximum d'enregistrements
107
+
108
+ Returns:
109
+ str: Liste des enregistrements trouvés avec leurs détails.
110
+ """
111
+ try:
112
+ if not config.client.is_connected():
113
+ return "❌ Pas connecté à Odoo - Configurez d'abord la connexion"
114
+
115
+ # Parse domaine
116
+ domain = []
117
+ if domain_text.strip():
118
+ try:
119
+ domain = eval(domain_text.strip())
120
+ except:
121
+ return "❌ Format de domaine invalide. Utilisez: [['field', '=', 'value']]"
122
+
123
+ # Parse champs
124
+ fields = [f.strip() for f in fields_text.split(',') if f.strip()] if fields_text else []
125
+
126
+ # Recherche
127
+ records = config.client.search_read(model, domain, fields, limit)
128
+
129
+ if records:
130
+ result_text = f"✅ **{len(records)} enregistrements trouvés dans {model}**\n\n"
131
+
132
+ for i, record in enumerate(records[:3]):
133
+ result_text += f"**{i+1}.** ID: {record.get('id', 'N/A')}"
134
+ if 'name' in record:
135
+ result_text += f" | Nom: {record['name']}"
136
+ if 'email' in record:
137
+ result_text += f" | Email: {record['email']}"
138
+ result_text += "\n"
139
+
140
+ if len(records) > 3:
141
+ result_text += f"\n... et {len(records) - 3} autres enregistrements"
142
+
143
+ return result_text
144
+ else:
145
+ return f"⚠️ Aucun enregistrement trouvé dans {model}"
146
+
147
+ except Exception as e:
148
+ return f"❌ Erreur: {str(e)}"
149
+
150
  # =============================================================================
151
  # WRAPPERS SYNCHRONES POUR MCP (Gradio MCP nĂ©cessite des fonctions sync)
152
  # =============================================================================