39 Commits

Author SHA1 Message Date
ce785029f4 feat: add generate_grc_yaml tool for GNU Radio Companion block definitions
Blocks generated by gr-mcp now have a first-class path to GRC's
graphical editor. Previously, .block.yml was only produced as a
side-effect of full OOT export — now clients can generate YAML
standalone to preview, customize, or use without a full OOT module.

- New MCP tool: generate_grc_yaml (registered in block dev mode)
- New model: GrcYamlResult with yaml_content, notes, filename
- Enhanced YAML generation: flags, asserts from min/max bounds,
  parameter descriptions, docstring extraction
- New prompt resource: prompts://block-generation/grc-yaml
- 10 new unit tests for GRC YAML generation (475 total, 7 skipped)
2026-02-24 09:47:26 -07:00
212832e7e4 feat: expose protocol analysis, OOT export tools; harden for release
Wire up protocol analysis (parse_protocol_spec, generate_decoder_chain,
get_missing_oot_modules), signal analysis (analyze_iq_file), and OOT
export (generate_oot_skeleton, export_block_to_oot, export_from_flowgraph)
as MCP tools with integration tests.

Security fixes from Hamilton review:
- Remove `from __future__ import annotations` from tool registration
  files (breaks FastMCP schema generation)
- Add blocklist guard to evaluate_expression (was unsandboxed eval)
- Replace string interpolation with base64 encoding in Docker test
  harness (prevents code injection)
- Add try/finally cleanup for temp files and Docker containers
- Replace assert with proper ValueError in flowgraph block creation
- Log OOT auto-discovery failures instead of swallowing silently

Packaging:
- Move entry point to src/gnuradio_mcp/server.py with script entry
  point (uv run gnuradio-mcp)
- Add PyPI metadata (authors, license, classifiers, urls)
- Add MIT LICENSE file
- Rewrite README for current feature set (80+ tools)
- Document single-session limitation
2026-02-20 13:17:11 -07:00
5db7d71d2b feat: add AI-assisted block development tools
Implements complete workflow for generating GNU Radio blocks from
descriptions:

Block Generation:
- generate_sync_block, generate_basic_block, generate_interp_block,
  generate_decim_block tools for creating different block types
- Template-based code generation with customizable work logic
- Automatic validation via AST parsing and signature checking

Protocol Analysis:
- Parse protocol specifications into structured models
- Generate decoder pipelines matching modulation to demodulator blocks
- Templates for BLE, Zigbee, LoRa, POCSAG, ADS-B protocols

OOT Export:
- Export generated blocks to full OOT module structure
- Generate CMakeLists.txt, block YAML, Python modules
- gr_modtool-compatible output

Dynamic Tool Registration:
- enable_block_dev_mode/disable_block_dev_mode for context management
- Tools only registered when needed (reduces LLM context usage)

Includes comprehensive test coverage and end-to-end demo.
2026-02-09 12:36:54 -07:00
e63f6e1ba0 test: add coverage for dynamic runtime mode and client capabilities
Add integration tests for:
- TestDynamicRuntimeMode (5 tests): verify enable/disable toggle
  behavior, tool registration/removal, idempotency
- TestClientCapabilities (2 tests): verify structured capability
  output and roots listing

Total test count: 370 → 377
2026-02-02 13:08:18 -07:00
3811099623 feat: dynamic runtime tool registration to reduce context usage
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.
2026-02-02 02:11:53 -07:00
bf92c70d3b feat: auto-detect OOT modules from flowgraph files
Add detect_oot_modules() MCP tool that analyzes .py or .grc flowgraphs
to identify required OOT modules, enabling automatic Docker image
selection without manual image= parameter specification.

Detection approaches:
- Python files: parse import statements (gnuradio.module, import module)
- GRC files: heuristic prefix matching + explicit block-to-module mappings

New features:
- OOTDetectionResult model with detected_modules, unknown_blocks, and
  recommended_image fields
- auto_image parameter on launch_flowgraph() for automatic image selection
- _BLOCK_TO_MODULE mapping for edge cases like lora_rx → lora_sdr
- Comprehensive core block filtering (variable_*, filter blocks, xmlrpc)

