akirahrkw
Initial commit: Drone Control MCP Server
b4df7d7
|
Raw
History Blame Contribute Delete
7.8 kB

A newer version of the Gradio SDK is available: 6.26.0

Upgrade

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Project Overview

This is an MCP (Model Context Protocol) server for drone control via MQTT, built for the MCP 1st Birthday Hackathon. The project enables AI agents (like Claude) to control drones through natural language by translating MCP protocol calls into MQTT commands.

Architecture

The system has three independent components that communicate via MQTT:

  1. drone_mcp_server.py - MCP server that exposes drone control as MCP tools for AI agents
  2. gradio_demo.py - Web UI for manual drone control (independent MQTT client)
  3. mqtt_drone_client.py - Drone simulator that responds to MQTT commands

Key architectural principle: Both the MCP server and Gradio demo connect directly to MQTT. They do NOT communicate with each other. This allows:

  • Gradio to work standalone for quick testing
  • MCP server to work independently for AI agents
  • Both to run simultaneously without conflicts
Claude Desktop ──MCP──> drone_mcp_server ──┐
                                           β”œβ”€β”€> MQTT Broker ──> Drone Simulator
Browser ─────────────> gradio_demo β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Development Setup

# Install dependencies
pip install -r requirements.txt

# Install MQTT broker (macOS)
brew install mosquitto
brew services start mosquitto

# Or run manually
mosquitto -v

Running the System

Start components in separate terminals (order doesn't matter):

# Terminal 1: MQTT Broker (if not running as service)
mosquitto -v

# Terminal 2: Drone Simulator
python src/mqtt_drone_client.py

# Terminal 3: MCP Server (for AI agents)
python src/drone_mcp_server.py

# Terminal 4: Gradio Demo (for web UI)
python src/gradio_demo.py
# Then open http://localhost:7860 and click "πŸ”Œ Connect"

MQTT Communication

All three components use paho-mqtt with CallbackAPIVersion.VERSION2:

Topic Structure - Action Protocol

The system uses the action protocol for all flight commands:

  • Action Topic: {mqtt_prefix}/remotecontrol/action (default: doozy/command/remotecontrol/action)
  • Status Topic: {mqtt_prefix}/remotecontrol/aruco-mission/status

Command Flow

  1. MCP server or Gradio publishes action JSON to {mqtt_prefix}/remotecontrol/action
  2. Drone simulator receives, processes action, updates internal state
  3. Drone publishes status updates to ArUco mission status topic

Available Commands

Basic Flight (Action Protocol):

  • StartTakeoff - value: true - Takeoff the drone (uses default 1.5m altitude)
  • StartAutoLanding - value: true - Land the drone automatically

ArUco Marker Navigation (Action Protocol):

  • StartArUcoTakeoff - value: {marker_id: int, distance: float, marker_size: float}
  • StartArUcoMission - value: {marker_id: int, distance: float, initial_rotation_degree: float, rotate_to_left: bool, marker_size: float}
  • StartArUcoLanding - value: marker_id (int)
  • StopArUcoMission - value: {}

Legacy Commands (still available via MCP, not in Gradio Basic Controls):

  • move - params: {direction: str, distance: float}
  • rotate - params: {angle: float}
  • hover - params: {duration: float}
  • emergency_stop - params: {}

Action Protocol Message Format

Action messages have format:

{
  "action": "StartTakeoff",
  "value": true
}
{
  "action": "StartArUcoTakeoff",
  "value": { "marker_id": 23, "distance": 1.5, "marker_size": 0.176 }
}

Status messages include:

  • cid - current marker ID
  • tid - target marker ID
  • d - distance to target
  • dids - detected marker IDs
  • s - mission status (START, PRECISION_TAKEOFF, TARGET, COMPLETED_JOB, etc.)

Authentication and Configuration

All components support MQTT authentication and configuration via:

  1. Command-line arguments: python src/drone_mcp_server.py localhost 1883 username password mqtt_prefix
  2. Environment variables: MQTT_BROKER, MQTT_PORT, MQTT_USERNAME, MQTT_PASSWORD, MQTT_PREFIX
  3. Gradio UI: Configure in web interface (recommended for demo)

MQTT Prefix: The default prefix is doozy/command. This affects action protocol topics. Change it via command line arg 5 or MQTT_PREFIX env var, or configure it in the Gradio UI.

MCP Server Integration

To connect Claude Desktop or other MCP clients, add to their config:

{
  "mcpServers": {
    "drone-control": {
      "command": "python",
      "args": ["/absolute/path/to/src/drone_mcp_server.py"],
      "env": {
        "MQTT_BROKER": "localhost",
        "MQTT_PORT": "1883"
      }
    }
  }
}

The MCP server exposes 10 tools. Each tool's call_tool() handler:

  1. Validates parameters
  2. Calls send_action() or send_command() to publish MQTT message
  3. Returns JSON result as TextContent

Tools:

  • takeoff, land - Use action protocol (send_action())
  • aruco_takeoff, aruco_mission, aruco_landing, stop_aruco_mission - Use action protocol
  • move, rotate, hover, emergency_stop - Use legacy command protocol (still available)

Gradio UI Notes

  • Basic Controls Tab: Only includes Takeoff and Land buttons (simplified UI)
  • ArUco Marker Control Tab: Full ArUco navigation controls
  • Connection Settings: Configure MQTT broker, port, username, password, and prefix in the UI
  • Connection management: Uses connect_mqtt() and disconnect_mqtt() methods
  • Safety check: All commands verify is_connected flag before publishing
  • Auto-refresh: Uses gr.Timer(2) for 2-second status updates (not deprecated every parameter)

Hugging Face Deployment

The project includes app.py in the root directory for Hugging Face Spaces deployment:

Code Patterns

MQTT Client Setup (all components)

self.mqtt_client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id="unique_id")
self.mqtt_client.on_connect = self._on_connect  # Signature: (client, userdata, flags, rc, properties)
self.mqtt_client.on_message = self._on_message
if username and password:
    self.mqtt_client.username_pw_set(username, password)
self.mqtt_client.connect(broker, port, 60)
self.mqtt_client.loop_start()

Drone Simulator State Management

The simulator maintains state (position, altitude, heading, is_flying) and updates it when commands are received. It does NOT execute real movement - just simulates by updating internal variables and publishing status.

Testing

Run the full system locally:

  1. Start all 4 terminals as shown above
  2. In Gradio (localhost:7860), click Connect
  3. Test commands via Gradio UI
  4. Optionally connect Claude Desktop and test via natural language
  5. Watch Terminal 2 for drone simulator logs

Real Drone Integration

This project is designed to work with DJI drones via MQTT using the action protocol.

Requirements:

  • DJI drone with MQTT support
  • Red Dot Drone mobile app for ArUco marker flight control
  • Drone firmware implementing the action protocol

Integration:

  1. The drone subscribes to: {mqtt_prefix}/remotecontrol/action
  2. The drone publishes status to: {mqtt_prefix}/remotecontrol/aruco-mission/status
  3. No changes needed to MCP server or Gradio demo - they send action protocol commands

Simulator for Testing: mqtt_drone_client.py simulates a drone by:

  • Subscribing to action protocol topic
  • Handling both action protocol and legacy commands
  • Simulating flight state changes
  • Logging received commands (does not perform actual flight)