Serveur MCP SmartTune
Commit 13 sept. 2026Analyse les journaux de vol d'ArduPilot, Betaflight et PX4 pour fournir des recommandations de réglage PID, FFT et de filtrage pour les contrôleurs de vol de drones.
Aussi connu sous raylanlin/smarttune-cli
- Étoiles
- 33
- Outils
- —
- Téléchargements, 30 jours
- —
- Dernière version
- —
- Dernier commit
- 13 sept. 2026
- Licence
- MIT
Qu'est-ce que SmartTune MCP ?
SmartTune est un serveur MCP. Analyse les journaux de vol d'ArduPilot, Betaflight et PX4 pour fournir des recommandations de réglage PID, FFT et de filtrage pour les contrôleurs de vol de drones.
Résumé généré à partir du README du projet
À propos du MCP server SmartTune
Les ingénieurs et développeurs de drones peuvent utiliser SmartTune pour transformer les journaux de vol bruts d'ArduPilot, Betaflight et PX4 en paramètres de réglage exploitables. En analysant la réponse à l'échelon, les spectres de vibration FFT et l'étalonnage du magnétomètre, le système fournit des recommandations spécifiques pour les réglages PID, FFT et les filtres. Il est conçu pour fonctionner hors ligne sans nécessiter de clés API ni d'accès réseau, ce qui le rend adapté aux environnements isolés.
Les utilisateurs peuvent interagir avec le système via une interface en ligne de commande ou un MCP server en lecture seule pour les flux de travail d'agents LLM. Le MCP server propose 16 outils spécialisés, incluant smarttune_analyze_log pour une analyse complète et smarttune_validate_params pour garantir que les valeurs suggérées correspondent à des versions et des plages de firmware spécifiques. Le serveur fonctionne via le transport stdio et nécessite Python 3.10 ou une version supérieure pour les fonctionnalités MCP. Toutes les recommandations sont limitées à une variation de ±25 % afin de maintenir la sécurité pendant le processus de réglage.
Ce que vous pouvez faire avec
- 1Recommandations de réglage PID automatiséesUn agent IA peut analyser un journal de vol pour suggérer des deltas de paramètres PID spécifiques basés sur les modèles de réponse à l'échelon.
- 2Identification des sources de vibrationUn développeur peut utiliser l'analyse du spectre FFT pour distinguer les résonances provenant du moteur, de l'hélice ou du châssis.
- 3Validation des paramètres du firmwareAvant d'appliquer des changements, un agent peut vérifier qu'un nom et une valeur de paramètre suggérés sont valides pour une version de firmware spécifique.
- 4Traitement par lots de journaux de volLes utilisateurs peuvent exécuter une boucle pour analyser des centaines de journaux simultanément et exporter les résultats dans un format JSON structuré.
Extrait du README du projet. Chaque cas d'utilisation est vérifié par rapport à une citation du document.
Configuration
SMARTTUNE_MCP_ALLOWED_ROOTSSMARTTUNE_MCP_MAX_FILE_MB
| Nom | Description | Type |
|---|---|---|
| SMARTTUNE_MCP_ALLOWED_ROOTS | — | |
| SMARTTUNE_MCP_MAX_FILE_MB | — |
Vérifications automatisées
Exécuté le 14 nov. 2026Rapport complet →Pas encore vérifié. Un serveur nécessite un score de 80, aucune faille sérieuse et suffisamment de données pour que nous puissions effectuer les vérifications. Fonctionnement des vérifications · Ce qu'il faut corriger pour gagner des points
- Dépôt source lié et accessibleraylanlin/smarttune-cli is public and reachablegithub.com/raylanlin/smarttune-cli ↗Réussi
- Le nom du package correspond au dépôt sourceNon vérifié
- Provenance du build (attestation Sigstore)Non vérifié
- Licence open source (OSI)MITspdx.org/licenses/MIT.html ↗Réussi
- Commit ou version publiée au cours de l'année écouléeLast commit or release 2026-09-13github.com/raylanlin/smarttune-cli ↗Réussi
- OpenSSF ScorecardNon vérifié
- Nom du package non proche d'un package populaireNon vérifié
- Aucun avis critique dans le package ou ses dépendancesNon vérifié
- Aucune instruction cachée destinée au modèle0 tool descriptions and the README read; no override phrases, credential paths or hidden charactersRéussi
- Les outils destructifs sont étiquetésNon vérifié
- Le point de terminaison distant répond à la poignée de main MCPNon vérifié
README
Voir sur 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.
Questions sur SmartTune MCP
Quelles plateformes de contrôleurs de vol sont prises en charge ?
L'outil prend en charge ArduPilot, Betaflight et PX4.
SmartTune nécessite-t-il une connexion Internet pour fonctionner ?
Non, il est conçu pour fonctionner en priorité hors ligne et fonctionne dans des environnements isolés ou sécurisés (air-gapped).
L'outil peut-il suggérer des modifications de paramètres susceptibles d'endommager mon firmware ?
Non, toutes les recommandations sont validées par rapport aux tables de paramètres réelles du firmware et sont limitées à ±25 % par mesure de sécurité.
Quelle est la configuration requise pour exécuter le MCP server ?
Le MCP server nécessite Python 3.10 ou une version supérieure.