Tests: 23 new unit tests covering Python detection, GRC detection,
image recommendation, and edge cases.
2026-02-02 01:19:55 -07:00
15c17aa0a0 fix: re-register orphaned images and harden catalog branches
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.
2026-02-02 00:02:12 -07:00
66f1b260f2 feat: multi-OOT combo images via multi-stage Docker builds
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.
2026-02-01 22:45:14 -07:00
2956ceab0f fix: correct OOT catalog branches and add binding hash fixup
- 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
2026-01-31 15:04:50 -07:00
521c306173 feat: add OOT module directory as MCP resources
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.
2026-01-31 14:43:55 -07:00
e6293da1b6 feat: add OOT module installer for building modules into Docker images
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)
2026-01-31 10:01:38 -07:00
f720f767ee feat: add Docker compat patching pipeline for flowgraph launches
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.
2026-01-30 19:22:20 -07:00
dca4e80857 feat: add incremental OOT block path management and auto-discovery
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.
2026-01-30 18:02:27 -07:00
e8b3600e60 feat: add LoRa SDR receiver with Docker runtime infrastructure
LoRa receiver flowgraph built programmatically via gr-mcp:
- osmosdr_source → low_pass_filter → lora_rx → message_debug
- XML-RPC server for runtime variable control (samp_rate,
  center_freq) with introspection enabled
- Qt frequency sink for spectrum visualization

Docker infrastructure:
- gnuradio-lora: gr-lora_sdr OOT module from EPFL (chirp spread spectrum)
- gnuradio-lora-runtime: combined runtime with Xvfb + gr-lora_sdr
- Compose file, entrypoint, and launch script for LoRa receiver

Also includes:
- lora_scanner.py: multi-SF LoRa scanner example
- lora_infrastructure_test.py: hardware-free pipeline validation
  (signal_source → throttle → null_sink + xmlrpc variable control)
- Integration tests for LoRa scanner flowgraph construction

End-to-end pipeline validated: launch_flowgraph → connect_to_container →
list_variables → get/set_variable all working through Docker + XML-RPC.
2026-01-30 13:55:40 -07:00
f3efb36435 feat: add gap analysis tools, OOT block loading, and configurable Docker image
Source changes spanning three features:

- Gap analysis: 12 new MCP tools (generate_code, load_flowgraph,
  search_blocks, get_block_categories, flowgraph options, embedded
  Python blocks, expression evaluation, block bypass, export/import)
- OOT support: load_oot_blocks tool + auto-discovery of paths like
  /usr/local/share/gnuradio/grc/blocks for third-party modules
- Docker: configurable image parameter on launch_flowgraph for
  running OOT-enabled containers (e.g. gnuradio-lora-runtime)

Resolves merge from feat/oot-block-paths into gap analysis work.
All 274 tests pass (204 unit + 70 integration).
2026-01-30 13:55:21 -07:00
e9ac115728 feat: add OOT (Out-of-Tree) block path loading support
Add load_oot_blocks MCP tool to dynamically load GNU Radio OOT modules.

Since GRC's Platform.build_library() clears all blocks on every call,
the implementation combines default block paths with OOT paths before
rebuilding. This allows loading custom blocks from:
- /usr/local/share/gnuradio/grc/blocks (locally-built)
- Custom user-specified directories

Implementation:
- PlatformMiddleware.load_oot_paths(): validates paths, combines with
  defaults, rebuilds library
- PlatformProvider.load_oot_blocks(): exposes method to MCP layer
- McpPlatformProvider: registers load_oot_blocks tool

Returns useful diagnostics: added_paths, invalid_paths, and block
counts before/after reload.
2026-01-29 18:35:16 -07:00
fdcbffba1a tests: add integration tests for runtime middleware
Add comprehensive integration tests that don't require Docker:

- test_xmlrpc_subprocess.py: Tests XmlRpcMiddleware against a real
  subprocess-based XML-RPC server. Covers connection, variable
  discovery, get/set operations, and flowgraph control (18 tests).

- test_mcp_runtime.py: Tests MCP runtime tools via FastMCP Client.
  Verifies connect, disconnect, list_variables, get_variable,
  set_variable, and flowgraph control work end-to-end (15 tests).

- test_fm_scanner.py: Tests signal probe functionality and FM scanner
  parsing. Includes unit tests for helper functions and integration
  tests for flowgraph construction with signal probe blocks (18 tests).

All 59 integration tests pass. These tests provide faster feedback
than Docker-based tests while still exercising real XML-RPC
communication and flowgraph construction.
2026-01-29 05:14:29 -07:00
27f651307e fix: remove stale lru_cache from FlowGraphMiddleware.get_block
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.
2026-01-28 21:37:04 -07:00
c793208932 runtime: handle GRC servers without XML-RPC introspection
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.
2026-01-28 20:46:11 -07:00
75d19eb6dd runtime: add dynamic port allocation for Docker containers
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.
2026-01-28 14:28:59 -07:00
0afb2f5b6e runtime: Phase 2 ControlPort/Thrift integration
Add ControlPort/Thrift support as an alternative transport to XML-RPC:

New middleware:
- ThriftMiddleware wrapping GNURadioControlPortClient

