MCP server for controlling and querying GNU Radio SDR flowgraphs
Project description
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
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file gnuradio_mcp_server-0.1.1.tar.gz.
File metadata
- Download URL: gnuradio_mcp_server-0.1.1.tar.gz
- Upload date:
- Size: 23.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1bf7cc123c688474476c2cbf1ff7ec963b83603728e29715a3974648dfbc494c
|
|
| MD5 |
3702b27d58e48403c68cbf858c113c12
|
|
| BLAKE2b-256 |
05a4ed1ff0b7d30ab8804168519b8dcc822fb86b9be239ed0fb7a5931748d916
|
File details
Details for the file gnuradio_mcp_server-0.1.1-py3-none-any.whl.
File metadata
- Download URL: gnuradio_mcp_server-0.1.1-py3-none-any.whl
- Upload date:
- Size: 20.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
561c8f6db3dfbf85403056027e7b2bd3857ad7f852ef15abe60d613e8b9b11fc
|
|
| MD5 |
fba88197e9461ecf5c548f3cedcd73eb
|
|
| BLAKE2b-256 |
545c8e21e48e6f21373b69bba92ac676a77c59ecc1af366bbe7ac640bb10496b
|