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.
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。