MCP server de SmartTune
Commit 13 sept 2026Analiza registros de vuelo de ArduPilot, Betaflight y PX4 para proporcionar recomendaciones de ajuste de PID, FFT y filtros para controladores de vuelo de drones.
También conocido como raylanlin/smarttune-cli
- Stars
- 33
- Herramientas
- —
- Descargas, 30 días
- —
- Última versión
- —
- Último commit
- 13 sept 2026
- Licencia
- MIT
¿Qué es SmartTune MCP?
SmartTune es un MCP server. Analiza registros de vuelo de ArduPilot, Betaflight y PX4 para proporcionar recomendaciones de ajuste de PID, FFT y filtros para controladores de vuelo de drones.
Resumen generado a partir del README del proyecto
Acerca del MCP server de SmartTune
Los ingenieros y desarrolladores de drones pueden usar SmartTune para transformar registros de vuelo brutos de ArduPilot, Betaflight y PX4 en parámetros de ajuste accionables. Al analizar la respuesta al escalón, los espectros de vibración FFT y la calibración del magnetómetro, el sistema proporciona recomendaciones específicas para los ajustes de PID, FFT y filtros. Está diseñado para funcionar sin conexión sin necesidad de claves de API o acceso a la red, lo que lo hace ideal para entornos air-gapped.
Los usuarios pueden interactuar con el sistema a través de una interfaz de línea de comandos o un MCP server de solo lectura para flujos de trabajo con agentes LLM. El MCP server ofrece 16 herramientas especializadas, incluyendo smarttune_analyze_log para un análisis completo y smarttune_validate_params para asegurar que los valores sugeridos coincidan con versiones y rangos específicos de firmware. El servidor opera mediante transporte stdio y requiere Python 3.10 o superior para la funcionalidad de MCP. Todas las recomendaciones están limitadas a un cambio de ±25% para mantener la seguridad durante el proceso de ajuste.
Qué puedes hacer con él
- 1Recomendaciones automatizadas de ajuste de PIDUn agente de IA puede analizar un registro de vuelo para sugerir deltas específicos de parámetros PID basados en patrones de respuesta al escalón.
- 2Identificación de fuentes de vibraciónUn desarrollador puede usar el análisis de espectro FFT para distinguir entre resonancias del motor, la hélice o el chasis.
- 3Validación de parámetros de firmwareAntes de aplicar los cambios, un agente puede verificar que el nombre y el valor de un parámetro sugerido sean válidos para una versión de firmware específica.
- 4Procesamiento por lotes de registros de vueloLos usuarios pueden ejecutar un bucle para analizar cientos de registros a la vez y obtener los resultados en un formato JSON estructurado.
Escrito a partir del README del proyecto. Cada caso de uso se verifica con una cita del mismo.
Configuración
SMARTTUNE_MCP_ALLOWED_ROOTSSMARTTUNE_MCP_MAX_FILE_MB
| Nombre | Descripción | Tipo |
|---|---|---|
| SMARTTUNE_MCP_ALLOWED_ROOTS | — | |
| SMARTTUNE_MCP_MAX_FILE_MB | — |
Verificaciones automáticas
Ejecutado 14 nov 2026Informe completo →Aún no verificado. Un servidor necesita una puntuación de 80, ningún hallazgo grave y suficientes datos para que podamos revisarlo. Cómo funcionan las verificaciones · Qué corregir para obtener más puntos
- Repositorio de origen vinculado y accesibleraylanlin/smarttune-cli is public and reachablegithub.com/raylanlin/smarttune-cli ↗Aprobado
- El paquete indica este repositorio como su origenNo verificado
- Procedencia de la compilación (atestación de Sigstore)No verificado
- Licencia de código abierto (OSI)MITspdx.org/licenses/MIT.html ↗Aprobado
- Commit o lanzamiento en el último añoLast commit or release 2026-09-13github.com/raylanlin/smarttune-cli ↗Aprobado
- OpenSSF ScorecardNo verificado
- El nombre del paquete no es similar a un paquete popularNo verificado
- No hay avisos críticos en el paquete ni en sus dependenciasNo verificado
- Sin instrucciones ocultas para el modelo0 tool descriptions and the README read; no override phrases, credential paths or hidden charactersAprobado
- Las herramientas destructivas están etiquetadasNo verificado
- El endpoint remoto responde al handshake de MCPNo verificado
README
Ver en GitHubPip-install SmartTune, point it at a flight log, and your agent comes back with exact parameter deltas — validated against real firmware parameter tables.
No more guessing:stune params --validatechecks every recommendation before it reaches the user.Under the hood: ArduPilot step-response analysis replicates WebTools PIDReview.js via Wiener deconvolution. Betaflight blackbox logs are parsed by a 1000+ line pure-Python decoder (no C extensions, no Node.js). All three platforms output to one
FlightDatadataclass so analyzers work identically across APM/BF/PX4. The 6-layer knowledge base is plain JSON — agents can read rules and propose new ones by editing~/.smarttune/knowledge/.
Install
pip install git+https://github.com/raylanlin/smarttune-cli.git
# With all platform extras
pip install "git+https://github.com/raylanlin/smarttune-cli.git#egg=smarttune[all]"
# Development
git clone https://github.com/raylanlin/smarttune-cli.git
cd smarttune-cli
pip install -e ".[dev,all]"
Requires Python 3.9+
For Agents
SmartTune was designed specifically for LLM agent tool-calling workflows. Every aspect of the CLI follows agent-friendly principles:
| Principle | Implementation |
|---|---|
| Deterministic output | No interactive prompts, no TUI, no progress bars when piped to files. Same input → same output. |
| Structured by default | JSON on stdout via --format json (CLI) or smarttune_analyze_log (MCP) — one shared schema. Markdown/HTML via --report md|html. No parsing fragile ANSI-escaped terminal dumps. |
| Self-describing | stune platforms lists available adapters. Error codes are standardized (E10xx–E50xx). Exit codes are meaningful. |
| Fail-fast & isolated | Single-module failure doesn't abort the full analysis. Each module gets its own try/except block. |
| Config-free | Zero config files needed. Everything is flags or auto-detected. No env vars required. |
| Offline-first | No network calls. No API keys. No rate limits. Safe for isolated/air-gapped environments. |
| Machine-recommendable | Tuning suggestions include confidence scores and reasoning, not just parameter values. Agents can weigh multiple recommendations. |
What agents can learn through SmartTune
SmartTune isn't just a tool agents call — it's how agents learn the craft of flight controller tuning:
| Skill | How SmartTune teaches it |
|---|---|
| PID tuning intuition | Step-response analysis with confidence scores. Agents learn which overshoot/rise-time patterns call for higher Kp vs. damping. |
| Frequency-domain reasoning | FFT spectra with peak detection. Agents learn to distinguish vibration sources (prop/ motor/ frame resonance) from the spectrum shape. |
| Filter design logic | Notch and low-pass filter recommendations with Bode plots. Agents see the tradeoff between filtering and phase lag. |
| Platform differences | ArduPilot vs Betaflight parameter conventions. ParamRef maps between them — agents learn to translate tuning knowledge across platforms. |
| Safety awareness | All recommendations are capped at ±25%. Agents learn conservative tuning by default. |
| Rule-based reasoning | The 6-layer knowledge base is plain JSON. Agents can read, understand, and even propose rule changes by writing to their user layer. |
What agents can do with SmartTune
- Batch analysis — analyze hundreds of logs with a loop; JSON output per file
- Auto-tuning — feed recommendations back into a flight controller via MAVLink or CLI
- Fleet monitoring — aggregate vibration/PID metrics across multiple aircraft
- CI/CD integration — run
stune analyzeas part of a pre-flight validation pipeline - Collaborative diagnosis — have the agent compare logs from before/after a crash
MCP Server (Model Context Protocol)
SmartTune includes a read-only MCP server that lets LLM agents call analysis tools directly — no shell, no subprocess, no arbitrary file writes.
MCP requires Python 3.10+ (the MCP SDK does not support 3.9). The
stuneCLI itself still runs on Python 3.9. On 3.9,pip install ".[mcp]"silently skips the mcp package andsmarttune-mcpexplains why instead of crashing.
Install with MCP support:
pip install -e ".[all,mcp]"
Run the MCP server:
smarttune-mcp # stdio transport (for agent frameworks)
# or
python -m smarttune.mcp_server
Available MCP tools (16 total):
| Tool | Purpose |
|---|---|
smarttune_list_platforms |
List supported platforms, extensions, and capabilities |
smarttune_log_quality |
Parse log and return quality score, data availability, validation issues |
smarttune_analyze_log |
Full analysis (PID + FFT + Filter + Mag + SysID + Hardware) as JSON/Markdown |
smarttune_analyze_pid |
PID step response analysis per axis |
smarttune_analyze_fft |
FFT vibration spectrum with peak detection |
smarttune_analyze_magfit |
Magnetometer calibration analysis |
smarttune_analyze_sysid |
ARX system identification (natural freq, damping ratio) |
smarttune_analyze_filter |
Filter transfer function analysis (Bode plot data) |
smarttune_analyze_hardware |
Hardware configuration report |
smarttune_generate_plot |
Generate analysis chart as base64 PNG |
smarttune_list_param_groups |
NEW v3.2 — Browse a platform's parameter groups (start here) |
smarttune_list_params |
List parameters in one group or category — compact rows |
smarttune_get_param |
NEW v3.2 — Full definition of one parameter, incl. what each enum value means |
smarttune_search_params |
Ranked keyword search across names, descriptions and enum labels |
smarttune_validate_param |
⚠️ Validate one param name + value (enum membership as well as range) |
smarttune_validate_params |
NEW v3.2.1 — Validate a whole recommendation set in one call |
All tools are annotated readOnlyHint=True, destructiveHint=False, idempotentHint=True.
Response contract (v3.2) — one shape for every tool, so clients branch on fields instead of prose:
{ "ok": true, "platform": "ArduPilot", "...": "payload" }
{ "ok": false, "error_code": "E3002", "message": "Insufficient PID data in log",
"hint": "…", "retryable": false }
A rejected parameter value is a successful call with valid: false plus a verdict field
(ok / not_found / out_of_range / not_a_member / not_an_integer / unverifiable) —
not a transport error. All six parameter tools accept fw_version (e.g. "copter-4.5"; unknown versions return E4011 with the available list). And as of v3.2.1 the analysis tools attach validated /
validation_status to every recommendation they return, so the "always validate before
recommending" rule is enforced by the payload itself; explicit validation is only needed for
values the agent adjusted afterwards.
stdout carries JSON-RPC only: every service call runs with stdout redirected to stderr, so a
stray print from a third-party log parser can no longer corrupt the stream.
⚠️ Parameter validation is mandatory. Before recommending ANY parameter change, call smarttune_validate_param(param_name, value, platform). It checks enum membership as well as numeric range, and returns a status: ok / not_found / out_of_range / not_a_member / not_an_integer / unverifiable. unverifiable means the table cannot confirm the value — the call did not approve it. This prevents agents from suggesting parameters that don't exist in the target firmware — a critical issue because:
- Betaflight 4.5+ renamed many parameters (
d_min_roll→d_max_roll,gyro_lowpass_hz→gyro_lpf1_static_hz) - Parameter names differ between firmware versions
- Some parameters have strict value ranges that must be respected
Security boundary:
- No shell execution — library calls only
- No arbitrary file writes — results are returned inline
- No parameter mutation — no MAVLink writes, no firmware flashing
- Path validation — allowed roots, extensions (
.bin,.log,.tlog,.bbl,.bfl,.ulg), file size limits, symlink resolution - Configurable via environment variables:
export SMARTTUNE_MCP_ALLOWED_ROOTS="/path/a:/path/b"
export SMARTTUNE_MCP_MAX_FILE_MB="300"
OpenClaw / Claude Desktop configuration:
{
"mcp": {
"servers": {
"SmartTune": {
"command": "smarttune-mcp",
"args": [],
"env": {
"SMARTTUNE_MCP_ALLOWED_ROOTS": "/home/user/.openclaw/workspace/files/inbox:/home/user/.openclaw/workspace/files/output:/tmp",
"SMARTTUNE_MCP_MAX_FILE_MB": "300"
}
}
}
}
}
Quick Start
# Full analysis (auto-detect platform)
stune analyze -i flight.bin
# With charts (human-friendly)
stune analyze -i flight.bbl --visual
# Per-module deep dive
stune pid -i flight.bin -a roll --visual
stune fft -i flight.bin --visual
stune magfit -i flight.bin
stune sysid -i flight.bin -a pitch
stune hardware -i flight.bin
# Export to Markdown report
stune analyze -i flight.bin --report md -o report.md
# Export to HTML report
stune analyze -i flight.bin --report html -o report.html
# List supported platforms
stune platforms
# Machine-readable output (same schema as the MCP server)
stune analyze -i flight.bin --format json
# Run a subset of modules / cap recommendations
stune analyze -i flight.bin --modules pid,fft --max-recommendations 10 -f json
Output Formats
SmartTune supports multiple output formats, each designed for a specific consumption mode:
| Format | Use Case | Example |
|---|---|---|
| Terminal | Human inspection in the shell | stune analyze -i flight.bin |
| JSON | Agent/script consumption | stune analyze -i flight.bin --format json |
| Markdown | Reports, READMEs, documentation | stune analyze -i flight.bin --report md -o report.md |
| HTML | Visual reports with embedded charts | stune analyze -i flight.bin --report html -o report.html |
--format json 🆕 v3.1
Every analysis command takes -f/--format json. The payload comes from the same services-layer
functions the MCP server calls, so CLI JSON and MCP JSON are the same schema — no second
serializer to drift.
stune analyze -i flight.bin -f json | jq '.modules.pid.axes.roll'
stune pid -i flight.bin -f json -a roll
stune fft -i flight.bin -f json
stune quality -i flight.bin -f json -o quality.json
stune filter -i flight.bin -f json
stune params --search notch -f json
stune platforms -f json
Contract:
| Guarantee | Detail |
|---|---|
| stdout is JSON only | Progress, hints and error panels go to stderr — | jq never chokes. -o file.json writes the payload to a file instead. |
| Envelope | schema_version, tool {name, version}, command, status, generated_at, then the command's own fields. |
| Errors are JSON too | status: "error" + error {code, type, message, hint}, exit code 1. No screen-scraping the failure path. |
| Strict JSON | NaN/Infinity are emitted as null — safe for strict parsers. |
| Reproducible | SMARTTUNE_DETERMINISTIC=1 omits generated_at so runs diff byte-for-byte in CI. |
{
"schema_version": "1.0",
"tool": { "name": "smarttune", "version": "3.1.0" },
"command": "pid",
"status": "error",
"error": {
"code": "E3002",
"type": "InsufficientPIDDataError",
"message": "Insufficient PID data in log",
"hint": ""
}
}
JSON output example
{
"platform": "ArduPilot",
"timestamp": "2026-05-03T22:30:00",
"pid": {
"roll": {
"rating": "GOOD",
"confidence": 0.87,
"kp": {"current": 0.12, "recommended": 0.14, "reason": "Slight oscillation at 8 Hz"},
"ki": {"current": 0.05, "recommended": 0.05, "reason": "No steady-state error"},
"max_overshoot_pct": 8.2,
"rise_time_ms": 85,
"settling_time_ms": 210
}
},
"fft": {
"vibration": {
"level_rms": 2.1,
"grade": "EXCELLENT"
},
"peaks": [
{"freq_hz": 47.5, "magnitude_db": -12.3, "source": "propeller"}
]
}
}
Commands
stune analyze
Full-spectrum analysis: PID + FFT + MagFit + hardware — all in one pass.
stune analyze -i flight.bin # Auto-detect
stune analyze -i flight.bbl --platform betaflight # Force platform
stune analyze -i flight.bin --visual # With charts
stune analyze -i flight.bin --report md -o report.md # Markdown export
stune analyze -i flight.bin --report html -o report.html # HTML export
stune pid
PID step-response analysis with per-axis tuning recommendations.
stune pid -i flight.bin # All axes
stune pid -i flight.bin -a roll # Single axis
stune pid -i flight.bbl --visual # Betaflight
stune fft
Frequency-domain vibration analysis with notch filter suggestions.
stune fft -i flight.bin # Full spectrum
stune fft -i flight.bin --visual # With spectrum plot
stune magfit
Magnetometer calibration — hard/soft iron offset, coverage, field strength.
stune magfit -i flight.bin # ArduPilot only
stune sysid
ARX system identification — natural frequency and damping ratio.
stune sysid -i flight.bin -a roll # Single axis
stune sysid -i flight.bin -a pitch --na 4 --nb 3 # Custom order
stune hardware
Full hardware configuration report: firmware version, sensors, battery, parameters.
stune hardware -i flight.bin
stune hardware -i flight.bbl
stune filter
Filter chain analysis with Bode plots.
stune filter -i flight.bin --gyro-filter 40 --visual
stune filter -i flight.bin --auto # Auto-derive from params
stune platforms
List all available platform adapters and their capabilities.
stune platforms
stune params — firmware parameter tables
Browse, look up, search and validate real firmware parameters. Tables are generated from
official firmware metadata by tools/build_param_tables.py —
see Parameter tables.
# What's available
stune params # tables, param counts, group counts, firmware
# Browse by parameter group (the firmware's own grouping)
stune params ap --groups # 194 ArduPilot groups
stune params ap --group ATC_ # attitude controller group
stune params bf --group PID_PROFILE # Betaflight PG_PID_PROFILE
stune params px4 --group "Multicopter Rate Control"
# Pick a firmware-version table (default: Copter-4.1 for ArduPilot)
stune params ap --fw-version copter-4.5 --group ATC_
stune params --validate ATC_RAT_RLL_P 0.45 -p ap --fw-version copter-4.5 # 4.5: max 0.5
# Browse by topic
stune params ap -c pid # pid / filter / mag / battery / rate / …
# One parameter: description, range, default, and what each enum value MEANS
stune params BATT_MONITOR
stune params MC_ROLLRATE_P
# Ranked keyword search — names, descriptions and enum labels
stune params --search notch
stune params --search "analog voltage" # finds BATT_MONITOR
# ⚠️ Validate before recommending (exit 0 = valid, 1 = invalid)
stune params --validate BATT_MONITOR 4 -p ap # ✓ 4 = Analog Voltage and Current
stune params --validate BATT_MONITOR 99 -p ap # ✗ not a valid value (lists allowed)
stune params --validate p_roll 999 -p bf # ✗ exceeds max 250
# Validate a whole recommendation set in one call (exit 0 only if all valid)
echo '[{"param":"BATT_MONITOR","value":4},{"param":"p_roll","value":45}]' \
| stune params --validate-batch - -p ap
# Data health (CI gate)
stune params --lint # exit 1 if any table has defects
Every subcommand supports -f json.
Supported Platforms
| Platform | Log Format | Parser | Status |
|---|---|---|---|
| ArduPilot | .bin / .log (onboard DataFlash) |
pymavlink | ✅ Full support |
| ArduPilot | .tlog (GCS telemetry) 🆕 v3.4 |
pymavlink | ⚠️ Screening only — see below |
| Betaflight | .bbl / .bfl (Blackbox) |
Pure Python | ✅ Full support |
| PX4 | .ulg (ULog) |
pyulog | ✅ PID / FFT / SysID / Quality (v3.0+) |
Telemetry logs (.tlog) 🆕 v3.4
A .tlog is what Mission Planner / MAVProxy / QGroundControl records over the radio link —
a fundamentally thinner source than the onboard log, and SmartTune treats it that way:
onboard .bin |
telemetry .tlog |
|
|---|---|---|
| Written by | flight controller (SD card) | ground station (PC) |
| Rate | loop rate, 400 Hz+, lossless | stream rates, 1–50 Hz, lossy |
| Rate controller | PIDR/PIDP/PIDY with P/I/D terms |
not streamed at all |
| Gyro | IMU at 400 Hz+ | RAW_IMU/ATTITUDE, 2–50 Hz |
| Coverage | whole flight | only while the link was up |
stune quality -i "2026-09-13 10-00-00.tlog" # states every limit up front
stune analyze -i flight.tlog -f json | jq '.telemetry_notes'
What SmartTune does with one:
- PID is reconstructed from
ATTITUDE_TARGET(desired body rates) vsATTITUDE(actual). P/I/D term breakdown does not exist in telemetry, so those series read zero — like the existing legacy-RATEfallback. If the vehicle never streamedATTITUDE_TARGET, PID analysis is skipped with a reason, not faked. - FFT is band-limited by the stream rate: a 10 Hz stream can only show 0–5 Hz, far below the 40–120 Hz band where prop and frame resonances live. The report says so.
- Parameters only exist if the GCS downloaded them during the recording.
- Radio dropouts, missing accel stream, and EKF-filtered rate sources are all reported
in
telemetry_notes(JSON) or the "Telemetry Log Limits" block (terminal). - A
.tlogrecorded from a PX4 vehicle is refused with a pointer to the onboard.ulg.
Every caveat is scored: telemetry logs cannot reach the top quality bands, and
quality.advice points at the onboard log for tuning work.
Auto-Detection
SmartTune identifies your log format from file headers — no --platform flag needed:
| Bytes | Platform |
|---|---|
0xA3 0x95 |
ArduPilot DataFlash |
8-byte timestamp + 0xFD/0xFE |
ArduPilot MAVLink telemetry (.tlog) |
H Product:Blackbox |
Betaflight Blackbox |
| ULog magic | PX4 ULog |
Architecture
┌─────────────────────────────────────────────┐
│ CLI Layer │
│ stune analyze / pid / fft / ... │
│ --report md / html │
└──────────────────┬──────────────────────────┘
│
┌──────────────────┤ ┌───────────────────────┐
│ │ │ MCP Server (stdio) │
│ │ │ smarttune-mcp │
│ │ │ JSON / Markdown out │
│ │ │ Read-only · No shell │
│ │ └───────────┬───────────┘
│ │ │
│ ┌───────────────▼──────────────▼────────────┐
│ │ Services Layer (shared) │
│ │ services/analysis.py · services/serialize │
│ └───────────────┬──────────────────────────┘
│ │
┌──────────────────▼──────────────────────────┐
│ Platform Adapter Layer │
│ ArduPilot · Betaflight · PX4 │
│ Parsers → FlightData (unified IR) │
└──────────────────┬──────────────────────────┘
│
┌──────────────────▼──────────────────────────┐
│ Analysis Engine (platform-aware) │
│ PID / FFT / SysID / MagFit / Filter / HW │
│ Per-platform modules: │
│ ardupilot/ → WebTools-aligned FFT │
│ betaflight/ → Wiener deconvolution FFT │
│ px4/ → stubs │
│ BF: Feedforward · RPM Filter · D-term │
│ Protocol-based interface constraints │
└──────────────────┬──────────────────────────┘
│ AnalysisResult + ParamRef
┌──────────────────▼──────────────────────────┐
│ Knowledge Base (6-layer deep merge) │
│ common → platform → user → Pro │
│ JSON-based rules — inspectable & editable │
└──────────────────┬──────────────────────────┘
│
┌──────────────────▼──────────────────────────┐
│ Output Layer │
│ Terminal (Rich) / JSON / Markdown / HTML │
│ ParamRef → platform-native parameter names │
└─────────────────────────────────────────────┘
Knowledge Base
A 6-layer deep-merge rule engine powers all tuning recommendations. Each layer overrides the previous:
| # | Layer | Location | Editable |
|---|---|---|---|
| 1 | Common physics rules | smarttune/knowledge/rules/common/ |
❌ Built-in |
| 2 | Platform rules | smarttune/knowledge/rules/{platform}/ |
❌ Built-in |
| 3 | User common | ~/.smarttune/knowledge/common/ |
✅ |
| 4 | User platform | ~/.smarttune/knowledge/{platform}/ |
✅ |
| 5 | Pro common | smarttune-knowledge-pro (optional) |
🔒 |
| 6 | Pro platform | smarttune-knowledge-pro (optional) |
🔒 |
Rules are standard JSON files. Add a file, restart the command, and the engine picks it up. No compilation, no database, no setup.
Preguntas sobre SmartTune MCP
¿Qué plataformas de controladores de vuelo son compatibles?
La herramienta es compatible con ArduPilot, Betaflight y PX4.
¿SmartTune requiere conexión a internet para funcionar?
No, está diseñado para funcionar primero de forma offline y es compatible con entornos aislados o air-gapped.
¿Puede la herramienta sugerir cambios de parámetros que puedan dañar mi firmware?
No, todas las recomendaciones se validan con tablas de parámetros de firmware reales y tienen un límite de ±25% por seguridad.
¿Cuál es el requisito para ejecutar el MCP server?
El MCP server requiere Python 3.10 o superior.