fispro-mcp
# fispro-mcp
Serveur [MCP](https://modelcontextprotocol.io) pour **[FisPro](https://www.fispro.org)**, le logiciel libre de systèmes d'inférence floue développé par l'INRAE et l'Institut Agro (Serge Guillaume, Brigitte Charnomordic).
Il permet à un assistant compatible MCP — Claude Desktop, Claude Code, Cursor, VS Code… — de lire vos fichiers `.fis`, d'exécuter des inférences, et surtout **d'expliquer quelles règles se déclenchent et pourquoi**. C'est là tout l'intérêt : la logique floue produit des modèles interprétables, encore faut-il pouvoir interroger cette interprétabilité en langage naturel.
```
Vous : Pourquoi mon système recommande 55 minutes d'arrosage à 15 % d'humidité et 32 °C ?
Claude: [explain_inference] Une seule règle se déclenche, R1 (« SI humidite_sol est sec
ET temperature est chaude »), avec une force de 0,625 — le sol est « sec » à 62,5 %
et la température « chaude » à 100 %. Comme aucune autre règle n'est active, la
sortie vaut exactement le conséquent de R1, soit 55.
```
## Deux dialectes `.fis`
Le format `.fis` existe en deux variantes, et le serveur lit les deux — le
dialecte est détecté à la lecture et exposé dans `describe_fis`.
| | MATLAB | FisPro natif |
|---|---|---|
| Écrit par | Fuzzy Logic Toolbox, exports tiers | **le logiciel FisPro lui-même** |
| Compteurs | `NumInputs`, `NumMFs` | `Ninputs`, `NMFs`, `Nexceptions` |
| Opérateur ET | `AndMethod` dans `[System]` | `Conjunction` dans `[System]` |
| Défuzzification | `DefuzzMethod` dans `[System]` | `Defuzzification` dans `[Output*]` |
| Agrégation | `AggMethod` | `Disjunction` dans `[Output*]` |
| Sous-ensemble | `MF1='sec':'trimf',[0 0 40]` | `MF1='sec','triangular',[0 0 40]` |
| Règle | `1 2, 4 (1) : 1` | `1, 2, 4.000 ,` |
| Formes | `trimf`, `trapmf`, `gaussmf`, `gbellmf`, `si`, `sd` | `triangular`, `trapezoidal`, `SemiTrapezoidalInf/Sup`, `door` |
En dialecte FisPro, une sortie `Nature='crisp'` porte ses conclusions
directement dans les règles (Sugeno d'ordre 0) ; une sortie `Nature='fuzzy'` se
défuzzifie sur une surface. `Disjunction` décide du sort des règles qui
partagent une conclusion : `max` les fusionne au degré le plus fort, `sum` les
additionne — un choix qui change le résultat, pas un détail.
Les opérateurs `area`, `MeanMax`, `MaxCrisp` et `sugeno` de FisPro sont calculés
analytiquement, sans discrétisation. Sur le contrôleur de chauffage de
référence, les dix combinaisons possibles donnent la même valeur que le moteur
C++ officiel, au dernier chiffre affiché.
## Deux moteurs, deux usages
| | Moteur R (`FisPro` sur CRAN) | Moteur Python (intégré) |
|---|---|---|
| Rôle | **inférence faisant foi** | introspection et explication |
| Socle | bibliothèque C++ officielle | réimplémentation lisible |
| Dépendances | R ≥ 3.6 + paquet `FisPro` | aucune |
| Explique le raisonnement | non | **oui** |
Par défaut (`backend="auto"`), le serveur utilise R s'il est disponible et bascule sinon sur Python en le signalant. Les résultats numériques restent donc traçables.
## Installation
```bash
git clone https://github.com/Kofi04/fispro-mcp.git
cd fispro-mcp
pip install -e .
```
Backend R (recommandé, optionnel) :
```r
install.packages("FisPro")
```
## Configuration du client
Dans `claude_desktop_config.json` (Claude Desktop) ou tout autre client MCP :
```json
{
"mcpServers": {
"fispro": {
"command": "fispro-mcp",
"env": {
"FISPRO_MCP_ROOT": "/chemin/vers/vos/modeles"
}
}
}
}
```
Pour Claude Code, voir la procédure d'ajout de serveurs MCP dans la [documentation officielle](https://docs.claude.com/en/docs/claude-code/mcp).
### Variables d'environnement
| Variable | Défaut | Rôle |
|---|---|---|
| `FISPRO_MCP_ROOT` | `.` | Racine autorisée. **Aucun fichier hors de cette arborescence n'est lisible.** |
| `FISPRO_MCP_RSCRIPT` | `Rscript` | Exécutable R à utiliser |
| `FISPRO_MCP_R_TIMEOUT` | `120` | Délai maximal d'un appel R, en secondes |
## Outils exposés
| Outil | Ce qu'il fait |
|---|---|
| `check_environment` | Racine autorisée, disponibilité de R et du paquet FisPro |
| `list_fis` | Inventaire des `.fis` avec entrées, sorties et nombre de règles |
| `describe_fis` | Variables, partitions floues, opérateurs, règles rédigées en français |
| `infer` | Sorties pour un vecteur d'entrées (backend `auto` / `r` / `python`) |
| `explain_inference` | Degrés d'appartenance et règles déclenchées, triées par force |
| `infer_dataset` | Inférence par lot sur un CSV, avec export optionnel |
| `validate_fis` | Audit : sous-ensembles inutilisés, prémisses dupliquées, partitions non fortes, trous de la base de règles |
Toutes les réponses d'inférence portent un champ `warnings` : ce sont les anomalies
relevées à la lecture du fichier (règle tronquée, section inconnue…). Elles ne font
pas échouer le calcul mais peuvent le fausser — lisez-les avant d'exploiter un résultat.
### Ce que `validate_fis` contrôle exactement
- **Partitions** : la somme des degrés d'appartenance est échantillonnée en 101 points
sur le domaine de chaque entrée. Un creux signale une partition non forte, une somme
nulle une zone qu'aucun sous-ensemble ne représente, une somme supérieure à 1 un
recouvrement excessif.
- **Base de règles** : l'espace d'entrée est balayé sur une grille (budget de 4096 points,
réparti sur les axes) pour repérer les régions où aucune règle ne se déclenche — celles
où le système ne sait rien répondre.
- **Cohérence** : sous-ensembles jamais employés en prémisse, prémisses dupliquées,
plages invalides.
S'y ajoutent une ressource `fispro://systems` (inventaire) et une invite `audit_prompt` (audit guidé d'un modèle).
## Exemple
Le dépôt contient `tests/data/irrigation.fis`, un système Sugeno à deux entrées (humidité du sol, température) et une sortie (durée d'arrosage) :
```bash
FISPRO_MCP_ROOT=tests/data fispro-mcp
```
## Limites, en toute franchise
- **Le lecteur `.fis` reste le maillon fragile.** Les deux dialectes sont couverts et les 15 fichiers d'exemple livrés avec FisPro se lisent sans avertissement, mais le format admet des variantes que ce lecteur ne connaît peut-être pas. Tout ce qu'il ne comprend pas atterrit dans `warnings` plutôt que d'être deviné en silence — lisez-les. Si vos fichiers déclenchent des avertissements, ouvrez une issue avec un extrait anonymisé : c'est la contribution la plus utile au projet.
- **Le moteur Python couvre un sous-ensemble des fonctions d'appartenance** : `trimf`, `trapmf`, `gaussmf`, `gbellmf`, `si`, `sd`, `universal` côté MATLAB ; `triangular`, `trapezoidal`, `SemiTrapezoidalInf/Sup`, `door` côté FisPro ; et les conséquents `constant` / `linear`. Les formes `sinus`, `discrete` et `gaussian` de FisPro ne sont pas implémentées : elles lèvent une erreur explicite plutôt que de renvoyer un nombre faux.
- **`MeanMax` a un cas limite connu.** L'opérateur est reproduit comme la moyenne de l'alpha-coupe de la conclusion la mieux notée, écrêtée à `min(1, degré)`. Sur les 150 lignes du jeu iris et les onze systèmes d'exemple de FisPro, une seule inférence diverge (`configfpa.fis`, ligne 107, 2,00 contre 2,49) : deux conclusions y sont presque à égalité et FisPro semble alors agréger différemment. Les autres opérateurs sont exacts.
- **Côté Mamdani MATLAB, la défuzzification reste discrétisée.** La grille est adaptée à la finesse de la partition de sortie, mais `centroid` demeure une approximation ; attendez-vous à un écart de l'ordre du pas de grille. Les systèmes en dialecte FisPro, eux, ne passent pas par la grille.
- **Pas d'apprentissage automatique.** Induction de règles, génération de partitions, réduction d'espace : ces algorithmes vivent dans la bibliothèque C++ et ne sont pas exposés par le paquet R. Les brancher demanderait un binding pybind11 ou un appel aux exécutables en ligne de commande — c'est la prochaine étape naturelle du projet.
- **Le serveur lit et calcule ; il n'écrit pas de `.fis`.** Concevez vos systèmes dans FisPro, exploitez-les ici.
## Développement
```bash
pip install -e ".[dev]"
pytest # sans dépendance à R
ruff check .
```
Arborescence :
```
src/fispro_mcp/ config.py, fis_model.py, inference.py, r_backend.py, server.py
tests/ tests unitaires + tests/data/irrigation.fis
```
## Licence
Code de ce serveur : MIT (voir `LICENSE`).
FisPro lui-même est distribué sous licence **CeCILL** et n'est pas redistribué ici : le backend R appelle une installation que vous réalisez vous-même. Si vous publiez des travaux s'appuyant sur FisPro, citez Guillaume & Charnomordic, *Fuzzy Inference Systems: an integrated modelling environment for collaboration between expert knowledge and data using FisPro*, Expert Systems with Applications 39(10), 2012.
Ce projet n'est pas affilié à l'INRAE ni aux auteurs de FisPro.
TDQS
Scored across 7 tools
Each tool has a clearly distinct purpose: environment check, file listing, system description, single inference, inference explanation, dataset inference, and validation. There is no overlap; even infer and explain_inference are clearly separated by output (results vs. reasoning).
All tool names follow a consistent snake_case verb_noun or verb pattern (check_environment, list_fis, describe_fis, infer, explain_inference, infer_dataset, validate_fis). The only minor deviation is the bare verb 'infer', but it is clean and understandable in context.
Seven tools is a well-scoped count for a fuzzy inference system server. Each tool covers a distinct operation needed to work with FIS files, and none feel redundant or excessive.
The tool surface covers the full workflow for the domain: preparing/checking the environment, discovering and inspecting FIS files, running single and batch inferences, understanding inference results, and validating system integrity. No obvious dead ends or missing core operations.