px4-flight-debugger
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@px4-flight-debuggerwhy did my latest flight failsafe and land blind?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
px4-flight-debugger
Is it my planner, or is it PX4? An MCP server for people writing offboard and
autonomy code against PX4 SITL: Claude (or any MCP client) reads the .ulg
and answers "why did that flight never reach its goal?", "how far off was the
estimate from the simulator's truth?" or "how late does PX4 follow my velocity
commands?" in one call instead of a hand-written pyulog script.
> log_summary 2026-10-20/16_21_32
log 2026-10-20/16_21_32.ulg started 2026-10-20 09:21:32 PDT, 50.9 s, 10.2 MB
PX4 v1.14.4 dev on PX4_SITL
armed: 12.6s (internal command) -> 49.9s (landing)
in the air 14.4-47.9s
[...]
modes: 0.0 AUTO_LOITER disarmed -> 12.6 OFFBOARD armed -> 17.6 ALTCTL FAILSAFE -> 49.9 OFFBOARD disarmed
failsafe: first at 17.6s
estimator while armed: horizontal position invalid 17.5-50.0s; dead reckoning 13.5-50.0s
warnings and errors (6 distinct):
13.8s WARNING [health_and_arming_checks] Preflight Fail: No valid data from Compass 0 (x3, last 22.6s)
17.5s WARNING [mc_pos_control] Failsafe: blind land (x15, last 46.1s)
[...]
17.6s WARNING Failsafe activated, triggering fallback to altitude control
[...]That flight came from an obstacle-avoidance batch in Gazebo where, in two runs out of sixteen, the planner never got to start navigating. The planner was fine: SITL lost its compass right after arming, the estimator lost its horizontal position four seconds later and PX4 failsafed into a blind landing.
Why
Developing offboard planners against PX4 SITL, most of the "is it my code or
the simulator?" questions are answered by the flight log, but reading one
means a fresh script each time: find which .ulg belongs to the flight, decode
the mode numbers, line up messages, events and estimator flags. The tools here
are the questions that kept coming up, answered in plain text an assistant can
read and reason about.
Related MCP server: log-mcp
Tools
Tool | Answers |
| which logs exist; which one was running at 10:07 local time |
| what happened: version, arming and why, takeoff/landing, modes, failsafes, estimator trouble, distinct warnings |
| everything that changed, in order: modes, commands and acks, failsafe flags, takeoff, estimator validity, warnings |
| console messages and decoded events by level, text and time window |
| when position/velocity were invalid, dead reckoning, resets, which sources were fused when, faults, rejected measurements |
| SITL only: estimate against the simulator's ground truth, on the ground before liftoff and in the air |
| PX4's response to offboard velocity setpoints as a first-order lag plus dead time |
| parameter values by name or glob, and changes during the flight |
| any uORB topic: fields, rates, stats over a window, a downsampled table |
| one line per log for a whole day: which ones failsafed, which ones mention "compass" |
| a PNG of any fields against time, mode changes marked |
All read-only. A log is named by path, file name (16_21_32.ulg), date/name
(2026-10-20/16_21_32), latest or latest-N. Times are seconds since the
log started; the local wall-clock start is in every header. PX4 names log
folders and files in UTC, while day arguments and printed start times are
local.
Install
Needs uv.
git clone https://github.com/blar-tw/px4-flight-debugger && cd px4-flight-debugger
uv syncRegister it with Claude Code (user scope, so every project sees it):
claude mcp add px4-flight-debugger --scope user -- uv --directory /path/to/px4-flight-debugger run px4-flight-debuggeror add it to an MCP client's config by hand:
{
"mcpServers": {
"px4-flight-debugger": {
"command": "uv",
"args": ["--directory", "/path/to/px4-flight-debugger", "run", "px4-flight-debugger"],
"env": {"PX4_ULOG_DIRS": "/home/you/PX4-Autopilot/build/px4_sitl_default/rootfs/log", "PYTHONPATH": ""}
}
}
}PX4_ULOG_DIRS lists where to look (separated by :), default
~/PX4-Autopilot/build/px4_sitl_default/rootfs/log. Empty PYTHONPATH keeps a
sourced ROS 2 environment from leaking its packages into the server.
How it reads a log
pyulog parses the file; each tool asks only for the topics it needs, and a few parsed logs are kept in memory, keyed on the file's modification time.
Events are decoded with the definitions PX4 embeds in the log, falling back to a local
all_events.jsonfrom a PX4 build. Nothing is downloaded.Mode, arming and command names are PX4 v1.14's. The arming reason names come from commander's
arm_disarm_reason_t, not theARM_DISARM_REASON_*constants inVehicleStatus.msg, which are out of date (6 is "landing", not "safety button").velocity_trackingonly counts setpoints with position NaN and velocity set while PX4 is in offboard, which is what it flies as a velocity command. A position setpoint whose velocity fields were simply left at zero is not one; counting those halved the fitted lag before this rule. It says so when the fit does not look like a lagged velocity follower.estimate_vs_truthtakes the truth relative to where the drone spawned (the simulator's world frame need not start at PX4's local origin) and reports separately how far PX4 placed its local origin from the simulator's.pyulog prints warnings on stdout, which is the protocol channel on stdio; they are sent to stderr instead. An unreadable file is a tool error, and
scan_logsskips it with the reason.
Things the logs showed while building it
SITL logs carry the ground truth.
vehicle_local_position_groundtruthandvehicle_attitude_groundtruthare logged next to the estimate, so estimate-vs-truth needs no Gazebo bridge or extra recorder. Across 97 SITL flights here, the height estimate had settled between 1.17 m below and 1.22 m above the truth while the drone still sat on the ground (either sign, more than 0.3 m in 60 of them), and the offset carried into the air. Horizontally, most of the error is where PX4 put its local origin at the first GPS fix: in 17_06_45 the origin sits 0.35 m from the spawn point and the estimate is off by 0.39 m.PX4's own lag and the planner's. Over 87 flights with a clean fit, PX4 followed an offboard velocity setpoint like a first-order lag of 0.45 s (0.40-0.55) after 0.20 s of dead time. For 17_06_45 the log says 0.65 s in total, while the planner that sent the setpoints measured about 0.75 s from its own side: transport and scheduling add roughly 0.1 s, and the end-to-end figure is the one a planner should budget.
A message mismatch, visible as an arming reason. The planner arms through a
VehicleCommandwithfrom_externalset, yet the log says "internal command". Itspx4_msgs(main) hassource_componentasuint16where v1.14 hasuint8, which shifts the fields after it.
Limits
Built and tested against PX4 v1.14 SITL logs. Other versions parse, but enum values they added show up as numbers.
estimate_vs_truthneeds a SITL log; real flights have no truth topic. It takes the first truth sample as the spawn point, so the drone should be at rest when logging starts (PX4 starts logging at boot by default).PX4's default logging profile thins
trajectory_setpointto about 5 Hz, so the fitted dead time is only good to about 0.2 s.
Development
uv run pytestThe tests run on two real SITL logs cut down with
tools/make_fixture.py (1.3 MB together): the compass failure above and a
clean offboard flight whose height estimate drifts. Each test is a question
that once needed its own script, plus an MCP round trip in-process and over a
real stdio subprocess.
MIT licensed.
Available Tools
12 toolsestimate_vs_truthA
SITL only: PX4's position/yaw estimate against the simulator's ground truth, on the ground before liftoff and in the air, plus sudden jumps. Shows offsets a planner flying on the estimate would carry.
Inputs: log. Returns: result
estimator_healthB
EKF2 view: when local position/velocity were invalid, dead reckoning, resets, which sources were fused and when (GPS, mag, baro...), faults, and innovation test ratios that exceeded 1 (measurements rejected).
Inputs: log. Returns: result
flight_timelineB
Everything that changed, in order: modes and arming, commands and their acks, failsafe flags set/cleared, takeoff/landing, estimator validity, warnings.
Inputs: log, limit. Returns: result
list_logsA
List flight logs newest first with their local start time, or find the one that covers a given wall-clock time.
Inputs: at, day, limit. Returns: result
list_topicsB
Every logged uORB topic with sample count, rate and field count.
Inputs: log. Returns: result
log_messagesB
PX4 console messages and decoded events at or above a level, oldest first.
Inputs: log, t_to, limit, t_from, +2 more. Returns: result
log_paramsC
Parameter values as logged at boot, and any changed during the log.
Inputs: log, names, pattern. Returns: result
log_summaryB
What happened in one flight: PX4 version, arming and why, takeoff and landing, mode changes, failsafes, estimator trouble while armed, distinct warnings and errors (console and decoded events).
Inputs: log. Returns: result
plot_seriesB
Plot logged fields against time (mode changes dashed, failsafes red) and return the PNG.
Inputs: series (required), log, t_to, t_from.
scan_logsB
One line per log: start time, duration, time armed, first failsafe, warning count and the first warning. For questions like 'which flights today lost the compass' or 'which ones failsafed'.
Inputs: day, limit, contains. Returns: result
topic_dataB
Min/mean/max/first/last of a topic's fields over a time window, optionally with a downsampled table.
Inputs: topic (required), log, t_to, fields, +2 more. Returns: result
velocity_trackingA
How PX4 followed offboard velocity setpoints: fits a first-order lag plus dead time from trajectory_setpoint to the measured velocity (the 'reaction time' an avoidance planner has to budget for).
Inputs: log. Returns: result
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
TDQS
Scored across 12 tools
Most tools have clearly distinct scopes: discovery (list_logs, scan_logs), single-flight narrative (log_summary, flight_timeline, log_messages), estimator analysis (estimator_health, estimate_vs_truth), and data access (list_topics, topic_data, plot_series). The main friction is between log_summary, flight_timeline, and log_messages, which all describe 'what happened in a flight' from slightly different angles, and between list_logs and scan_logs, though the descriptions do differentiate them well enough.
All names are snake_case and readable, with no mixed casing conventions. However the pattern is not uniformly verb_noun: list_logs, scan_logs, plot_series use verbs while log_summary, flight_timeline, estimator_health, topic_data are noun phrases, creating a minor stylistic inconsistency.
12 tools is well within the ideal range and each one maps to a distinct analysis need (discovery, summarization, event ordering, EKF health, truth comparison, setpoint tracking, params, topics, plotting). No tool feels redundant or padded.
The surface covers discovery, per-flight narrative, estimator diagnostics, parameters, uORB topics, and plotting, which is strong lifecycle coverage for flight log debugging. Minor gaps remain, such as raw/full-resolution topic export (topic_data only gives stats plus an optional downsampled table) and no dedicated actuator/motor or battery analysis path, though plot_series partially compensates.
Maintenance
Related MCP Connectors
Analytics and debugging for your MCP server — explore usage and sessions, then root-cause errors.
Analytics for MCP servers. Query your tool calls, first-call success, retries and schema cost.
CircleCI's MCP server: inspect projects, runs, workflows, jobs, logs, tests, and artifacts.
1Governed data discovery, exact queries, decisions, simulations, and runtime utilities over MCP.
Related MCP Servers
- FlicenseBqualityCmaintenanceEnables AI-assisted analysis of log files through advanced searching, filtering, and test execution capabilities. Supports time-based queries, pattern matching, test summarization, and code coverage reporting directly within compatible MCP clients.12-
- AlicenseAqualityDmaintenanceMCP server for log file analysis. Gives LLMs the ability to efficiently analyze large log files without loading them into context.7101MIT
- AlicenseNot gradedqualityDmaintenanceMCP server for inspecting PX4 ULog flight logs, enabling AI assistants to understand, debug, and reason about drone systems.3MIT
- AlicenseAqualityAmaintenanceMCP server for chatting with physical-world data from robotics, drones, automotive, and IoT sources using natural language. It generates auditable SQL queries over Apache Arrow/DuckDB to let you analyze, summarize, and build data pipelines.25401Apache 2.0