New MCP tools:
- connect_controlport, disconnect_controlport
- get_knobs (with regex filtering), set_knobs (atomic)
- get_knob_properties (units, min/max, description)
- get_performance_counters (throughput, timing, buffers)
- post_message (PMT injection to block ports)

Docker support:
- enable_controlport param in launch_flowgraph
- ENABLE_CONTROLPORT env in entrypoint.sh
- ControlPort config generation in ~/.gnuradio/config.conf

Models: KnobModel, KnobPropertiesModel, PerfCounterModel,
ThriftConnectionInfoModel, plus ContainerModel updates.
2026-01-28 12:05:32 -07:00
bfab802e05 coverage: add cross-process coverage collection for containerized flowgraphs
New MCP tools:
- collect_coverage(name) - combine parallel files, return summary
- generate_coverage_report(name, format) - HTML/XML/JSON reports
- combine_coverage(names) - aggregate across test runs
- delete_coverage(name?, older_than_days?) - cleanup

Modified:
- launch_flowgraph() now accepts enable_coverage parameter
- stop() uses 30s timeout for graceful shutdown (coverage needs atexit)

Docker:
- Dockerfile.gnuradio-coverage extends runtime with python3-coverage
- entrypoint-coverage.sh wraps execution with coverage run
- .coveragerc configured for GNU Radio source paths

Tests: 125 unit tests (21 new), 80% coverage
2026-01-27 13:50:17 -07:00
91a442cdf9 tests: add RuntimeProvider coverage (82% → 94%)
Unit tests (35):
- Mocked DockerMiddleware and XmlRpcMiddleware
- Full coverage of orchestration logic, preconditions, state tracking

Integration tests (6):
- Real Docker containers with gnuradio-runtime image
- End-to-end: launch → connect → control variables → stop
- Skip gracefully when Docker/image unavailable

Total: 112 tests, 94% coverage
2026-01-27 10:16:47 -07:00
2084c41228 runtime: Phase 1 Docker + XML-RPC control
Add RuntimeProvider with 17 MCP tools for controlling running flowgraphs:
- Container lifecycle: launch, list, stop, remove
- Connection: connect by URL or container name
- Variable control: list, get, set via XML-RPC introspection
- Flowgraph execution: start, stop, lock, unlock
- Visual feedback: screenshot capture, container logs

Docker is optional - 10 tools work without it for external flowgraphs.

Includes:
- DockerMiddleware wrapping docker.DockerClient
- XmlRpcMiddleware wrapping xmlrpc.client.ServerProxy
- Dockerfile with Xvfb + ImageMagick + VNC for headless QT
- 29 new unit tests (71 total)
2026-01-27 09:48:44 -07:00
fdc42c9bed Upgrade to FastMCP 3.0 and Python 3.14
- Bump version to 0.2.0
- Require Python 3.14+
- Update to FastMCP 3.0.0b1 with new Client API
- Update tests for FastMCP 3.0 (Pydantic models in .data)
- Pin modern dependency versions
2026-01-26 16:46:05 -07:00
Yoel bassin
664c2adedc add tests for FastMCP integration and update pre-commit 2026-01-05 20:52:48 +02:00
Yoel Bassin
f5a0629da7 main - fix: Fix using already populated GRC file and connection of hidden ports 2025-04-27 20:51:48 +03:00
Yoel Bassin
6d6e4d0fc2 main - fix: Change BlockModel key to name 2025-04-27 17:16:13 +03:00
Yoel Bassin
ac4105b210 main - feat: Create new BlockTypeModel and allow named ports 2025-04-27 16:58:50 +03:00
Yoel Bassin
42484d6c7d main - feat: Implement gnuradio element validation and errors 2025-04-27 12:33:29 +03:00
Yoel Bassin
f8174d07a1 main - feat: Implement block params update 2025-04-27 00:18:18 +03:00
Yoel Bassin
5485413efd main - feat: Implement block connection 2025-04-27 00:02:19 +03:00
Yoel Bassin
73bf514fc1 main - feat: Implement default block naming 2025-04-26 22:05:06 +03:00
Yoel Bassin
185e68f809 main - feat: Add pre-commit and fix all files 2025-04-26 21:52:32 +03:00
Yoel Bassin
37cb51f056 main - fiat: Implement BlockMiddleware and reorganize tests 2025-04-26 21:25:28 +03:00
Yoel Bassin
c5b4be6950 main - feat: Implement flowgraph block removal 2025-04-26 16:40:39 +03:00
Yoel Bassin
a4a3d124bd main - feat: Implement basic flowgraph 2025-04-26 16:35:43 +03:00
Yoel Bassin
eb0d9fd6be main - feat: Add real gnuradio data to tests 2025-04-26 16:08:09 +03:00
Yoel Bassin
377dab4ff9 main - feat: Create initial structure 2025-04-26 15:47:56 +03:00