Metadata-Version: 2.4
Name: gnuradio-mcp-server
Version: 0.1.1
Summary: MCP server for controlling and querying GNU Radio SDR flowgraphs
Author-email: Pranav Dhiran <dhiranpranav72@gmail.com>
License: MIT
License-File: LICENSE
Requires-Python: >=3.10
Requires-Dist: mcp>=1.0
Requires-Dist: numpy>=1.24
Requires-Dist: pydantic-settings>=2.0
Requires-Dist: pydantic>=2.0
Requires-Dist: pyzmq>=25.0
Requires-Dist: scipy>=1.10
Requires-Dist: tenacity>=8.0
Provides-Extra: dev
Requires-Dist: pytest; extra == 'dev'
Requires-Dist: pytest-asyncio; extra == 'dev'
Requires-Dist: pytest-mock; extra == 'dev'
Description-Content-Type: text/markdown

# 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)

```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
