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 comme gestionnaire de projet
- Accès SSH sans mot de passe vers l'esieabot
pigpiodconfiguré 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 :
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 :
ssh pi@<IP_DE_TON_ESIEABOT>
sudo systemctl edit pigpiod
Ajouter :
[Service]
ExecStart=
ExecStart=/usr/bin/pigpiod -n
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
# 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
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)
# 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
{
"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
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












