mcp-esieabot
README.md
# mcp-esieabot
Serveur MCP (Model Context Protocol) pour le contrôle de l'esieabot via Claude Desktop ou le MCP Inspector.
Développé dans le cadre du TD3 — Module Python ING3, ESIEA Paris.
**Auteure :** Vanelle Stéphanie MANGOUA DJOUSSEU
**Email :** vanellestephanie.mangouadjousseu@et.esiea.fr
**Dépôt :** https://gitlab.esiea.fr/stephanie_mangoua/mcp-esieabot
---
## Présentation
Ce projet expose les capacités de l'esieabot (moteurs, servomoteur, caméra) sous forme de **tools MCP**, permettant à un LLM comme Claude de piloter le robot en langage naturel :
> *« Avance pendant 2 secondes, tourne à droite, puis prends une photo »*
Claude appelle automatiquement les tools MCP correspondants et retourne les résultats dans la conversation, y compris les images capturées par la caméra.
---
## Architecture choisie : Architecture B — Serveur MCP sur le PC
Le serveur MCP tourne sur le PC. Il se connecte au démon `pigpiod` du Raspberry Pi à distance via le réseau (port 8888) et à la caméra via SSH.
```
Votre PC Raspberry Pi
┌────────────────────────────────┐ ┌──────────────────┐
│ Claude Desktop (client MCP) │ │ │
│ │ │ │ pigpiod :8888 │
│ ▼ │ │ (GPIO) │
│ server.py (FastMCP) │── pigpio ───►│ ├─ Moteurs │
│ http://localhost:8000/mcp │── SSH ──────►│ ├─ Servos │
└────────────────────────────────┘ │ └─ Caméra │
└──────────────────┘
```
**Avantages de l'Architecture B :**
- Aucun problème CORS/firewall — tout MCP est en localhost
- Debug facile depuis l'IDE (breakpoints, logs en temps réel)
- Rechargement instantané sans déploiement Git sur le Pi
- Mode simulation intégré pour développer sans robot
---
## Structure du projet
```
mcp-esieabot/
├── server.py ← Serveur MCP principal (tools, resources, prompt)
├── robot/
│ ├── __init__.py ← Auto-détection pigpio (stub / local / remote)
│ ├── motors.py ← Contrôle des moteurs DC via pigpiod
│ ├── servos.py ← Contrôle du servomoteur via pigpiod
│ ├── camera.py ← Capture photo via SSH (Architecture B)
│ └── stub.py ← Simulation pigpio pour développement local
├── captures/ ← Photos capturées localement (créé automatiquement)
│ ├── capture1.jpg
│ ├── capture2.jpg
│ └── capture3.jpg
├── debug_photo.jpg ← Photo retournée par take_photo en mode simulation
├── pyproject.toml
├── .gitignore
└── README.md
```
---
## Prérequis
- Python **3.11+**
- [Poetry](https://python-poetry.org/) comme gestionnaire de projet
- Accès SSH sans mot de passe vers l'esieabot
- `pigpiod` configuré en écoute réseau sur le Pi (port 8888)
### Dépendances Python
| Package | Version |
|---------|---------|
| `mcp[cli]` | >=1.26.0, <2.0.0 |
| `pigpio` | >=1.78, <2.0 |
Installation :
```bash
poetry install
```
---
## Auto-détection de l'environnement
`robot/__init__.py` détecte automatiquement le mode de fonctionnement au démarrage :
| Situation | `ESIEABOT_HOST` | `pigpio` installé ? | Mode activé |
|-----------|-----------------|---------------------|-------------|
| Développement PC pur | Non défini | Non | **Stub** — simulation console |
| Architecture B (PC → Pi) | `192.168.x.x` | Oui | **Remote** — connexion pigpio distante |
| Architecture A (sur le Pi) | Non défini | Oui | **Local** — pigpiod local |
### Mode simulation — Stub GPIO
`robot/stub.py` simule tous les appels GPIO dans la console sans aucun matériel :
```
[STUB] pigpio connecté (mode simulation — cible: local)
[STUB] GPIO 24 → OUTPUT
[STUB] GPIO 24 = HIGH
[STUB] GPIO 7 = HIGH
[STUB] Servo GPIO 16 : pulse = 1500µs
[STUB] pigpio déconnecté
```
### Mode simulation — Caméra
Si `ESIEABOT_HOST` n'est pas défini, `camera.py` retourne automatiquement `debug_photo.jpg` au lieu de tenter une connexion SSH. Cette photo (prise depuis la perspective du robot, au ras du sol) permet de tester le tool `take_photo` complètement hors ligne sans aucun crash.
---
## Configuration de l'esieabot
### 1. Activer pigpiod en écoute réseau
Par défaut, `pigpiod` n'écoute que sur localhost. Pour l'Architecture B :
```bash
ssh pi@<IP_DE_TON_ESIEABOT>
sudo systemctl edit pigpiod
```
Ajouter :
```ini
[Service]
ExecStart=
ExecStart=/usr/bin/pigpiod -n
```
```bash
sudo systemctl daemon-reload
sudo systemctl restart pigpiod
# Vérification — doit afficher une ligne avec *:8888
ss -tlnp | grep 8888
```
### 2. Configurer SSH sans mot de passe
```bash
# Sur votre PC
ssh-keygen -t ed25519 # si pas déjà fait
ssh-copy-id pi@<IP_DE_TON_ESIEABOT>
# Test
ssh pi@<IP_DE_TON_ESIEABOT> "echo OK"
```
---
## Lancement du serveur
### Mode simulation — sans robot
```bash
poetry run python server.py
```
Sortie attendue :
```
⚠️ Aucun hôte caméra. Passage en mode SIMULATION (Photo locale).
⚠️ pigpio non trouvé. Passage en mode SIMULATION (Stub global).
INFO: Uvicorn running on http://0.0.0.0:8000
```
### Mode réel — Architecture B (PC → Pi)
```bash
# Linux / macOS
ESIEABOT_HOST=<IP_DE_TON_ESIEABOT> poetry run python server.py
# Windows (PowerShell)
$env:ESIEABOT_HOST="<IP_DE_TON_ESIEABOT>"; poetry run python server.py
# Windows (cmd)
set ESIEABOT_HOST=<IP_DE_TON_ESIEABOT> && poetry run python server.py
```
Sortie attendue :
```
✅ Caméra configurée pour l'hôte : <IP>
🤖 Robot connecté physiquement (pigpio → <IP>)
INFO: Uvicorn running on http://0.0.0.0:8000
```
Le serveur écoute sur **http://localhost:8000/mcp**.
---
## Primitives MCP exposées
### Tools (12)
| Tool | Description | Validation entrée |
|------|-------------|-------------------|
| `ping` | Vérifie que le serveur est en ligne | — |
| `identify` | Hostname, OS, version Python du robot | — |
| `move_forward` | Avance en ligne droite avec suivi de progression temps réel | durée [0.1–10.0 s] |
| `move_backward` | Recule en ligne droite | durée [0.1–10.0 s] |
| `turn_left` | Pivote à gauche sur place | durée [0.1–5.0 s] |
| `turn_right` | Pivote à droite sur place | durée [0.1–5.0 s] |
| `emergency_stop` | Arrêt immédiat de tous les moteurs | — |
| `set_servo_angle` | Positionne le servomoteur à un angle précis | angle [0–180°] |
| `detach_servo` | Désarme le servomoteur (coupe le signal PWM) | — |
| `take_photo` | Prend une photo et la retourne directement à Claude | — |
| `list_captures` | Liste toutes les photos dans `./captures/` avec leur taille | — |
| `get_capture` | Affiche une photo spécifique par nom de fichier | nom de fichier |
### Resources (2)
| URI | Description | Mode simulation |
|-----|-------------|-----------------|
| `robot://status` | Température CPU, mémoire, uptime du Pi via SSH | Retourne `(Mode simulation — Hors ligne)` |
| `robot://captures` | Liste statique des captures disponibles | Liste les fichiers présents dans `./captures/` |
### Prompt (1)
| Prompt | Paramètres | Description |
|--------|------------|-------------|
| `patrol_mission` | `area` (défaut: `"bureau"`), `photo_count` (défaut: `3`) | Génère une mission de patrouille complète pour Claude |
Exemple d'utilisation dans Claude Desktop :
> *« Utilise le prompt patrol_mission pour le couloir avec 2 photos »*
---
## GPIO de l'esieabot
| Composant | GPIO BCM | Fonction |
|-----------|----------|----------|
| Moteur gauche — avance | 24 | Sens marche avant gauche |
| Moteur gauche — recul | 23 | Sens marche arrière gauche |
| Moteur droit — avance | 7 | Sens marche avant droit |
| Moteur droit — recul | 8 | Sens marche arrière droit |
| Servomoteur | 16 | Angle PWM (500–2500 µs) |
---
## Connexion avec Claude Desktop
Éditez le fichier de configuration de Claude Desktop :
- **Windows :** `%APPDATA%\Claude\claude_desktop_config.json`
- **macOS :** `~/Library/Application Support/Claude/claude_desktop_config.json`
```json
{
"mcpServers": {
"esieabot": {
"type": "streamable-http",
"url": "http://localhost:8000/mcp"
}
}
}
```
Redémarrez Claude Desktop. Les 12 tools `esieabot` apparaissent automatiquement.
### Exemples d'interactions avec Claude
```
« Quel est l'état de mon robot ? »
→ Claude consulte la resource robot://status
« Avance pendant 2 secondes puis tourne à droite »
→ Claude appelle move_forward(duration=2.0) puis turn_right(duration=0.5)
« Prends une photo »
→ Claude appelle take_photo() et affiche l'image dans la conversation
« Liste les captures disponibles »
→ Claude appelle list_captures() ou consulte robot://captures
« Utilise le prompt de patrouille pour le bureau avec 2 photos »
→ Claude charge patrol_mission(area="bureau", photo_count=2) et exécute la mission
```
---
## Test avec le MCP Inspector
```bash
npx -y @modelcontextprotocol/inspector
```
Connectez-vous à `http://localhost:8000/mcp` pour tester chaque tool individuellement sans Claude Desktop.
---
## Bonus implémentés
| Bonus | Description | Implémentation |
|-------|-------------|----------------|
| **C** — Resource captures | `robot://captures` liste les photos disponibles passivement | `@mcp.resource("robot://captures")` dans `server.py` |
| **D** — Progress reporting | `move_forward` reporte la progression en temps réel par paliers | `ctx.report_progress()` + `asyncio.sleep()` par paliers de 1/5 |
| **E** — Connexion pigpio partagée | Une seule instance `pigpio.pi()` partagée entre moteurs et servos | Instance unique créée dans `robot_lifespan()`, injectée via `MotorController(pi=pi)` et `ServoController(pi=pi)` |
---
## Auteure
**Vanelle Stéphanie MANGOUA DJOUSSEU**
Étudiante ING3 — Systèmes Embarqués et Autonomes
ESIEA Paris (Ivry-sur-Seine)
vanellestephanie.mangouadjousseu@et.esiea.fr
This server cannot be deployed
Maintenance
ActivityInactive
ResponsivenessNo issues