sdrpp-mcp
Control and query a running SDR++ instance through MCP for tuning, spectrum inspection, signal analysis, recording, decoding, and logbook management.
Check SDR++ status, launch it, and start/stop the SDR source.
Tune the Radio VFO with mode and optional bandwidth.
Capture spectrum snapshots or sweep frequency ranges, detecting signals and returning waterfall/spectrum images.
Look up band-plan allocations and nearby known channels for a frequency.
Analyze signals for bandwidth, modulation, deviation, symbol rate, burst timing, tones, stereo pilot/RDS, etc., with a zoomed waterfall.
Demodulate and record audio to WAV, or save raw IQ as cu8/cf32.
Decode digital transmissions with multimon-ng (pagers, APRS, EAS/SAME, DTMF, ZVEI, Morse) or rtl_433 ISM sensors.
Save, search, and delete logbook entries.
Export the logbook to SDR++ Frequency Manager bookmarks.
Provides a SQLite-backed logbook for identified signals, with tools to log, search, and delete entries and to export stored bookmarks.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@sdrpp-mcp sweep 400-500 MHz and identify any signals you find"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
sdrpp-mcp
An MCP server that drives a running
SDR++ instance to find, identify, decode,
record and log radio transmissions. A companion skill (skill/sdr-signal-id) packages the
identification workflow and reference material: signal signatures, decoder notes, hardware
quirks and US legal guardrails.
It works with any SDR++ source. It was developed and tested on an RTL-SDR (Nooelec SMArTee XTR, E4000 tuner, 2.4 MS/s).
Features
Live spectrum: snapshot the current passband with max-hold detection against an estimated noise floor, or step-sweep an arbitrary range (up to 200 retunes). Both return waterfall PNGs. Retuning lands exactly on the requested centre, sweeps report any range they failed to cover, and every tool that has to retune puts the Radio VFO back afterwards.
Signal analysis: extract a channel and measure:
SNR, 99% occupied bandwidth, duty cycle and bursts
envelope statistics, spectral skew and flatness
FM deviation and FSK levels, symbol rate (snapped to standard bauds), TDMA framing
CTCSS and audio tones, WFM stereo pilot and RDS
A heuristic classifier then makes a modulation guess: NFM, WFM, AM, SSB, CW/OOK, 2/4-FSK, wideband digital or carrier.
Band plan lookup: US allocations plus named channels (NOAA WX1–7, FRS/GMRS, MURS, APRS, ACARS, AIS, ISM, etc.).
Demodulation and recording: FM, WFM (75 µs de-emphasis), AM, USB, LSB and CW to WAV, or raw IQ (
cu8/cf32) for offline tools.Decoding:
multimon-ng: POCSAG/FLEX pagers, APRS/AFSK1200, EAS/SAME, DTMF, ZVEI, Morse, X10.
rtl_433: ISM-band sensors.
Channel watching and LoRa/MeshCore decoding: continuous capture of one channel, logging every burst; LoRa is recognised by dechirping, demodulated with gr-lora_sdr, and MeshCore packets are parsed (route, hop path, payload type, node adverts with name/type/position). Encrypted message bodies are not decrypted.
Logbook: SQLite log of identified signals, searchable, exportable as an SDR++ Frequency Manager bookmark list.
Related MCP server: GR-MCP
How it talks to SDR++
SDR++ module | Port | Used for |
Rigctl Server | localhost:4532 | tuning the Radio VFO, mode/bandwidth, start/stop, triggering the centre probe |
IQ Exporter (Baseband, TCP server, Float32) | localhost:4533 | live wideband IQ for spectrum, analysis and demodulation |
Recorder "Center Probe" (baseband) | – | rigctl only reports the VFO, so a ~0.1 s baseband recording's filename reveals the true centre frequency; the file is then deleted |
setup_sdrpp.py configures all three. Run it with SDR++ closed. It backs up each changed
file next to the original as *.json.bak-<time>.
Keep the Recorder and Center Probe menus in SDR++'s sidebar collapsed (the setup script
collapses them). Rigctl starts and stops the probe from a background thread, and if a recorder
menu is being drawn at that moment SDR++ can abort with an ImGui PushItemFlag/PopItemFlag
assertion.
Install
Requires Python ≥ 3.10 and SDR++ 1.2+ (nightly builds include the IQ Exporter).
git clone https://github.com/entitledosprey/sdrpp-mcp.git
cd sdrpp-mcp
python3 -m venv .venv && .venv/bin/pip install -e .
python3 setup_sdrpp.py # with SDR++ closed
sudo apt install multimon-ng rtl-433 # optional decodersOptional, for LoRa/MeshCore decoding in watch_channel (GNU Radio + gr-lora_sdr, used through
the system python3):
sudo apt install gnuradio-dev cmake pybind11-dev libspdlog-dev libfmt-dev libgmp-dev
git clone https://github.com/tapparelj/gr-lora_sdr.git && cd gr-lora_sdr
mkdir build && cd build && cmake .. -DCMAKE_BUILD_TYPE=Release && make -j"$(nproc)"
sudo make install && sudo ldconfigRegister the server with your MCP client as a stdio server, for example:
{
"mcpServers": {
"sdrpp": { "command": "/path/to/sdrpp-mcp/.venv/bin/sdrpp-mcp" }
}
}Skill
skill/sdr-signal-id/ is an Agent Skill (SKILL.md plus references/). To install it, copy or symlink the
directory into your client's skills folder:
ln -s "$PWD/skill/sdr-signal-id" ~/.config/<client>/skills/sdr-signal-idExample requests
Once the server (and optionally the skill) is registered with an MCP client, plain requests map onto the tools:
Request | What runs |
"What's on 2 m / 70 cm right now?" |
|
"What is this signal at 154.6?" |
|
"Decode pagers on 929–932" |
|
"Any weather sensors?" |
|
"Watch the MeshCore channel while I send an advert" |
|
"Log that" |
|
Tools
Tool | Purpose |
| SDR++ running? rigctl/IQ reachable, centre, rate, gain, clipping, installed decoders |
| start SDR++ (optionally with |
| set VFO frequency, mode, bandwidth |
| start/stop the source |
| detect signals in the current passband, returns a waterfall image |
| sweep |
| band plan allocation and known channels near a frequency |
| measure and classify one signal, with a zoomed waterfall |
| demodulate to WAV |
| save raw IQ ( |
| run multimon-ng or rtl_433 on a capture |
| listen to one channel for up to 15 min; detect, decode and parse LoRa/MeshCore packets |
| live state and recent calls of the sdrpp-p25 trunking module, if it's running |
| logbook |
| write the logbook to SDR++'s Frequency Manager (SDR++ must be closed) |
Frequencies accept Hz or strings such as 146.52M, 433.92 MHz or 1090m. Bare numbers below 10000
are treated as MHz.
P25 trunking
sdrpp-p25 is a companion SDR++ module that trunks P25
Phase 1/2 systems and plays the voice in SDR++. When it is running it owns the SDR's tuning:
p25_status and p25_calls read its decoder's API and event log, and every tool here that
would retune SDR++ refuses until the module is stopped.
Data locations
Everything lives under ~/.local/share/sdrpp-mcp/, or under SDRPP_MCP_DATA if that is set in
the server's environment (run setup_sdrpp.py with the same variable so SDR++'s probe recorder
writes there too):
images/: PNG spectra and waterfalls (named<time>_<freq>_<kind>); override withSDRPP_MCP_IMAGEScaptures/: WAV and IQ recordingscenter-probe/: temporary probe fileslogbook.db: the logbooksdrpp.log: SDR++'s console output when started withsdr_launch
Other tools
tools/sdrtrunk_to_sdrpp.py PLAYLIST.xml OUT_DIR: turns an SDRTrunk playlist's site frequencies into SDR++ Frequency Manager import files. SDR++ can't follow P25 trunking or decode its voice; for that use SDRTrunk, OP25 or DSD-FME (which can retune SDR++ through its rigctl server).
Frequency calibration
RTL-SDR crystals are typically off by somewhere between 0 and 50 ppm, and TCXO models by about 1 ppm. A good local reference
is the ATSC digital TV pilot: an unmodulated carrier at the channel's lower edge plus 309.441 kHz.
Measure the apparent offset of a few strong pilots (narrow FFT peak within ±15 kHz of the
expected frequency; ignore weak channels and stations that run offset pilots). Broadcast FM
carriers are too noisy for this. The correction is
ppm = (true − measured) / true × 10⁶. Enter it, rounded, under Source → PPM Correction in
SDR++.
Legal
The software is for receiving only. In the US, 47 USC 605 and ECPA restrict divulging or using the contents of private communications. Decoding cellular or cordless-phone content and decrypting anything are both off limits. Know your local rules.
History
See CHANGELOG.md.
License
MIT. See LICENSE.
Available Tools
15 toolsanalyze_signalA
Measure a signal's characteristics to help identify it: occupied bandwidth, carrier, envelope constancy, FM deviation, FSK levels, symbol rate, burst timing, TDMA periodicity, CTCSS / audio tones (for FM/AM), stereo pilot/RDS (WFM). Returns heuristic modulation guesses, band-plan context and a zoomed waterfall image. If bandwidth_hz is omitted it is estimated. If SDR++ has to retune to reach the signal, the original VFO is restored afterwards, unless tune_vfo=True, which leaves the Radio VFO on the signal so the user can listen.
Inputs: frequency (required), seconds, tune_vfo, bandwidth_hz.
band_sweepA
Sweep a frequency range wider than the SDR's bandwidth by retuning SDR++ in steps. Returns detected signals across the range plus a combined spectrum image. Note: this moves the user's SDR++ view; the original VFO frequency is restored afterwards.
Inputs: stop (required), start (required), top, dwell_s, +2 more.
decodeA
Capture and decode digital transmissions. decoder:
multimon-ng (FM-demodulated audio): pager (POCSAG+FLEX), pocsag, flex, aprs, eas/same, dtmf, zvei, morse
rtl_433: ism (433/315/345/915 MHz sensors, remotes, TPMS, meters) -- run on captured IQ Long captures block for
seconds. Privacy: pager and similar traffic can contain personal information; summarise rather than repeat sensitive content.
Inputs: decoder (required), frequency (required), seconds, bandwidth_hz.
delete_log_entryC
Delete a logbook entry by id.
Inputs: entry_id (required). Returns: result
export_bookmarksA
Write the logbook into SDR++'s Frequency Manager as a bookmark list (shown on the waterfall). SDR++ must be closed; a backup of the old bookmarks file is kept.
Inputs: list_name. Returns: result
identify_frequencyA
Band-plan lookup (US/FCC, ITU Region 2): which allocation a frequency falls in and which well-known channels/services are nearby. No radio access needed.
Inputs: frequency (required), window_khz.
log_signalC
Save an identified (or mystery) signal to the logbook. confidence: confirmed/likely/guess.
Inputs: label (required), frequency (required), mode, files, +4 more.
record_audioB
Demodulate a frequency from the live IQ stream and save a WAV (independent of SDR++'s own audio, so the user can keep listening elsewhere). mode: FM/NFM, WFM, AM, USB, LSB, CW.
Inputs: frequency (required), mode, seconds, audio_rate, +1 more.
record_iqB
Save channelised IQ around a frequency. fmt_: 'cu8' (rtl_433 / most tools, 8-bit unsigned) or 'cf32' (float32 complex). The output sample rate is chosen as exactly bandwidth_hz (250 kS/s default suits rtl_433). The filename carries freq and rate.
Inputs: frequency (required), fmt_, seconds, bandwidth_hz.
sdr_launchA
Start SDR++ if it isn't running (autostart=True also starts the SDR source).
Inputs: autostart. Returns: result
sdr_powerA
Start (on=True) or stop the SDR source in SDR++ (the play/stop button).
Inputs: on (required). Returns: result
sdr_statusA
Report SDR++ state: running, centre/VFO frequency, mode, source, gain, sample rate, whether rigctl and the IQ Exporter are reachable, and which decoders are installed.
Inputs: no named parameters.
sdr_tuneB
Tune SDR++'s Radio VFO so the user hears the frequency. mode: FM (=NFM), WFM, AM, DSB, USB, LSB, CW, RAW. bandwidth_hz optional (e.g. 12500 NFM, 200000 WFM, 10000 AM, 2700 SSB).
Inputs: frequency (required), mode, bandwidth_hz.
search_logC
Search the logbook by text and/or frequency range.
Inputs: stop, text, limit, start. Returns: result
spectrum_snapshotC
Capture the full SDR++ passband, detect signals (max-hold, so short bursts count) and
return a table plus a spectrum/waterfall image. Optionally retune to frequency first.
duty = fraction of time the signal was present (1.0 = continuous).
Inputs: top, seconds, fft_size, frequency, +1 more.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 15 tools
Each tool targets a clearly distinct aspect of SDR++ control or signal workflow: status, launch, tune, power, snapshot, sweep, identify, analyze, record audio/IQ, decode, and logbook CRUD. The descriptions explicitly delineate boundaries (e.g., passband snapshot vs. wideband sweep vs. single-signal analysis), so an agent can reliably select the right tool.
All names use snake_case, and the sdr_ prefix logically groups control tools. However, the verb/noun ordering is not uniform across the rest (e.g., identify_frequency, spectrum_snapshot, band_sweep, decode), which is a minor deviation from a predictable verb_noun pattern.
15 tools sit at the top of the ideal range and each covers a distinct, necessary capability for SDR++ remote control, signal analysis, recording, and logging. The set feels comprehensive without redundancy.
Core workflows—control, capture, analyze, record, decode, log—are well covered. Minor gaps include setting gain, sample rate, or input source, and no explicit log-entry update or list operation, though those can be worked around via search or manual SDR++ UI use.
Maintenance
Related MCP Connectors
MCP server for Speech-to-Text
QuLab MCP remote server (Streamable HTTP) for computational science and lab tools.
Remote MCP server for audio stem separation, denoise, reverb, and MIDI export.
MCP server for interacting with the Supabase platform
Related MCP Servers
- GPL 3.0
- AlicenseNot gradedqualityDmaintenanceAn MCP server that enables natural language-driven creation and management of GNU Radio flowgraphs with validated block connections and parameter configurations. It provides tools for searching the GNU Radio block library, detecting SDR hardware, and generating functional signal processing code.8MIT
- AlicenseNot gradedqualityDmaintenanceEnables natural language control of a live GNU Radio SDR flowgraph, allowing users to tune frequencies, adjust gain, capture IQ samples, analyze spectra, and detect signals through an MCP-compatible client.2MIT
- AlicenseNot gradedqualityCmaintenanceEnables MCP clients to control a local TradingView Desktop instance, providing tools to read chart state, change symbols and timeframes, and fetch OHLCV data.92 npm134MIT