GNU Radio MCP Server
  
An MCP (Model Context Protocol) server that bridges an LLM to a live GNU Radio SDR flowgraph. Control your software-defined radio — tune frequencies, adjust gain, capture IQ samples, analyse spectra, and sweep for signals — all through natural language via any MCP-compatible client.
Architecture
┌─────────────┐ MCP (stdio / HTTP) ┌──────────────────┐
│ LLM / │◄──────────────────────────────►│ gnuradio_mcp │
│ Claude │ tool calls & │ MCP Server │
│ Desktop │ responses │ │
└─────────────┘ └──┬──────────┬───┘
│ │
XML-RPC │ │ ZMQ SUB
(control) │ │ (IQ data)
▼ ▼
┌────────────────────┐
│ GNU Radio │
│ Companion │
│ Flowgraph │
│ ┌──────────────┐ │
│ │ XMLRPC Server │ │
│ │ ZMQ PUB Sink │ │
│ └──────────────┘ │
└────────┬───────────┘
│
▼
┌────────────────────┐
│ SDR Hardware │
│ (HackRF / RTL-SDR │
│ / USRP / Sim) │
└────────────────────┘
Quick Start (Simulation — No Hardware)
pip install gnuradio-mcp-server
# Open simulation_mcp.grc in GNU Radio Companion and click Run
# (provides two test tones at +10 kHz and +50 kHz from center)
gnuradio-mcp
Quick Start (HackRF)
pip install gnuradio-mcp-server
# Open hackrf_mcp.grc in GNU Radio Companion and click Run & ensure HackRF is connected
GNURADIO_HARDWARE=hackrf gnuradio-mcp
Claude Desktop Integration
Add the following to your claude_desktop_config.json:
{
"mcpServers": {
"gnuradio_mcp": {
"command": "gnuradio-mcp",
"args": [],
"env": {
"GNURADIO_HARDWARE": "hackrf",
"GNURADIO_GR_HOST": "127.0.0.1",
"GNURADIO_GR_XMLRPC_PORT": "8080",
"GNURADIO_GR_ZMQ_PORT": "5555"
}
}
}
}
For HTTP transport:
{
"mcpServers": {
"gnuradio_mcp": {
"url": "http://127.0.0.1:8000/mcp",
"transport": "streamable-http"
}
}
}
Tools Reference
| # | Tool Name | Description | Read-Only | |----|------------------------------------|-----------------------------------------------------|-----------| | 1 | gnuradio_flowgraph_start | Start the GNU Radio flowgraph | No | | 2 | gnuradio_flowgraph_stop | Stop the GNU Radio flowgraph | No | | 3 | gnuradio_flowgraph_status | Get flowgraph status and current parameters | Yes | | 4 | gnuradio_set_center_frequency | Set the SDR center frequency | No | | 5 | gnuradio_set_sample_rate | Set the SDR sample rate | No | | 6 | gnuradio_set_gain | Set the SDR gain (IF/RF/BB stages) | No | | 7 | gnuradio_set_variable | Set an arbitrary flowgraph variable | No | | 8 | gnuradio_get_variable | Read an arbitrary flowgraph variable | Yes | | 9 | gnuradio_list_variables | List all flowgraph variables | Yes | | 10 | gnuradio_capture_samples | Capture IQ samples and return a power summary | Yes | | 11 | gnuradio_get_spectrum_snapshot | FFT/PSD analysis with peak detection | Yes | | 12 | gnuradio_detect_signals | Sweep a frequency range and detect active signals | Yes | | 13 | gnuradio_ping | Health check (XML-RPC + ZMQ connectivity) | Yes |
Environment Variables
All variables use the GNURADIO_ prefix:
| Variable | Default | Description | |------------------------------|---------------|--------------------------------------| | GNURADIO_GR_HOST | 127.0.0.1 | GNU Radio host address | | GNURADIO_GR_XMLRPC_PORT | 8080 | XML-RPC server port | | GNURADIO_GR_ZMQ_PORT | 5555 | ZMQ PUB sink port | | GNURADIO_GR_XMLRPC_TIMEOUT| 5 | XML-RPC timeout in seconds | | GNURADIO_GR_ZMQ_TIMEOUT_MS| 3000 | ZMQ receive timeout in ms | | GNURADIO_HARDWARE | hackrf | Hardware type: hackrf/rtlsdr/usrp/simulation | | GNURADIO_FREQ_MIN_HZ | 1000000 | Minimum tunable frequency (Hz) | | GNURADIO_FREQ_MAX_HZ | 6000000000 | Maximum tunable frequency (Hz) | | GNURADIO_GAIN_MIN_DB | 0 | Minimum gain (dB) | | GNURADIO_GAIN_MAX_DB | 62 | Maximum gain (dB) | | GNURADIO_SAMP_RATE_MIN | 100000 | Minimum sample rate (sps) | | GNURADIO_SAMP_RATE_MAX | 20000000 | Maximum sample rate (sps) | | GNURADIO_DEFAULT_SAMP_RATE| 2000000 | Default sample rate for DSP | | GNURADIO_TRANSPORT | stdio | Transport: stdio / streamable_http | | GNURADIO_HTTP_PORT | 8000 | HTTP transport port |
Edge Cases & Known Limitations
- Sample rate restart: Some SDR hardware (especially RTL-SDR) requires a flowgraph restart after changing the sample rate. The
gnuradio_set_sample_ratetool includes a warning about this.
- ZMQ dtype requirement: The ZMQ PUB Sink in your flowgraph must output
complex64(8 bytes per sample). Misaligned data will raise aGRHardwareError.
- Frequency clamping: Frequencies outside the configured
[freq_min_hz, freq_max_hz]range are rejected before being sent to hardware. Adjust the env vars for your specific hardware.
- Context overflow warning: Capturing more than 65,536 IQ samples triggers a warning, as the response summary may still be large. Use
gnuradio_get_spectrum_snapshotfor analysed results instead.
- XML-RPC not thread-safe: A new
ServerProxyis created per RPC call to avoid shared-state bugs in async contexts.
- ZMQ socket lifecycle: Each
recv_samplescall opens and closes its own ZMQ SUB socket. This is intentional — the slight overhead avoids shared-socket state issues.
Development
# Install in development mode
pip install -e ".[dev]"
# Run tests
pytest tests/ -v
# Run with HTTP transport
GNURADIO_TRANSPORT=streamable_http python -m gnuradio_mcp.server
License
MIT











