- Change test_block_in_docker to use gnuradio-runtime:latest instead of
non-existent gnuradio/gnuradio:latest
- Add auto_enable option to McpBlockDevProvider to register block dev
tools at startup (avoids MCP reconnect dance)
- Support GR_MCP_BLOCK_DEV=1 env var for auto-enabling
Restructure ClientCapabilities to explicitly surface all MCP 2025-11-25
client capabilities:
- roots: workspace directory exposure (listChanged notification support)
- sampling: server-initiated LLM requests (tools, context sub-caps)
- elicitation: server-prompted user input (form, url modes)
Each capability now has its own Pydantic model with clear documentation
about what it enables. Raw capabilities dict preserved for any unknown
or future capabilities.
Add get_client_capabilities and list_client_roots tools to inspect
MCP client information. These help debug MCP connections by exposing:
- Client name/version (e.g., "claude-code" v2.1.15)
- Protocol version and supported capabilities
- Root directories advertised by the client (typically CWD)
Both tools are always registered (part of mode control, not runtime).
Runtime tools now register on-demand rather than at startup:
- get_runtime_mode(): check mode status and available capabilities
- enable_runtime_mode(): dynamically register 36 runtime tools
- disable_runtime_mode(): remove runtime tools when not needed
At startup, only 33 design-time tools are registered. When runtime mode
is enabled, tool count increases to 69. This reduces context usage
significantly when only doing flowgraph design work.
Uses FastMCP's add_tool/remove_tool API for dynamic registration,
following MCP spec's notifications/tools/list_changed pattern.
build_module() now re-registers when a Docker image exists but the
registry entry is missing (e.g., after manual registry edits or
schema migrations). This fixes auto-build in combo workflows where
a module's image exists but isn't tracked.
Also fixes gr-rds catalog branch (main → maint-3.10) and adds
tests for per-entry registry validation and orphan re-registration.
Combine multiple OOT modules into a single Docker image using
multi-stage COPY from existing single-OOT images. No recompilation
needed — fast and deterministic.
New MCP tools: build_multi_oot_image, list_combo_images, remove_combo_image
Also hardens _load_registry() to validate per-entry instead of
all-or-nothing, preventing one corrupt entry from discarding the
entire registry.
Add two new OOT modules to the catalog:
- gr-leo: LEO satellite channel simulator from LibreSpace Foundation
- gr-dl5eu: DVB-T OFDM synchronization and TPS decoder
Update fix_binding_hashes.py to search python/**/bindings/ recursively,
supporting both GR 3.9 layout (python/bindings/) and GR 3.10 layout
(python/<module>/bindings/).
New installable modules:
- foo: Wireshark PCAP connector, burst tagger (bastibl, maint-3.10)
- owc: Optical Wireless Communication simulation (UCaNLab, main)
- dab: DAB/DAB+ digital audio broadcast receiver (hboeglen, maint-3.10)
gr-dab requires fdk-aac-dab (bundled subdir) + libfaad-dev at build time.
gr-foo is a dependency of the already-cataloged gr-ieee802-11.
Catalog now has 22 modules (12 preinstalled, 10 installable).
All 3 new modules built and verified in Docker.
- Fix branch names for 5 modules discovered during install attempts:
ieee802_11, ieee802_15_4, adsb (maint-3.10), iridium, nrsc5 (master)
- Remove packet_radio (repo gone/private)
- Add build_deps for modules that need them (castxml, autotools, Qt5)
- Add fix_binding_hashes.py helper script to Dockerfile builds to
prevent castxml regen failures from stale pybind11 header hashes
- Use tar build context in Docker builds to support COPY instruction
- Note inspector as incompatible with GR 3.10 (API changes)
Successfully built: ieee802_11, ieee802_15_4, adsb, iridium, nrsc5
Curated catalog of 20 GNU Radio OOT modules served via two MCP
resources (oot://directory, oot://directory/{name}). Each entry
includes git URL, branch, build deps, and a ready-to-use
install_oot_module() example.
Modules are tagged preinstalled when they ship with the
gnuradio-runtime base Docker image (12 of 20), so agents can
distinguish what's already available from what needs building.
Single MCP tool call builds any GNU Radio OOT module from a git repo
into a reusable Docker image. Generates a Dockerfile from template,
builds via Docker SDK, and tracks results in a persistent JSON registry.
New tools: install_oot_module, list_oot_images, remove_oot_image
Also changes launch_flowgraph default xmlrpc_port from 8080 to 0 (auto)
Flowgraphs generated by GRC on the host often fail in Docker containers
due to three issues:
1. message_debug constructor signature changed between GR 3.10.5 and
3.10.12 — strip the second arg for older runtimes
2. XML-RPC binds to localhost, unreachable from Docker host — rewrite
to 0.0.0.0
3. input('Press Enter to quit:') gets immediate EOF in detached
containers, killing the flowgraph instantly — inject signal.pause()
fallback after EOFError
All patches are applied in a single pass via patch_flowgraph() before
the container launches. The original file is never modified.
Add add_block_path() and get_block_paths() MCP tools for incremental
OOT module loading with BlockPathsModel responses. On startup, auto-scan
/usr/local/share and ~/.local/share for OOT blocks so modules like
gr-lora_sdr are available without manual configuration.
The lru_cache on get_block() caused three cache coherence bugs:
1. Removed blocks remained accessible — set_block_params would
modify a detached block object that no longer exists in the
flowgraph, so save_flowgraph would serialize stale state.
2. Re-created blocks with the same auto-generated name would
return the cached (removed) block instead of the new one.
3. Renamed blocks (via set_block_params id=...) left phantom
cache entries under the old name.
Fix: always look up blocks from the live flowgraph. Block lookup
is a linear scan of typically <20 blocks — no cache needed.
Raises KeyError instead of StopIteration for missing blocks.
GRC's SimpleXMLRPCServer uses register_instance() which doesn't
expose system.listMethods. Wrap the connectivity check in a
try/except so a Fault is treated as "connected" while
ConnectionRefusedError still propagates.
Prevent silent Docker bind failures by checking port availability
before container creation. Supports auto-allocation (port=0) and
patches compiled flowgraphs when the embedded XML-RPC port differs
from the requested port.