@h2loop/uav 1.1.0 → 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -59,7 +59,9 @@ skills/uav/ # on-demand `uav` skill + references
59
59
  data/ # bundled apm-params.json + built-in defaults
60
60
  bridge/ # optional MAVLink→MCP Python bridge
61
61
  plugins/ # BUILT bundle (index.js + worker/) — generated
62
- mcp.json # exa + mavlink MCP servers (disabled by default)
62
+ mcp.json # exa MCP server (disabled by default); mavlink is registered
63
+ # from src/index.ts's config hook — it needs a resolved
64
+ # interpreter + an ABSOLUTE script path, which static JSON can't give
63
65
  ```
64
66
 
65
67
  ## Run standalone
@@ -235,30 +237,29 @@ project KG.
235
237
 
236
238
  A local Python stdio server. Read-only tools: `read_params`, `param_get`, `param_get_all`,
237
239
  `get_messages`, `tail_telemetry`, `get_flight_mode`, `get_status`. The write tier
238
- (`param_set` / `param_set_batch`) is **off by default** — see below.
240
+ (`param_set` / `param_set_batch`) is **on by default** so tune→push→retest works out of the
241
+ box — see below.
239
242
 
240
243
  **Requires:**
241
- - Python ≥ 3.10 with `pymavlink>=2.4.49` and `mcp[cli]>=1.0.0` installed. The pack does **not**
244
+ - Python ≥ 3.10 with `pymavlink>=2.4.49` and `mcp[cli]>=1.0.0,<2` installed. The pack does **not**
242
245
  auto-provision a venv — install the deps yourself: `pip install -r bridge/requirements.txt`
243
246
  (ideally into a venv), and point the command's `python3` at that interpreter.
244
247
  - A reachable MAVLink endpoint (e.g. `udp:127.0.0.1:14550` from SITL or a telemetry radio),
245
248
  or a `.tlog`/`.log` file for offline replay.
246
249
  - The `bridge/` directory ships with the plugin (the `mcp.json` references it).
247
250
 
248
- Enable per-project in your Hydron config. **Param writes are OFF by default** (the bridge
249
- defaults to `--read-only`). To enable the tune→push→retest write tier, the command must pass
250
- **both** `--no-read-only` **and** `--allow-param-write`. ⚠ this lets the agent write params to
251
- a **live vehicle** — prefer SITL/bench.
252
- ```jsonc
253
- "mcp": {
254
- "mavlink": {
255
- "enabled": true,
256
- "command": ["python3", "<plugin-path>/bridge/uav_mavlink_bridge.py",
257
- "--connect", "udp:127.0.0.1:14550",
258
- "--no-read-only", "--allow-param-write"]
259
- }
260
- }
251
+ Ships **enabled**, with param writes **on** — the command passes `--no-read-only`
252
+ `--allow-param-write`, so `param_set` / `param_set_batch` are registered and the tuning loop
253
+ works with no configuration. ⚠ this lets the agent write params to a **live vehicle** — prefer
254
+ SITL/bench. To ship read-only, drop both flags.
255
+
256
+ No `--connect` is passed, so the target comes from the **`MAVLINK_CONNECT`** env var, falling
257
+ back to `udp:127.0.0.1:14550`:
258
+ ```bash
259
+ export MAVLINK_CONNECT=serial:/dev/ttyUSB0:57600 # COM3:57600 on Windows
261
260
  ```
261
+ Don't put it in the server's `environment` block — Hydron spreads that *over* `process.env`, so
262
+ it would shadow your export instead of defaulting to it.
262
263
 
263
264
  Connect-target forms: `udp:HOST:PORT` (default `udp:127.0.0.1:14550` = SITL/MAVProxy) |
264
265
  `tcp:HOST:PORT` | `serial:/dev/ttyUSB0:BAUD` | `/path/log.tlog` (offline replay); can also be
package/USAGE.md CHANGED
@@ -12,11 +12,12 @@ covers getting it running on **macOS, Linux, and Windows**, validating it works,
12
12
  - **Bun** — *only* needed to build the bundle from source or run the pack's tests; **not**
13
13
  needed to use a published pack.
14
14
  - **Python ≥ 3.10** — *only* for the optional live MAVLink bridge (`pymavlink>=2.4.49` +
15
- `mcp[cli]>=1.0.0`). The pack does **not** auto-provision a venv; you install the deps
15
+ `mcp[cli]>=1.0.0,<2`). The pack does **not** auto-provision a venv; you install the deps
16
16
  yourself (see §6). Plain `.bin` log analysis needs no Python.
