gr-mcp/README.md
Ryan Malloy 41dcebbf6d fix: update project URLs from GitHub to Gitea, switch to date-based versioning
- pyproject.toml URLs now point to git.supported.systems/MCP/gr-mcp
- README clone URL updated to match
- Version bumped to 2026.02.20 (date-based scheme)
- Published to PyPI as gnuradio-mcp==2026.2.20
2026-02-20 15:53:02 -07:00

286 lines
9.2 KiB
Markdown

# GR-MCP: GNU Radio MCP Server
[![Python Version](https://img.shields.io/badge/python-3.14%2B-blue.svg)](https://www.python.org/downloads/)
[![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)
**GR-MCP** is a [FastMCP](https://gofastmcp.com) server for [GNU Radio](https://www.gnuradio.org/) that enables programmatic, automated, and AI-driven creation of GNU Radio flowgraphs. It exposes 80+ MCP tools for building, validating, running, and exporting `.grc` files — plus block development, protocol analysis, and OOT module management.
> **What can you do with it?**
> - Build and validate flowgraphs programmatically
> - Generate custom GNU Radio blocks from natural language descriptions
> - Parse protocol specifications into decoder pipelines
> - Analyze IQ recordings to detect signal characteristics
> - Export blocks to distributable OOT modules
> - Run flowgraphs in Docker containers with real-time variable control
> - Install and manage OOT modules via Docker
## Quickstart
### 1. Install
```bash
git clone https://git.supported.systems/MCP/gr-mcp
cd gr-mcp
# Create venv with system site-packages (required for gnuradio)
uv venv --system-site-packages --python 3.14
uv sync
```
### 2. Run
```bash
uv run gnuradio-mcp
```
### 3. Add to your MCP client
**Claude Code:**
```bash
claude mcp add gnuradio-mcp -- uv run --directory /path/to/gr-mcp gnuradio-mcp
```
**Claude Desktop / Cursor / other MCP clients:**
```json
{
"mcpServers": {
"gnuradio-mcp": {
"command": "uv",
"args": ["run", "--directory", "/path/to/gr-mcp", "gnuradio-mcp"]
}
}
}
```
### Requirements
- Python >= 3.14
- GNU Radio (tested with GRC v3.10.12.0)
- Docker (optional — for runtime control, block testing, OOT builds)
- [uv](https://docs.astral.sh/uv/) package manager
> **Note:** GR-MCP is designed for single-session use. All connected MCP clients share the same flowgraph state. Run one server instance per concurrent session.
## Features
### Flowgraph Building (30 tools)
Build, edit, validate, and export `.grc` files:
| Category | Tools |
|----------|-------|
| Blocks | `make_block`, `remove_block`, `get_blocks` |
| Parameters | `get_block_params`, `set_block_params` |
| Ports | `get_block_sources`, `get_block_sinks` |
| Connections | `connect_blocks`, `disconnect_blocks`, `get_connections` |
| Validation | `validate_block`, `validate_flowgraph`, `get_all_errors` |
| Persistence | `save_flowgraph`, `load_flowgraph` |
| Code Gen | `generate_code` |
| Discovery | `get_all_available_blocks`, `search_blocks`, `get_block_categories` |
| Options | `get_flowgraph_options`, `set_flowgraph_options` |
| Python | `create_embedded_python_block`, `evaluate_expression` |
| Bypass | `bypass_block`, `unbypass_block` |
| Import/Export | `export_flowgraph_data`, `import_flowgraph_data` |
| OOT Paths | `load_oot_blocks`, `add_block_path`, `get_block_paths` |
### Block Development (18 tools, dynamically registered)
Generate, validate, test, and export custom blocks. These tools are registered on-demand via `enable_block_dev_mode` to minimize context usage:
| Category | Tools |
|----------|-------|
| Generation | `generate_sync_block`, `generate_basic_block`, `generate_interp_block`, `generate_decim_block` |
| Validation | `validate_block_code`, `parse_block_prompt` |
| Testing | `test_block_in_docker` |
| Integration | `inject_generated_block` |
| Protocol | `parse_protocol_spec`, `generate_decoder_chain`, `get_missing_oot_modules` |
| Signal | `analyze_iq_file` |
| OOT Export | `generate_oot_skeleton`, `export_block_to_oot`, `export_from_flowgraph` |
| Mode | `enable_block_dev_mode`, `disable_block_dev_mode`, `get_block_dev_mode` |
### Runtime Control (36 tools)
Run flowgraphs in Docker containers with real-time control:
| Category | Tools |
|----------|-------|
| XML-RPC | `connect`, `disconnect`, `get_status`, `list_variables`, `get_variable`, `set_variable` |
| Execution | `start`, `stop`, `lock`, `unlock` |
| ControlPort | `connect_controlport`, `disconnect_controlport`, `get_knobs`, `set_knobs`, `get_knob_properties`, `get_performance_counters`, `post_message` |
| Docker | `launch_flowgraph`, `list_containers`, `stop_flowgraph`, `remove_flowgraph`, `connect_to_container`, `capture_screenshot`, `get_container_logs` |
| Coverage | `collect_coverage`, `generate_coverage_report`, `combine_coverage`, `delete_coverage` |
| OOT Mgmt | `detect_oot_modules`, `install_oot_module`, `list_oot_images`, `remove_oot_image`, `build_multi_oot_image`, `list_combo_images`, `remove_combo_image` |
### MCP Resources
| Resource URI | Description |
|-------------|-------------|
| `oot://directory` | Curated directory of 20 OOT modules (12 preinstalled) |
| `oot://directory/{module}` | Details for a specific OOT module |
| `prompts://block-generation/*` | Block generation patterns and templates |
| `prompts://protocol-analysis/*` | Decoder pipeline guidance |
## Usage Examples
### Building a flowgraph
```python
# Create blocks
make_block(block_type="analog_sig_source_x", name="sig_source")
make_block(block_type="audio_sink", name="speaker")
# Configure
set_block_params(block_name="sig_source", params={
"freq": "1000",
"amplitude": "0.5",
"waveform": "analog.GR_COS_WAVE"
})
# Wire and save
connect_blocks(
source_block="sig_source", source_port="0",
sink_block="speaker", sink_port="0"
)
validate_flowgraph()
save_flowgraph(path="/tmp/my_flowgraph.grc")
```
### Generating a custom block
```python
enable_block_dev_mode()
generate_sync_block(
name="pm_demod",
description="Phase modulation demodulator",
inputs=[{"dtype": "complex", "vlen": 1}],
outputs=[{"dtype": "float", "vlen": 1}],
parameters=[{"name": "sensitivity", "dtype": "float", "default": 1.0}],
work_logic="Extract instantaneous phase from complex samples"
)
```
### Protocol analysis to decoder chain
```python
enable_block_dev_mode()
# Parse a protocol spec
protocol = parse_protocol_spec(
"GFSK at 250k baud, deviation: 25khz, preamble 0xAA, sync 0x2DD4"
)
# Generate the decoder pipeline
chain = generate_decoder_chain(protocol=protocol, sample_rate=2000000.0)
# Returns: blocks, connections, variables, missing_oot_modules
```
### Exporting to an OOT module
```python
enable_block_dev_mode()
# Generate block
block = generate_sync_block(name="my_filter", ...)
# Export to distributable OOT module
export_block_to_oot(
generated=block,
module_name="mymodule",
output_dir="/path/to/gr-mymodule",
author="Your Name"
)
# Creates: CMakeLists.txt, python/mymodule/my_filter.py, grc/mymodule_my_filter.block.yml
```
### Runtime control (Docker)
```python
# Launch flowgraph in container
launch_flowgraph(
flowgraph_path="/path/to/flowgraph.py",
name="my-sdr",
xmlrpc_port=8080,
enable_vnc=True
)
# Tune in real-time
connect_to_container(name="my-sdr")
set_variable(name="freq", value=2.4e9)
# Inspect and clean up
capture_screenshot(name="my-sdr")
stop_flowgraph(name="my-sdr")
```
## Architecture
```
src/gnuradio_mcp/
├── server.py # FastMCP app entry point
├── models.py # Pydantic models for all tools
├── utils.py # Unique IDs, error formatting
├── oot_catalog.py # Curated OOT module directory
├── middlewares/
│ ├── platform.py # GNU Radio Platform wrapper
│ ├── flowgraph.py # Block/connection management
│ ├── block.py # Parameter/port access
│ ├── ports.py # Port resolution utilities
│ ├── docker.py # Docker container lifecycle
│ ├── xmlrpc.py # XML-RPC variable control
│ ├── thrift.py # ControlPort/Thrift client
│ ├── oot.py # OOT module Docker builds
│ ├── block_generator.py # Code generation for custom blocks
│ ├── oot_exporter.py # Export blocks to OOT modules
│ └── protocol_analyzer.py # Protocol parsing, decoder chains, IQ analysis
└── providers/
├── base.py # PlatformProvider (flowgraph tools)
├── mcp.py # McpPlatformProvider (registers tools)
├── runtime.py # RuntimeProvider (Docker/XML-RPC/Thrift)
├── mcp_runtime.py # McpRuntimeProvider (registers tools)
├── block_dev.py # BlockDevProvider (generation/analysis)
└── mcp_block_dev.py # McpBlockDevProvider (dynamic registration)
```
**Data flow:** GNU Radio objects → Middlewares (validation/rewrite) → Pydantic Models (serialization) → MCP Tools
## Development
```bash
# Install all dependencies
uv sync --all-extras
# Run tests
pytest
# Run specific test suite
pytest tests/unit/
pytest tests/integration/
# Pre-commit hooks (black, flake8, isort, mypy)
pre-commit run --all-files
```
## Docker Images (Optional)
For runtime control and block testing:
```bash
# Runtime image (Xvfb + VNC + ImageMagick)
docker build -f docker/Dockerfile.gnuradio-runtime -t gnuradio-runtime:latest docker/
# Coverage image (adds python3-coverage)
docker build -f docker/Dockerfile.gnuradio-coverage -t gnuradio-coverage:latest docker/
```
## License
[MIT](LICENSE)