gnuradio-mcp-server
by Pranav-d33
README.md
# GNU Radio MCP Server
[](https://pypi.org/project/gnuradio-mcp-server/)
[](https://pypi.org/project/gnuradio-mcp-server/)
[](https://opensource.org/licenses/MIT)
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)
```bash
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)
```bash
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`:
```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:
```json
{
"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
1. **Sample rate restart**: Some SDR hardware (especially RTL-SDR) requires a flowgraph restart after changing the sample rate. The `gnuradio_set_sample_rate` tool includes a warning about this.
2. **ZMQ dtype requirement**: The ZMQ PUB Sink in your flowgraph **must** output `complex64` (8 bytes per sample). Misaligned data will raise a `GRHardwareError`.
3. **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.
4. **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_snapshot` for analysed results instead.
5. **XML-RPC not thread-safe**: A new `ServerProxy` is created per RPC call to avoid shared-state bugs in async contexts.
6. **ZMQ socket lifecycle**: Each `recv_samples` call opens and closes its own ZMQ SUB socket. This is intentional — the slight overhead avoids shared-socket state issues.
## Development
```bash
# 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
This server cannot be deployed
Maintenance
ActivityInactive
ResponsivenessNo issues