17
17
  - *Optional:* `export EXA_API_KEY=…` for web grounding of bounds.
18
- - macOS/Linux are native; on **Windows** use **WSL2** for the bridge's Python (the bridge is
19
- POSIX-oriented).
18
+ - **macOS, Linux, and Windows are all native** — no WSL required. The pack resolves the Python
19
+ interpreter per-platform (`python3` / `python` / the `py -3` launcher); override it with
20
+ `UAV_PYTHON=<full path to python>` if you keep one in a venv.
20
21
 
21
22
  ---
22
23
 
@@ -41,14 +42,27 @@ hydron plugin add /path/to/uav-pack # add --project to scope it to
41
42
  Native. Nothing extra needed to use a published pack. Python ≥ 3.10 is only required for the
42
43
  optional MAVLink bridge (§6).
43
44
 
44
- ### Windows — use WSL2 for the bridge
45
- The `hydron plugin add` command itself is cross-platform. The MAVLink bridge, however, is
46
- POSIX-oriented Python, so run it (and ideally Hydron) inside **WSL2** (Ubuntu):
45
+ ### Windows
46
+ Native — run the same `hydron plugin add` in PowerShell. `.bin` log analysis, the checks, param
47
+ audit, tuning, plots and compare need no Python at all.
48
+
49
+ The Python-backed features (`uav_python`, `.tlog`/`.ulog` decode, the MAVLink bridge) need a
50
+ real Python ≥ 3.10 — install it from **python.org** and tick **“Add python.exe to PATH”**. The
51
+ pack finds it via the `py -3` launcher or `python`; there is no `python3` on Windows.
52
+
53
+ > Windows pre-installs *stub* `python.exe` / `python3.exe` aliases that only open the Microsoft
54
+ > Store. The pack ignores them (it probes by running code, not by looking on PATH), but if
55
+ > `python --version` opens the Store rather than printing a version, turn the stubs off under
56
+ > **Settings → Apps → Advanced app settings → App execution aliases**.
57
+
58
+ Pinning a specific interpreter (e.g. a venv) works everywhere:
47
59
  ```powershell
48
- wsl --install -d Ubuntu # PowerShell (admin), one-time; then open the Ubuntu shell
60
+ $env:UAV_PYTHON = "C:\path\to\.venv\Scripts\python.exe"
49
61
  ```
