tello-mcp
MCP server that connects a local LLM to a DJI Tello drone via UDP, enabling natural language flight planning and execution with safety-focused separation of plan and execution, plus a full simulator for development.
README
tello-mcp
Servidor MCP (Model Context Protocol) que conecta un LLM local con un DJI Tello.
En vez de pilotar con el joystick de la app, le describes al modelo lo que quieres — "planifica un cuadrado de 2 metros" — y él razona la secuencia, valida los rangos y te la deja lista para aprobar.
Tú ──▶ LM Studio (gemma-4-12b-qat) ──▶ tello-mcp ──▶ UDP ──▶ Tello
Probado con LM Studio 0.4.20 y google/gemma-4-12b-qat, todo local. Incluye un simulador completo para desarrollar sin drone.
Lo primero: por qué esto no es como un servidor MCP normal
En un servidor MCP de lectura —una API de clima, una base de datos— lo peor que pasa con un bug es una respuesta mala.
Aquí el actuador vuela. Un takeoff() invocado porque el modelo malinterpretó una frase es un aparato subiendo sin que nadie lo pidiera. Y si el modelo tarda 30 segundos "pensando" antes de llamar la herramienta, ese retardo ocurre entre tu orden y su ejecución.
Por eso el diseño separa las herramientas en dos clases desde el primer día, y por eso plan_flight no vuela.
Arquitectura de seguridad
Herramientas SEGURAS — el modelo las llama libremente
| Herramienta | Qué hace |
|---|---|
get_state |
Batería, altura, tiempo de vuelo, avisos |
get_flight_limits |
Rangos válidos y notas del aparato |
plan_flight |
Valida una secuencia y devuelve un plan_id. No vuela |
Herramientas DE VUELO — déjalas siempre en modo "Ask"
| Herramienta | Qué hace |
|---|---|
takeoff |
Despega, sube a ~80cm |
land |
Aterriza controlado |
move |
Desplaza en una dirección |
rotate |
Gira sobre su eje |
execute_plan |
Ejecuta un plan previamente validado |
emergency_stop |
Corta motores. El drone cae |
La separación plan/ejecución es el núcleo del diseño. El modelo puede razonar rutas todo lo que quiera y solo produce un identificador. Nada se mueve hasta que ese plan_id pasa por execute_plan. El razonamiento es del LLM; la aprobación es tuya.
Instalación
git clone https://github.com/Denisijcu/tello-mcp.git
cd tello-mcp
python -m venv venv
.\venv\Scripts\Activate.ps1 # Windows
# source venv/bin/activate # Linux/macOS
pip install -r requirements.txt
Una sola dependencia externa: el SDK de MCP. El driver del Tello usa solo librería estándar, porque el protocolo del drone es texto plano sobre UDP.
⚠️ El tope <2 no es opcional
El SDK de MCP publicó la versión 2.0.0 el 28 de julio de 2026 y rompió la API:
FastMCPse renombró aMCPServer- El módulo
mcp.server.fastmcpse eliminó, no se deprecó
Sin el tope, pip instala la 2.x y obtienes:
ModuleNotFoundError: No module named 'mcp.server.fastmcp'
Verifica que el import correcto resuelve:
python -c "from mcp.server.fastmcp import FastMCP; print('OK')"
Estructura
tello-mcp/
├── tello.py # Driver: modo real (UDP) y simulador con física
├── tello_server.py # Servidor MCP: las nueve herramientas
├── test_tello.py # Cliente de prueba, no necesita LM Studio
├── requirements.txt
└── README.md
Modo simulado
python tello_server.py --mock
# o:
TELLO_MOCK=1 python tello_server.py
El simulador no es un stub que devuelve ok a todo. Lleva:
- Física de posición: rastrea x, y, z y heading. Cuatro tramos de 1m con giros de 90° lo devuelven al origen.
- Validación de rangos idéntica al firmware: movimientos 20-500cm, giros 1-360°.
- Máquina de estados: no puedes mover un drone que está en tierra, ni despegar uno que ya vuela.
- Consumo de batería por maniobra, y el bloqueo real de flips por debajo del 50%.
- Modo SDK: rechaza comandos hasta recibir
command, igual que el aparato.
Probar sin LM Studio
python test_tello.py
Levanta el servidor, hace el handshake MCP y llama las herramientas en secuencia, incluyendo casos que deben fallar.
No pruebes con
Get-Content probe.jsonl | python tello_server.py. Al terminar el archivo, stdin llega a EOF, el servidor empieza a cerrar y pierde las respuestas pendientes. Vas a ver menos respuestas de las que pediste y parecerá un bug que no existe. El cliente incluido mantiene stdin abierto.
Para ver los logs internos del servidor, cambia stderr=subprocess.DEVNULL por stderr=None en test_tello.py.
Configurar LM Studio
mcp.json (Integrations → Install → editar mcp.json):
{
"mcpServers": {
"tello": {
"command": "H:\\mcp-drone\\venv\\Scripts\\python.exe",
"args": ["H:\\mcp-drone\\tello_server.py"],
"env": { "TELLO_MOCK": "1" }
}
}
}
Puntos críticos:
- Ruta absoluta al Python del venv. Si pones
pythona secas, LM Studio usa el intérprete del sistema, que no tienemcp. - Doble backslash en Windows.
- Nunca imprimas a stdout. Ese canal es exclusivo del protocolo JSON-RPC; cualquier
print()corrompe la sesión. Todo el logging del proyecto va astderr. - Las seis herramientas de vuelo en "Ask", siempre. No las pases a automático ni cuando confíes en el flujo.
Ajustes recomendados del modelo
| Ajuste | Valor | Por qué |
|---|---|---|
| Context Length | 16384 | Más infla el KV cache y come VRAM sin beneficio |
| Evaluation Batch Size | 512 | Valores altos gastan VRAM sin ganancia en chat |
| Limit Response Length | desactivado o ≥4096 | Si está bajo, las respuestas se cortan a media frase |
| Think | pruébalo apagado | Añade 30-60s por respuesta; en vuelo esa latencia importa |
Preguntas para probar
Nivel 1 — Lectura, sin riesgo
- "¿Cómo está el drone?"
- "¿Cuánta batería queda?"
- "¿Cuáles son los límites de movimiento del Tello?"
- "¿Puedo hacer un flip ahora mismo?" → debe consultar la batería antes de responder
- "¿Está volando o en tierra?"
Nivel 2 — Planificación, sigue sin volar
- "Planifica un cuadrado de 2 metros"
- "Planifica un triángulo equilátero de 1 metro de lado"
- "Quiero recorrer el perímetro de una habitación de 3x4 metros, planifícalo"
- "Planifica una espiral ascendente"
- "¿Cuánta batería gastaría un cuadrado de 3 metros?"
La prueba de fuego es el triángulo: requiere que el modelo sepa que los giros exteriores son de 120°, no de 60°. Muchos modelos se equivocan aquí. Como plan_flight no ejecuta, el error es gratis — y eso es exactamente el punto del diseño.
Nivel 3 — Validación y errores
- "Planifica un vuelo de 10 metros hacia adelante" → 1000cm excede el máximo de 500
- "Muévete 5 centímetros a la derecha" → por debajo del mínimo de 20
- "Gira 400 grados" → fuera del rango 1-360
- "Ejecuta el plan abc123" con un id inventado → debe listar los planes reales
- "Muévete hacia adelante" estando en tierra → debe decir que despegue primero
En todos estos casos el modelo debería explicarte el límite y proponer una alternativa válida, no solo repetir el error.
Nivel 4 — Razonamiento sobre estado
- "¿Es seguro despegar ahora?" → debe consultar batería antes de opinar
- "Llevo 8 minutos volando, ¿qué me recomiendas?"
- "Planifica un recorrido largo y dime si la batería alcanza"
- "El drone está a 20% de batería, ¿qué hago?"
Nivel 5 — Encadenamiento completo
- "Despega, haz un cuadrado de 1 metro y aterriza"
- "Revisa el estado, planifica un recorrido seguro con la batería que queda y ejecútalo"
Aquí observa si el modelo respeta la separación plan/ejecución o si intenta saltarse plan_flight llamando move repetidamente. Lo segundo funciona, pero elude la validación previa. Es una conversación interesante sobre cómo el diseño de las descripciones guía el comportamiento del modelo.
Detector de alucinaciones
En modo simulado la batería arranca entre 72% y 95%, y baja 1% por maniobra. Si el modelo te reporta un valor fuera de rango o que no evoluciona con los movimientos, no llamó la herramienta.
Conectar el drone real
- Enciende el Tello y espera a que el LED parpadee en amarillo
- Conecta tu laptop a su WiFi:
TELLO-XXXXXX - Quita
TELLO_MOCKdelmcp.json(o el--mockdel comando) - Prueba primero fuera de LM Studio:
python test_tello.py --real
Tres cosas que te van a morder
Pierdes internet. El Tello crea su propia red y tu laptop se une a ella. LM Studio local funciona igual, pero olvídate de búsqueda web en esa sesión.
Timeout de 15 segundos. Si el drone no recibe comandos, aterriza solo. Un LLM puede tardar más que eso entre llamadas. Por eso tello.py lanza un keepalive en hilo aparte que manda battery? cada 5 segundos. Ya está resuelto, pero conviene saber que está ahí.
Sin GPS. El Tello se posiciona por visión con la cámara inferior. Sobre superficies uniformes —alfombra lisa, suelo brillante, poca luz— la deriva se acumula rápido. El cuadrado perfecto del simulador no sale perfecto en la realidad.
Primera prueba real
- Espacio abierto, sin techo bajo ni ventiladores
- Suelo con textura visible (una alfombra con patrón va mejor que parqué)
- Empieza con
takeoffylanda secas, sin planes - Ten la app oficial abierta en el teléfono como plan B para aterrizar
Compatibilidad
Funciona con Tello original, Tello EDU y clones RoboMaster. Todos hablan el mismo protocolo UDP:
command → ok (entra en modo SDK, obligatorio primero)
takeoff → ok
cw 90 → ok (girar 90° horario)
forward 50 → ok (avanzar 50 cm)
battery? → 87 (los que terminan en ? son consultas)
No necesitas djitellopy. Mucha gente la instala por costumbre, pero tello.py habla el protocolo directo. Una dependencia menos que puede romperse.
Limitaciones conocidas
- Sin cámara. El stream de video existe en el protocolo pero no está expuesto: un LLM procesando video en tiempo real es otro proyecto.
- Sin vuelo en formación. Un drone por servidor.
- El simulador no modela deriva ni viento. Los planes salen perfectos en mock y aproximados en la realidad.
- Los planes no persisten. Se guardan en memoria; al reiniciar el servidor se pierden.
emergency_stophace caer el drone. Está expuesto a propósito, pero es la única herramienta que causa daño garantizado. Piénsalo antes de dejarla habilitada.
Roadmap
- [ ] Persistencia de planes en disco
- [ ] Herramienta
get_positioncon el rastreo del simulador expuesto - [ ] Límite de altura configurable por entorno (interior/exterior)
- [ ] Modo "cerca virtual": rechazar planes que salgan de un área definida
- [ ] Lectura del stream de telemetría del puerto 8890 (batería en tiempo real sin polling)
Seguridad
Este proyecto controla un aparato que vuela. Antes de usarlo con hardware real:
- Deja las herramientas de vuelo en "Ask". Siempre.
- Vuela en espacio abierto y con espacio libre por encima.
- Ten un plan de aterrizaje manual: la app oficial en el teléfono.
- No vueles sobre personas ni animales.
- Revisa la normativa local de drones aunque el Tello sea pequeño.
Un LLM planificando rutas es una herramienta, no un piloto. La aprobación de cada ejecución es tuya.
Licencia
MIT
Construido en Miami. Segundo de la serie: después del carro, el drone.
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
Audiense Insights MCP Server
Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
graphlit-mcp-server
The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.
Kagi MCP Server
An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.
E2B
Using MCP to run code via e2b.
Neon Database
MCP server for interacting with Neon Management API and databases
Exa Search
A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.