50
- Use the **VS Code "WSL" remote** (or Hydron's CLI inside WSL) so Hydron and the bridge share
51
- the same environment.
62
+
63
+ WSL2 also works and stays fully supported — but if you use it, install the pack **and** run
64
+ Hydron inside WSL (VS Code's **WSL** remote). A Windows-side Hydron cannot see a WSL-side
65
+ install; that mismatch is the usual cause of "the UAV tools didn't appear".
52
66
 
53
67
  ### Uninstall (any OS)
54
68
  ```bash
@@ -113,57 +127,84 @@ See `skills/uav/references/project-config.md` for the full list (`uav-thresholds
113
127
  A **MAVLink→MCP bridge**: a local Python stdio server Hydron spawns so the agent can query a
114
128
  live vehicle / SITL / log replay. Read-only tools: `get_status`, `get_flight_mode`,
115
129
  `read_params`, `param_get`, `param_get_all`, `get_messages`, `tail_telemetry`. The **write**
116
- tools `param_set`/`param_set_batch` are **off by default** (see the ⚠ note below).
130
+ tools `param_set`/`param_set_batch` are **on by default**, so tune→push→retest works out of
131
+ the box (see the ⚠ note below to turn them off).
117
132
 
118
- ### Install the Python deps yourself
133
+ ### Install the Python deps (the only manual step)
119
134
  The pack does **not** auto-provision a venv. The bridge needs Python ≥ 3.10 with
120
- `pymavlink>=2.4.49` and `mcp[cli]>=1.0.0`:
135
+ `pymavlink>=2.4.49` and `mcp[cli]>=1.0.0,<2`:
121
136
  ```bash
122
137
  pip install -r bridge/requirements.txt # ideally into a venv
123
138
  ```
124
- Then point the `mavlink` command's `python3` at that interpreter.
125
-
126
- ### Enable and configure (per-project in opencode.jsonc)
127
- The `mavlink` server ships in `mcp.json` **disabled by default**. Enable it per-project:
128
- ```jsonc
129
- "mcp": {
130
- "mavlink": {
131
- "enabled": true,
132
- "command": ["python3", "<plugin-path>/bridge/uav_mavlink_bridge.py",
133
- "--connect", "udp:127.0.0.1:14550"]
134
- }
135
- }
139
+ > The `<2` bound is required, not cosmetic: the MCP Python SDK **removed `mcp.server.fastmcp`
140
+ > in 2.x**, so the bridge fails at import on `mcp>=2`. Verified working on 1.29.0.
141
+
142
+ You do **not** need to edit any command. The plugin registers the `mavlink` server itself at
143
+ startup, resolving:
144
+
145
+ - **the interpreter** — via the same probe-by-execution resolver the `.tlog`/`.ulog` decoders
146
+ use, so `python3` / `python` / the Windows `py -3` launcher are all handled and Windows'
147
+ Microsoft-Store alias stubs are rejected. Pin a specific one with `UAV_PYTHON` (e.g. a venv:
148
+ `export UAV_PYTHON=/path/.venv/bin/python`, or `…\Scripts\python.exe` on Windows).
149
+ - **the script path** — absolute, inside the installed plugin bundle. This matters: Hydron
150
+ spawns local MCP servers with the cwd set to *your project*, so a bundle-relative path can
151
+ never resolve. That is why the server is no longer declared in `mcp.json`.
152
+
153
+ If no usable Python is found the server is not registered at all; if Python is found but can't
154
+ `import mcp, pymavlink`, it is registered **disabled** — so you see it listed rather than
155
+ getting a failed server on every launch. Check with `hydron mcp list`.
156
+
157
+ ### Point it at your vehicle
158
+ The `mavlink` server is registered **enabled**, with param writes on, so nothing needs enabling.
159
+ The one thing you may need to change is the connect target.
160
+
161
+ The command passes **no** `--connect`, so the bridge falls back to its own default —
162
+ which reads the **`MAVLINK_CONNECT`** environment variable, then `udp:127.0.0.1:14550`. So for
163
+ anything other than local SITL/MAVProxy, just export the target:
164
+ ```bash
165
+ export MAVLINK_CONNECT=serial:/dev/ttyUSB0:57600 # or COM3:57600 on Windows
136
166
  ```
137
167
  Connect-target forms: `udp:HOST:PORT` (default `udp:127.0.0.1:14550` = SITL/MAVProxy) |
138
- `tcp:HOST:PORT` | `serial:/dev/ttyUSB0:BAUD` | `/path/log.tlog` (offline replay). Can also be
139
- set via the `MAVLINK_CONNECT` env on the server.
168
+ `tcp:HOST:PORT` | `serial:/dev/ttyUSB0:BAUD` (on Windows a COM port, e.g. `COM3` or
169
+ `COM3:57600`) | `/path/log.tlog` (offline replay).
170
+
171
+ > Set it in the environment, **not** in the server's `environment` block: Hydron spawns local
172
+ > MCP servers with `{...process.env, ...environment}`, so a server-level entry *shadows* your
173
+ > export rather than acting as a default. That is why the plugin sets neither.
140
174
 
141
175
  > **"Connected" ≠ a live vehicle.** The panel shows `mavlink Connected` once the bridge *process*
142
176
  > starts. The tools only return data while something is **actually publishing MAVLink** at the
143
177
  > connect target. With no source, calls return empty / time out (`-32001`). Start your SITL/vehicle
144
178
  > (or leave it — log analysis via `uav_analyze` doesn't need the live bridge).
145
179
 
146
- > **Param writes are OFF by default.** The bridge defaults to `--read-only`. To enable the
147
- > tune→push→retest write tier (`param_set` / `param_set_batch`), the command must pass **both**
148
- > `--no-read-only` **and** `--allow-param-write`:
149
- > ```jsonc
150
- > "command": ["python3", "<plugin-path>/bridge/uav_mavlink_bridge.py",
151
- > "--connect", "udp:127.0.0.1:14550",
152
- > "--no-read-only", "--allow-param-write"]
180
+ > **⚠ Param writes are ON by default.** The shipped command passes `--no-read-only`
181
+ > `--allow-param-write`, which registers the tune→push→retest write tier (`param_set` /
182
+ > `param_set_batch`). This lets the agent **write parameters to a live vehicle**. Prefer
183
+ > SITL/bench, and point `MAVLINK_CONNECT` at a real airframe only when you intend that.
184
+ >
185
+ > To ship read-only, remove both flags from the `config` hook in `src/index.ts` — the bridge's own defaults are
186
+ > `read_only=True` / `allow_param_write=False`, and the write tools are then never registered:
187
+ > ```ts
188
+ > command: [...py, script], // no --no-read-only / --allow-param-write
153
189
  > ```
154
- > ⚠ this lets the agent **write parameters to a live vehicle** — prefer SITL/bench, and point
155
- > `--connect` at a real airframe only when you intend that.
190
+ > Reads (`param_get`, `param_get_all`, `read_params`, telemetry) are unaffected either way.
156
191
 
157
192
  ---
158
193
 
159
194
  ## 7. Troubleshooting
160
195
 
161
196
  - **UAV tools don't appear** → you didn't *fully* restart Hydron (a window reload isn't enough); the
162
- plugin loads once per process. Confirm it's installed with `hydron plugin list`. On Windows make
163
- sure Hydron is running in the **same WSL env** you're using.
164
- - **`mavlink` shows Disabled** → the `python3` in the `mavlink` command lacks `pymavlink`+`mcp`, or
165
- it isn't Python ≥ 3.10. Install the deps (`pip install -r bridge/requirements.txt`, ideally into a
166
- venv) and point the command at that interpreter.
197
+ plugin loads once per process. Confirm it's installed with `hydron plugin list`. If you install
198
+ under WSL, Hydron must also **run** under WSL — a Windows-side Hydron cannot see a WSL-side
199
+ install (check for the green `WSL: Ubuntu` badge in VS Code's bottom-left corner).
200
+ - **`uav_python` / `.ulog` decode → "no working Python 3 interpreter found"** → no runnable Python
201
+ on PATH. On Windows, install from python.org with **“Add python.exe to PATH”** ticked — the
202
+ pre-installed Store *stubs* don't count. Then reopen the terminal, or set `UAV_PYTHON` to the
203
+ interpreter's full path.
204
+ - **`mavlink` shows Disabled** → the interpreter in the `mavlink` command lacks `pymavlink`+`mcp`,
205
+ or it isn't Python ≥ 3.10. Install the deps (`pip install -r bridge/requirements.txt`, ideally
206
+ into a venv) and point the command at that interpreter. Note `mcp.json` ships `python3`, which
207
+ does not exist on Windows — change it to `python` or an absolute path.
167
208
  - **Every mavlink tool → `MCP error -32001: Request timed out`** → the bridge is Connected but **no
168
209
  MAVLink source is live** at the connect target. Start SITL / point `--connect` at a live link.
169
210
  - **`MCP error -32000: Connection closed`** → the bridge crashed at startup: usually the wrong Python
@@ -1,2 +1,6 @@
1
1
  pymavlink>=2.4.49
2
- mcp[cli]>=1.0.0
2
+ # Pinned below 2.0: the MCP Python SDK removed `mcp.server.fastmcp` in 2.x (FastMCP is gone,
3
+ # replaced by a different MCPServer API), so this bridge fails at import on mcp>=2. The
4
+ # unpinned `>=1.0.0` silently floated into that breaking major. Porting to the 2.x server API
5
+ # is a separate change; until then this range is the supported one (verified on 1.29.0).
6
+ mcp[cli]>=1.0.0,<2
package/mcp.json CHANGED
@@ -4,12 +4,6 @@
4
4
  "url": "https://mcp.exa.ai/mcp",
5
5
  "headers": { "x-api-key": "${EXA_API_KEY}" },
6
6
  "enabled": false
7
- },
8
- "mavlink": {
9
- "type": "local",
10
- "enabled": false,
11
- "command": ["python3", "./bridge/uav_mavlink_bridge.py", "--connect", "udp:127.0.0.1:14550"],
12
- "environment": { "MAVLINK_DIALECT": "ardupilotmega" },
13
- "timeout": 10000
14
7
  }
15
8
  }
9
+
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@h2loop/uav",
3
- "version": "1.1.0",
3
+ "version": "1.2.1",
4
4
  "description": "UAV domain pack for Hydron — ArduPilot/PX4 flight-log intelligence (analyze, triage, compare, tune)",
5
5
  "type": "module",
6
6
  "private": false,