fishball-sdr-mcp
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., "@fishball-sdr-mcpwhat FM stations can I actually receive here?"
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.
fishball-sdr-mcp
Ask an LLM what's on the air, and have it actually go and look.
An MCP server for the Fishball7020 / PlutoSky software-defined radio (Zynq-7020 + AD9361). It turns the board into 16 tools an assistant can use: tune it, sweep a band, measure a spectrum, capture IQ, engage the FPGA channel filter, and — if you deliberately switch it on — transmit.
> what FM stations can I actually receive here?
sdr_scan_band(start_hz=87500000, stop_hz=108000000)
| Frequency | Level | Above floor |
|------------|------------|-------------|
| 102.1 MHz | -31.5 dBFS | 73.9 dB |
| 100.7 MHz | -44.2 dBFS | 61.2 dB |
...The board's firmware and FPGA build system live in a companion repository, fishball7020-fpga-devkit.
Quick start
git clone https://github.com/matsvandamme/Fishball7020-mcp.git
cd Fishball7020-mcp
python3 -m venv .venv
.venv/bin/pip install -e .
claude mcp add fishball-sdr -- "$PWD/.venv/bin/fishball-sdr-mcp"-e . installs the package into the venv, which puts a fishball-sdr-mcp
launcher on the venv's bin/. Use that rather than python -m fishball_sdr_mcp: your MCP client starts the server from its own working
directory, not this one, so a bare -m invocation will not find the package.
Note the venv records absolute paths. If you move this directory, delete
.venv and recreate it.
Then ask for sdr_get_status. If the board answers, you're done.
Not sure where your board is? iio_attr -S scans and prints it. The default is
ip:192.168.2.1, the USB Ethernet gadget.
Related MCP server: SDR MCP Server
Requirements
Python 3.10+, and a Fishball7020 reachable over libiio. That's it.
The board is reached over libiio's network protocol using plain sockets, so
there is no pylibiio to install and no libiio version to match against your
firmware. numpy is used for the FFT if it happens to be importable, and a
pure-Python transform otherwise — the server runs with only mcp installed.
Tools
Look at things — sdr_get_status · sdr_spectrum · sdr_scan_band ·
sdr_capture_iq · sdr_board_health · sdr_list_devices ·
sdr_read_attribute
Change things — sdr_tune · sdr_configure_rx · sdr_set_fpga_filter
Transmit (off by default) — sdr_tx_tone · sdr_transmit_iq ·
sdr_transmit_waveform · sdr_tx_status · sdr_tx_chain_state ·
sdr_tx_disable
Every tool takes response_format: markdown to read, json to parse.
Three design decisions worth knowing
sdr_capture_iq writes to a file and returns the path. It never returns
samples inline — even a short capture is megabytes, and putting that through a
context window helps nobody. The format is interleaved little-endian int16,
which GNU Radio reads as a file source of type short and which
sdr_transmit_iq accepts straight back.
sdr_set_fpga_filter works by setting a sample rate. There is no "filter
on" attribute anywhere. Writing cf-ad9361-lpc's sampling_frequency to one
eighth of the converter rate is precisely what drives GP_CONTROL bit 0 and
flips the bypass mux in the bitstream. See
the channelizer write-up.
Receive levels are dBFS against a 12-bit converter, so full scale is ±2047. Transmit is not: the DAC takes the full 16-bit range. That asymmetry is measured, not assumed — see Notes from the hardware.
Configuration
Variable | Default | Meaning |
|
| Where the board is |
|
| Socket timeout, seconds |
|
| Where |
| unset | Set to |
| unset | Restrict TX, e.g. |
| unset | Leave the transmitter exactly as found |
.mcp.json.example is a drop-in config if you'd rather not use claude mcp add.
Transmitting
Off unless SDR_MCP_ALLOW_TX=1. This board tunes the FM broadcast band,
where transmitting without a licence is illegal, and an assistant that can call
a transmitter should not be able to do so by accident. Refusals name the exact
variable to set.
Turning transmit on
The flag is read from the server's environment at startup, not from the shell you type in, so exporting it in your terminal does nothing. Put it in the MCP registration:
claude mcp add fishball-sdr -e SDR_MCP_ALLOW_TX=1 -- \
/absolute/path/to/Fishball7020-mcp/.venv/bin/fishball-sdr-mcpor in .mcp.json:
{ "mcpServers": { "fishball-sdr": {
"command": "/absolute/path/to/Fishball7020-mcp/.venv/bin/fishball-sdr-mcp",
"env": { "SDR_MCP_ALLOW_TX": "1" } } } }Restart your MCP client afterwards. The environment is fixed when the
server process starts, so changing the registration mid-session has no effect
on the already-running server — the transmit tools will keep refusing until
the client is restarted. sdr_tx_status reports what the running server
actually believes:
| Transmitting allowed | no (set SDR_MCP_ALLOW_TX=1) |Leave the flag off unless you are transmitting into a dummy load or a shielded setup, or you hold a licence for the frequency you intend to use.
sdr_tx_disableandsdr_tx_statusare never gated. An off switch that can be unavailable is not an off switch.sdr_tx_disablealso runs on server shutdown, so a crashed client cannot leave the board transmitting a cyclic buffer.cyclic=truekeeps transmitting after the call returns. That's the point of it, and it still surprises people;sdr_tx_statusshows what's running.Every transmit call is logged to stderr with frequency, gain and sample count.
A TX→RX loopback without an attenuator will destroy your receiver. The receiver is the fragile end: the AD9361's RX input is rated to roughly +2.5 dBm. And this board is sold in a variant carrying a Mini-Circuits PGA-102+ power amplifier — 17.7 dB of gain at 50 MHz falling to 10.4 dB at 6 GHz, P1dB +17.5 dBm. Measured at 900 MHz through a 50 dB pad, such a board delivers about +18.5 dBm flat out, some 16 dB above what its own receive port survives. Fit at least 20 dB; 40–50 dB is comfortable. Connect with TX attenuation at maximum and raise power in steps.
Testing
.venv/bin/python evaluation/smoke_test.py # protocol only, no radio
.venv/bin/python evaluation/smoke_test.py --live # also call read-only toolsThis stands in for MCP Inspector, which needs Node 18 while Ubuntu 22.04
packages Node 12. It speaks JSON-RPC over stdio using only the standard library
and checks the handshake, tool schemas and annotations, that the transmit gate
refuses and names its variable, that diagnostics stay off stdout, and — with
--live — that every read-only tool returns real data. It never transmits and
never retunes your radio.
evaluation/questions.xml holds ten evaluation questions with verified answers,
per the mcp-builder
skill this server was built to.
Notes from the hardware
Things that cost real time to work out, recorded so they cost you none.
The IIOD channel mask is fixed-width. Exactly 8 hex characters per 32 scan
channels. 00000003 enables channels 0 and 1. Both 3 and
0000000000000003 fail with -22 EINVAL and no hint as to why.
WRITEBUF is acknowledged twice — once before the payload and once after.
Skip the first status and the stream desyncs, with your samples arriving as the
next "response line".
Transmit full scale is 16-bit; receive is 12-bit. Measured over a cable: digital amplitudes of 8191 and 32767 produced +12.7 dB and +24.8 dB relative to 2047 (expected +12.0 and +24.1) with no rise in distortion. Scaling transmit to ±2047, as the receive side does, emits 24 dB low.
TX gain order no longer matters — on current firmware. Starting a TX
buffer fires the kernel's preenable hook, which on devkit firmware built
before October 2026 unmuted by restoring a cached attenuation, overwriting
whatever you wrote beforehand: asking for -10 dB put -60 dB on the wire.
patches/0005
fixes that — the cache is now restored only if nothing has been set since the
mute, so setting a gain before the stream works, and starting a stream having
set nothing still brings back your last gain. The transmit tools here set gain
after the stream regardless, which is correct either way.
The TX mute costs no output power. Swept over a 50 dB attenuated loopback: commanded and applied attenuation matched to 0.01 dB at every point including 0 dB, and received level tracked the commanded gain across a 40 dB range within 1.9 dB. Full output is fully available.
An empty serial makes other tools refuse the board. This server connects by
URI and is unaffected, but SDRangel identifies Plutos by serial number, and
devkit firmware built before September 2026 reported an empty one — the board's
Winbond W25Q128 flash never emits the SPI-NOR-UniqueID line the boot script
greps for. SDRangel then lists PlutoSDR0 TBD and fails with open serial TBD failed. Current devkit firmware mints a persistent serial on first boot without
changing the gadget MAC or interface name; sdr_get_status reports it. If you
see a TBD, reflash from the current
devkit.
Two tools cannot hold the board at once. When SDRangel (or anything else)
opens the Pluto over USB, the firmware reconfigures the composite device and
the USB Ethernet gadget disappears — so ip:192.168.2.1 stops answering and
every tool here fails with a connection error until that application closes.
Not a fault; just mutually exclusive.
Something on the board may be changing your gain. /mnt/jffs2 is
persistent and /mnt/jffs2/autorun.sh runs at every boot, so a helper script
there survives reflashing and appears nowhere in the firmware source. A common
one polls the TX buffer and applies a fixed gain a second or two after any
stream starts — a workaround for the clobbering described above, and no longer
needed. It overrides this server's gain silently, and on a board with the
PGA-102+ power amplifier the 10 dB such scripts typically use is about +13 dBm
at the SMA against a +2.5 dBm receive port. The devkit's
tools/selftest/sdr_selftest.py --ssh lists what is there.
The transmitter idles hot on stock firmware. The AD9361 comes up in ENSM
fdd with the synthesiser running and 10 dB of attenuation, so the TX port
leaks LO with nothing in the DAC. This server quiets it at startup unless
transmitting is enabled; the companion devkit
fixes it properly in firmware.
License
Same terms as the companion devkit: GPL-2.0.
Available Tools
16 toolssdr_board_healthBoard healthARead-onlyIdempotent
Read the Zynq XADC: internal supply rails and die temperature. Useful for checking the board is healthy, or whether it is running hot.
| Name | Required | Description | Default |
|---|---|---|---|
| response_format | No | markdown for reading, json for structured output | markdown |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the safety profile is covered. The description adds useful context about what is read (supply rails and die temperature) but does not go further into behavior such as response shape, timing, or environmental assumptions. With the annotation coverage, this is adequate but not rich.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences with no filler: the first states the action and object, the second states practical use cases. Information is front-loaded and every word earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only, zero-required-parameter tool with an output schema and strong annotations, the description is sufficient. It explains what is read and why an agent would call it; nothing essential is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% for the single optional parameter, and the schema already provides enum values, a default, and a description for response_format. The tool description adds no parameter-level detail, so the schema carries the burden; baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb-resource pair: 'Read the Zynq XADC: internal supply rails and die temperature.' This clearly distinguishes the tool from siblings like sdr_tune or sdr_get_status, and the title 'Board health' is reinforced rather than merely restated.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit use cases: 'checking the board is healthy, or whether it is running hot.' This tells an agent when the tool is appropriate, though it does not explicitly name alternatives or state when not to use it—a minor gap given the many sibling tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
sdr_capture_iqCapture IQ to a fileA
Capture raw IQ samples and WRITE THEM TO A FILE, returning the path plus level statistics. Samples are never returned inline - even a short capture is megabytes. The file is interleaved little-endian int16 (I,Q,I,Q,...), which GNU Radio reads as a file source of type short, and which sdr_transmit_iq accepts directly.
| Name | Required | Description | Default |
|---|---|---|---|
| samples | No | Samples per channel | |
| filename | No | Name within the capture directory | |
| channel_pair | No | 0 or 1 | |
| response_format | No | markdown for reading, json for structured output | markdown |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations, the description discloses key behavior: samples are written to a file rather than returned inline, the response includes path and level statistics, files can be large, and the exact binary layout is specified. This gives an agent an accurate model of what will happen when the tool runs.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is tight and well-ordered: the core action is front-loaded, then the critical 'never inline' caveat, then the file format and compatibility notes. Every sentence contributes useful information without repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 4-parameter tool with an output schema and annotations, the description covers what the tool does, what it returns, why inline returns are infeasible, and how the output can be consumed. No critical operational detail appears missing for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so all four parameters are already documented in the schema. The description adds no additional parameter-level meaning, which is fine because the schema carries the burden; baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific verb and resource: capture raw IQ samples and write them to a file, returning the path plus level statistics. It also differentiates from sibling tools by contrasting with sdr_transmit_iq, which consumes the produced file.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear context: this tool is for file-based IQ capture, not inline sample return, and the file can be fed to GNU Radio or sdr_transmit_iq. It does not explicitly enumerate when not to use it, but the 'never returned inline' statement and file-format notes provide solid usage framing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
sdr_configure_rxConfigure the receiverAIdempotent
Set any of: converter sample rate (Hz), RF analog bandwidth (Hz), gain control mode, and manual gain (dB). Omitted settings are left alone. Values are checked against the radio's own '*_available' attributes, so an illegal request is rejected with the legal options rather than silently ignored.
Manual gain only applies when gain_mode is 'manual'.
| Name | Required | Description | Default |
|---|---|---|---|
| gain_db | No | Manual gain in dB | |
| gain_mode | No | e.g. manual, slow_attack, fast_attack, hybrid | |
| bandwidth_hz | No | Analog RF bandwidth in Hz | |
| sample_rate_hz | No | Converter sample rate in Hz | |
| response_format | No | markdown for reading, json for structured output | markdown |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate it is mutating (readOnlyHint=false) and idempotent. The description adds valuable behavior: validation against '*_available' attributes, rejection with legal options, and the conditional that manual gain only applies in manual mode. These go beyond the annotations and provide essential operational context.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two concise sentences, front-loaded with the primary actions and followed by crucial behavioral details. No wasted words, and each sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the output schema exists and annotations cover idempotency and destructiveness, the description is largely complete. It explains the validation behavior and conditional constraints. It does not elaborate on the response format parameter, but that is self-explanatory from the schema. Minor gaps exist around expected side effects, but they are not critical.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3. The description enriches this by explaining the overarching behavior (omitted settings left alone) and the relationship between gain_mode and gain_db. It also frames the parameters in terms of the radio's available attributes, which the schema alone does not convey.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a clear verb ('Set') and specific resources: sample rate, bandwidth, gain mode, and manual gain. It explicitly distinguishes this as a configuration tool for the receiver, which is distinct from sibling tools like tuning, capture, or status. The purpose is unambiguous and specific.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It provides usage context by stating that omitted settings are left alone, implying partial configuration is allowed, and clarifies the conditional application of manual gain. However, it does not explicitly compare to alternatives or state when not to use it. Since the tool's purpose is inherently clear among siblings, this is adequate but not exhaustive.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
sdr_get_statusRadio statusARead-onlyIdempotent
Report how the SDR is currently configured: RX local oscillator, converter and delivered sample rates, whether the FPGA channel filter is engaged, RF bandwidth, gain, RSSI, die temperature and firmware version. Start here.
| Name | Required | Description | Default |
|---|---|---|---|
| response_format | No | markdown for reading, json for structured output | markdown |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations (readOnlyHint, idempotentHint, destructiveHint false) already establish a safe, non-mutating profile. The description adds behavioral context by explaining that this is a reporting/entry-point operation with no configuration changes, and lists the kind of data it returns.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single dense sentence with no filler, front-loads the core behavior with 'Report', and efficiently enumerates the report contents. The closing 'Start here.' is short and directive without adding redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With a single optional parameter fully documented in the schema, a rich output schema, and comprehensive annotations, the description covers what an agent needs: what the tool reports, what fields are included, and how to begin. No critical guidance is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema fully describes the only parameter (response_format), including its enum values, default, and a clear explanation of when to use each format. The description itself adds no parameter-level detail, so the baseline of 3 applies since schema coverage is 100%.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description begins with a specific action verb ('Report') and a clear resource ('how the SDR is currently configured'), then enumerates the exact fields covered. It distinguishes itself from sibling status tools, such as sdr_tx_chain_state or sdr_board_health, by covering overall SDR configuration rather than a single subsystem.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The phrase 'Start here' explicitly tells an agent to invoke this tool first when investigating SDR state, providing practical routing guidance. It does not name specific alternative tools or exclusion conditions, so it falls just short of full explicit when/when-not guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
sdr_list_devicesList IIO devicesARead-onlyIdempotent
List every IIO device, channel and attribute the board exposes. Use this to discover exact names before calling sdr_read_attribute, or to check what a particular firmware build provides.
| Name | Required | Description | Default |
|---|---|---|---|
| response_format | No | markdown for reading, json for structured output | markdown |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, openWorld, and non-destructive behavior, so the description carries a lower burden. It adds helpful context that the listing is drawn from the current board/firmware exposure, but it does not disclose additional behaviors such as output size, pagination, or error cases beyond what the schema and annotations already convey.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two tight sentences: the first delivers the exact scope of the tool and the second immediately gives actionable use cases. No words are wasted and the purpose is front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only discovery tool with no required parameters, a fully documented parameter schema, and an output schema, the description sufficiently covers what the tool does and when to reach for it. An agent is not left guessing about prerequisites, behavior, or response structure.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The single parameter response_format is fully documented in the schema with enum values, default, and descriptions. The description adds no parameter-specific meaning, so the schema coverage baseline of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('List') and an explicit resource scope ('every IIO device, channel and attribute the board exposes'), going well beyond the title. It also references the collaborating sibling sdr_read_attribute, which helps distinguish this discovery tool from the other radio-control and status tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly gives two use cases: discover exact names before calling sdr_read_attribute, or check what a firmware build provides. It does not enumerate exclusions or specify when not to use it relative to other siblings, so it falls short of a full when-to-use and when-not-to-use guide.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
sdr_read_attributeRead an IIO attributeARead-onlyIdempotent
Read any single IIO attribute by name - an escape hatch for anything the other tools do not cover. Use sdr_list_devices to find valid names. Reading an attribute called '_available' shows the legal values for ''.
| Name | Required | Description | Default |
|---|---|---|---|
| device | Yes | Device name, e.g. 'ad9361-phy' | |
| output | No | True for an output channel | |
| channel | No | Channel id, e.g. 'voltage0'. Omit for a device-level attribute. | |
| attribute | Yes | Attribute name, e.g. 'rf_bandwidth' | |
| response_format | No | markdown for reading, json for structured output | markdown |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the safety profile is covered. The description adds useful behavioral context beyond the schema by explaining the '_available' attribute convention for discovering legal values, which is genuinely helpful for using the tool correctly.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences with no filler: purpose, tool-routing guidance, and an important attribute discovery behavior. The most important information is front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only escape-hatch tool with a 100%-covered schema and an output schema present, the description provides all needed decision-making and invocation context. openWorldHint supports its role as a general-purpose fallback, and the annotations cover safety.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3. The description adds extra semantic value by explaining how to find valid attribute names via sdr_list_devices and by describing how the '_available' suffix works, which directly enriches the 'attribute' parameter.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific action ('Read any single IIO attribute by name') and clearly identifies the resource. Calling it 'an escape hatch for anything the other tools do not cover' differentiates it from a large sibling set without listing each sibling.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives explicit guidance on when to use the tool ('escape hatch... anything the other tools do not cover') and points to sdr_list_devices for discovering valid attribute names. It does not name specific alternatives or state a concrete 'when not to use' condition, so it falls just short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
sdr_scan_bandScan a frequency rangeA
Step the LO across a range and report the signals found, strongest first. Use it to discover what is receivable - for example which FM broadcast stations are audible at this location.
The radio is left tuned to the last step, so re-tune afterwards if you care where it sits. A wide scan at a low sample rate takes many steps and is slow; raise the sample rate to cover ground faster at coarser resolution.
| Name | Required | Description | Default |
|---|---|---|---|
| samples | No | ||
| step_hz | No | Defaults to 80% of the sample rate | |
| stop_hz | Yes | ||
| start_hz | Yes | ||
| max_results | No | ||
| threshold_db | No | Report signals at least this far above the noise floor | |
| response_format | No | markdown for reading, json for structured output | markdown |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations, the description reveals an important state-changing side effect: the radio is left tuned to the last step and may need re-tuning. It also adds a performance tradeoff about sample rate versus scan speed and resolution, which is useful behavioral context.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences with no filler; the core operation and use case come first, followed by the side-effect caveat and a performance tradeoff. Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the output schema and annotations, the description covers the key operational facts: what it reports, how to use it, the re-tuning side effect, and the speed/resolution tradeoff. It does not mention interaction with sibling tools like sdr_tune or sdr_spectrum, but the description is otherwise sufficient for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The description contributes useful meaning around sample rate and scan speed, and 'across a range' maps to start_hz/stop_hz. However, with only 43% schema coverage, it does not compensate for all parameters; max_results and threshold_db selection are left to the schema titles and property descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific operation: step the LO across a range and report signals found, strongest first. The use case 'discover what is receivable' with an FM example makes the tool's intent unambiguous and distinguishes it from tuning, capture, or status siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It clearly explains when to use the tool: to discover what signals are receivable in a range. It does not explicitly name alternatives or state when not to use it, so it falls just short of full guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
sdr_set_fpga_filterEngage or bypass the FPGA channel filterAIdempotent
Switch the FPGA's decimate-by-8 channel filter into or out of the receive path.
On firmware built from this devkit's channelizer patch, engaging it selects a sharp FIR that removes everything outside the wanted channel, and drops the delivered rate to one eighth of the converter rate. It works by writing the cf-ad9361-lpc sample rate, which is what drives GP_CONTROL bit 0 and the bypass mux in the bitstream - there is no separate on/off attribute.
Bypassing is the way to A/B whether the filter is really doing anything: a neighbouring signal that reappears when bypassed is the proof.
| Name | Required | Description | Default |
|---|---|---|---|
| engaged | Yes | True to engage (÷8), False to bypass | |
| response_format | No | markdown for reading, json for structured output | markdown |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate the tool is an idempotent, non-destructive write operation (readOnlyHint=false, destructiveHint=false). The description adds useful context about the underlying mechanism (writing the cf-ad9361-lpc sample rate) and the lack of a separate on/off attribute. It doesn't contradict annotations and provides value beyond them.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with a clear opening sentence, technical details, and a practical usage tip. All paragraphs are informative and no part is redundant.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given that the tool has a small parameter set and an output schema, the description provides sufficient context for an agent to call it correctly. It explains the purpose, the effect, and how to verify the filter's action. The only minor gap is that it could mention the exact impact on sample rate and data rate more explicitly, but the existing details are adequate.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the schema already documents both parameters. However, the description adds depth by explaining the effect of the 'engaged' parameter (÷8, sharp FIR) and the response_format parameter's purpose (markdown vs json). This goes beyond the schema's basic descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's function: engaging or bypassing the FPGA channel filter, with specific details on the decimate-by-8 effect and the FIR filter behavior. It distinguishes itself from potential siblings by focusing on this specific filter control.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explains when to use this tool versus alternatives, particularly in the context of A/B testing the filter's effect. It mentions that bypassing is the way to verify the filter is working, providing clear context for when each mode is appropriate.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
sdr_spectrumMeasure the spectrumA
Capture IQ and return the strongest signals as a table of frequency and level, with the noise floor and capture statistics, optionally with a compact ASCII plot. This is the tool for 'what is on this frequency right now'.
Levels are dBFS referred to the 12-bit converter's full scale. Only the sample rate's worth of spectrum around the current LO is visible - use sdr_scan_band to cover more.
| Name | Required | Description | Default |
|---|---|---|---|
| plot | No | Include an ASCII plot | |
| peaks | No | How many peaks | |
| samples | No | Samples for the transform | |
| channel_pair | No | ||
| response_format | No | markdown for reading, json for structured output | markdown |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations include openWorldHint=true, indicating the tool may interact with external systems, and no destructive or read-only hints. The description adds important behavior beyond annotations: it mentions the dBFS reference to the 12-bit converter, implying a specific hardware context, and the frequency visibility limitation around the current LO. It does not contradict the annotations, but could disclose more about side effects.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences long, with the first sentence front-loading the core functionality and output. The second sentence delivers critical usage guidance. Every word serves a purpose, and there is no fluff or repetition of schema details.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool has an output schema (returning a table of signals and statistics), the description needs not explain the return structure in detail. It provides essential context: the dBFS reference, the frequency coverage limitation, and the alternative tool. With another tool (sdr_capture_iq) that likely captures raw IQ, the description clarifies that this tool analyzes and summarizes, which is a complete picture for an agent.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 80%, so many parameters have descriptions, but the description adds valuable context: it explains the dBFS reference and the frequency visibility scope, which helps interpret the samples parameter (transform size). The parameters 'response_format' and 'plot' are well described in the schema, and the description's mention of 'optionally with a compact ASCII plot' reinforces 'plot'. Overall, it adds useful meaning beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb 'Capture IQ' and the specific resource 'the spectrum', and explains that the tool returns a table of strongest signals, noise floor, and statistics. It also differentiates itself from the sibling tool sdr_scan_band by explicitly stating its coverage limitation, which is critical for an agent to choose the right tool.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly says 'This is the tool for "what is on this frequency right now"', giving a clear use case. It also provides an exclusion: 'Only the sample rate's worth of spectrum around the current LO is visible - use sdr_scan_band to cover more', directly pointing to the alternative tool when broader coverage is needed.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
sdr_transmit_iqTransmit an IQ fileADestructive
Transmit an arbitrary IQ waveform read from a file on this machine.
Formats: 'int16' interleaved little-endian I,Q (what sdr_capture_iq writes), 'complex64' (what a GNU Radio file sink writes), 'wav' (2 channels as I and Q), or 'auto' to infer from the extension.
With cyclic=true the buffer REPEATS FOREVER and transmission continues after this call returns - use sdr_tx_disable to stop. With cyclic=false the buffer plays once. Requires SDR_MCP_ALLOW_TX=1. Only transmit into a dummy load or on frequencies you are licensed to use.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | Path to the IQ file | |
| lo_hz | Yes | TX local oscillator in Hz | |
| scale | No | Peak amplitude, 0 to 1 | |
| cyclic | No | Repeat forever (true) or play once (false) | |
| tx_gain_db | No | TX attenuation in dB; 0 is full output. Must be set, because the firmware idles at maximum attenuation. | |
| file_format | No | Input sample format | auto |
| max_samples | No | ||
| sample_rate_hz | No | TX sample rate; leave unset to keep the current one | |
| response_format | No | markdown for reading, json for structured output | markdown |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description substantially expands on the annotations: it discloses that cyclic=true repeats forever and transmission outlives the call, names the stop tool, and adds the environment variable requirement plus the dummy-load/licensed-frequency safety constraint. With destructiveHint and openWorldHint already present, this is strong added behavioral context.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is dense but well-structured: purpose first, then formats, then cyclic behavior, then safety and prerequisites. Every sentence earns its place, and there is no filler or restatement of schema defaults.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 9-parameter transmit tool with an output schema and annotations, the description covers the critical non-obvious details: file formats, repeat-forever semantics, how to stop, the required allow flag, and legal operation. Nothing essential is missing for an agent to select and safely invoke the tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 89%, so the baseline is 3, but the description adds genuine meaning for file_format by explaining exactly what int16, complex64, and wav represent and where they come from. It also clarifies the cyclic parameter's real-world behavior. The only gap is that max_samples is not semantically expanded, but the schema already carries most of the load.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states a specific verb and resource: 'Transmit an arbitrary IQ waveform read from a file on this machine.' The file-based focus distinguishes it from tone/waveform siblings in practice, but it does not explicitly name or contrast those alternatives, so it stops short of a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives clear usage context: use this tool to transmit an IQ file, with format inference options, cyclic repeat behavior, the stop mechanism via sdr_tx_disable, and the SDR_MCP_ALLOW_TX=1 requirement. It does not explicitly spell out when to prefer sdr_tx_tone or sdr_transmit_waveform, so it lacks the full alternatives guidance needed for a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
sdr_transmit_waveformTransmit a generated waveformADestructive
Synthesise and transmit a test signal without needing an IQ file: a single tone, two tones (for intermodulation testing), a linear chirp, or band-limited noise.
Always cyclic, so it repeats until sdr_tx_disable is called. Requires SDR_MCP_ALLOW_TX=1. Only transmit into a dummy load or on frequencies you are licensed to use.
| Name | Required | Description | Default |
|---|---|---|---|
| lo_hz | Yes | ||
| scale | No | ||
| shape | No | Waveform to generate | tone |
| samples | No | ||
| tx_gain_db | No | TX attenuation in dB; 0 is full output. Must be set, because the firmware idles at maximum attenuation. | |
| bandwidth_hz | No | Tone offset, tone spacing, chirp width, or noise width | |
| response_format | No | markdown for reading, json for structured output | markdown |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark destructiveHint=true and readOnlyHint=false, but the description adds substantial behavioral context: the transmission is always cyclic, it repeats until sdr_tx_disable is called, it needs SDR_MCP_ALLOW_TX=1, and it should only be used into a dummy load or licensed frequencies. This goes well beyond annotation signals and does not contradict them.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three terse, front-loaded sentences: core purpose first, then lifecycle and safety. Every sentence earns its place and there is no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the annotations and output schema, the description covers the important lifecycle behavior, environment requirement, and safety constraint. It lacks only an explicit note about when to prefer sibling tools like sdr_tx_tone or sdr_transmit_iq, which prevents a perfect score.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The description adds useful meaning to the shape parameter by explaining the waveform types and their test purpose, and the schema already covers bandwidth_hz and tx_gain_db in detail. However, it provides no additional guidance for lo_hz, scale, or samples beyond their titles and defaults, so the coverage is adequate but not exemplary.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The first sentence states a specific operation ('Synthesise and transmit a test signal') and resource ('without needing an IQ file'), and lists the four waveform shapes. This distinguishes it from sdr_transmit_iq, but it does not explicitly separate it from the sibling sdr_tx_tone when the user only needs a single tone.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It provides clear conditions for use: generated test waveforms, no IQ file, always cyclic until sdr_tx_disable is called, and requires SDR_MCP_ALLOW_TX=1. It does not explicitly route the agent to sdr_tx_tone for simple tones or sdr_transmit_iq for IQ-file playback, so it narrowly misses a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
sdr_tuneSet the RX frequencyAIdempotent
Set the receive local oscillator, in Hz. Valid range 70 MHz to 6 GHz.
Note this tunes the LO, which becomes the CENTRE of the captured band. To keep the AD9361's LO leakage and DC offset out of a signal, tune deliberately off it and look at the resulting offset instead.
| Name | Required | Description | Default |
|---|---|---|---|
| frequency_hz | Yes | RX LO frequency in Hz | |
| response_format | No | markdown for reading, json for structured output | markdown |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations, the description adds meaningful behavioral context: the LO becomes the center of the captured band, and there is an AD9361-specific quirk about DC offset and LO leakage. This helps an agent anticipate the operational effect of the tuning action. It does not contradict the idempotent or non-destructive hints.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and front-loaded with the core action and units, followed by the valid range and a useful caveat. Every sentence earns its place, and there is no redundant filler or repetition of the title.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple setter with one required parameter, an output schema, and clear annotations, the description is complete: it states the action, range, and an important operational caveat. Nothing essential is missing for an agent to invoke this tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the parameter meaning is already documented. The description adds value by clarifying what frequency_hz actually controls—the local oscillator, which becomes the center of the captured band—rather than just restating the schema. This extra semantic context helps the agent select an appropriate value.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'Set the receive local oscillator, in Hz,' and gives the valid range. It clearly identifies this as the tuning operation and distinguishes it from related tools by explaining the LO becomes the center of the captured band.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear context about when this tool is relevant and includes practical advice to tune deliberately off-signal to avoid LO leakage and DC offset. However, it does not explicitly name alternatives or state when a different tool such as sdr_configure_rx should be used instead.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
sdr_tx_chain_stateIs the transmitter live?ARead-onlyIdempotent
Report whether the AD9361's transmit chain is actually energised, and why. The board boots into ENSM 'fdd' with the TX synthesiser running and only 10 dB of attenuation, so TX is live from power-on even with no data in the DAC DMA - it emits LO leakage rather than silence. This tool shows the ENSM mode, TX LO powerdown state and both attenuator settings, and says plainly whether anything is being emitted. Use sdr_tx_disable to silence it.
| Name | Required | Description | Default |
|---|---|---|---|
| response_format | No | markdown for reading, json for structured output | markdown |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
This description goes above beyond the annotations by revealing that the board boots in ENSM 'fdd' state with TX synthesiser running and only 10 dB attenuation, so TX is live from power-on even without DAC data, emitting LO leakage. This nuanced behavioral context—including what the tool shows (ENSM mode, TX LO powerdown, attenuators) and the statement that it says plainly whether anything is being emitted—is exactly the context that helps an agent interpret the result correctly.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is 3 sentences, well-structured: it immediately states the purpose, then explains the default behavior, then what the tool shows, and finally mentions the sibling tool. Every sentence carries meaningful information, though the second sentence could be slightly trimmed without losing critical context.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the low complexity (a read-only status query) and an output schema for return formatting, the description is complete enough: it tells what data will be shown and why it matters, and it links to the destructive sibling for action. The only minor gap is not a mentioning the relationship with `sdr_tx_status`, which could lead to some confusion among sibling tools.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The only parameter has 100% schema coverage with its description already stating that 'markdown' is for reading and 'json' for structured output. The tool description doesn't add any additional parameter semantics, so a baseline of 3 is appropriate because the schema already does the required work.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb 'Report' and the resource 'AD9361 transmit chain', explaining exactly what the tool does and what it exposes. It also includes the important scope that it tells whether anything is actually being emitted, making the purpose concrete. However, it does not explicitly differentiate from the similar sibling tool 'sdr_tx_tool_status', leaving the agent to infer which one to prefer.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides context about the always-on boot behavior and explicitly points to 'sdr_tx_disable' when action is required, giving some direction on when to use this tool as a diagnostic step. It does not explicitly state when to use this tool over the sibling 'sdr_tx_status' or give clear why/why-not conditions, so the general usage guidance is more implied than explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
sdr_tx_disableStop transmittingAIdempotent
Stop all transmission immediately: silence every DDS tone, close any sample buffer, and power down the TX local oscillator. Never gated - it works even when transmitting is otherwise disabled, because an off switch that can be unavailable is not an off switch. Safe to call at any time.
| Name | Required | Description | Default |
|---|---|---|---|
| response_format | No | markdown for reading, json for structured output | markdown |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already provide idempotentHint=true and destructiveHint=false; the description adds meaningful behavioral detail: immediate shutdown, silencing every DDS tone, closing sample buffers, and powering down the TX local oscillator. It also explains why the never-gated behavior exists, which aligns with and enriches the idempotency annotation without contradicting it.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is three short sentences, front-loading the immediate action and then justifying the unconditional availability. The 'off switch' aphorism earns its place by explaining the design rationale in a memorable way, with no wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple one-parameter control tool with an output schema and relevant annotations, the description covers purpose, exact side effects, usage conditions, and safety. An agent has everything it needs to call this tool correctly and know what will happen.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
There is one optional parameter, response_format, and the schema describes it fully with an enum and default value. The description adds nothing about parameters, but that is acceptable because schema description coverage is 100%, so the baseline of 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource ('Stop all transmission immediately') and enumerates the exact effect: silence DDS tones, close sample buffers, and power down the TX local oscillator. The 'all' qualifier and concrete actions distinguish it from status or tone-generation siblings like sdr_tx_status and sdr_tx_tone.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear contextual guidance by stating it is 'Never gated' and 'Safe to call at any time,' meaning no precondition blocks its use. It does not explicitly name an alternative tool or a when-not-to-use condition, but the unconditional availability is strong enough guidance for this control action.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
sdr_tx_statusTransmit statusARead-onlyIdempotent
Report what the transmitter is doing: whether transmitting is enabled at all, the TX LO and its powerdown state, sample rate, bandwidth, every DDS tone generator, and whether this server started a cyclic buffer that is still running. Always available, even when transmitting is disabled.
| Name | Required | Description | Default |
|---|---|---|---|
| response_format | No | markdown for reading, json for structured output | markdown |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already carry the safety profile (readOnly, idempotent, non-destructive), and the description adds genuinely useful context: the tool remains usable while transmitting disabled and reports whether a cyclic buffer is still running. These details go beyond annotation-provided facts.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact: one sentence lists all the reported state items without filler, and a second sentence adds an important behavioral note. It is well front-loaded and occupies no unnecessary words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only tool with no required parameters, complete schema coverage, and an output schema, the description is complete enough. The only missing piece is a comparison with overlapping sibling tools, which is covered in the usage dimension.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema provides complete descriptions of the single optional parameter, so the description adds nothing about parameters. With 100% schema coverage, the baseline of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly identifies the action and resource ('Report what the transmitter is doing') and lists specific state items, so an agent knows exactly what the tool returns. However, it does not explicitly differentiate itself from sibling tools like sdr_tx_chain_state, which may also report transmit-related state.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No explicit when-to-use guidance is provided, and no alternative tools are mentioned. The note about being 'always available' is a behavioral trait, not a routing instruction, so the agent gets no direct help choosing between this tool and similar status or state tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
sdr_tx_toneTransmit a toneADestructiveIdempotent
Transmit a continuous single-tone carrier using the FPGA's DDS generators, at an offset from the TX local oscillator.
TRANSMITS UNTIL STOPPED. Call sdr_tx_disable to stop it. Requires SDR_MCP_ALLOW_TX=1. Only transmit into a dummy load or on frequencies you are licensed to use.
| Name | Required | Description | Default |
|---|---|---|---|
| lo_hz | Yes | TX local oscillator in Hz | |
| scale | No | Amplitude, 0 to 1 | |
| tx_gain_db | No | TX attenuation in dB; 0 is full output. Must be set, because the firmware idles at maximum attenuation. | |
| tone_offset_hz | No | Tone offset from the LO, in Hz | |
| response_format | No | markdown for reading, json for structured output | markdown |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true and readOnlyHint=false, so the mutation risk is known. The description adds valuable behavioral context beyond annotations: the transmission continues until explicitly stopped, requires an environment variable, and has legal/safety constraints. It doesn't describe the return format, but the output schema exists and the safety-critical behavior is well disclosed.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and front-loaded: the core action is in the first sentence, followed by the critical stop condition, the required environment variable, and the safety warning. Every sentence earns its place with no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a destructive, continuous-transmission tool, the description covers the essential operational context: how to stop it, the required permission flag, and the safety constraint. The output schema exists so return values don't need explanation. It could mention what happens on error or whether the tool returns immediately, but the critical context is present.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents all 5 parameters. The description adds context for the overall operation (offset from LO) but doesn't add per-parameter meaning beyond what the schema provides. Baseline 3 is appropriate since the schema does the heavy lifting.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Transmit'), a specific resource ('continuous single-tone carrier using the FPGA's DDS generators'), and a distinguishing detail ('at an offset from the TX local oscillator'). It clearly differentiates from siblings like sdr_transmit_iq and sdr_transmit_waveform by specifying the single-tone DDS nature.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly says when to use it (transmit a continuous single tone) and gives critical usage constraints: it transmits until stopped, requires SDR_MCP_ALLOW_TX=1, and must only be used into a dummy load or licensed frequencies. It also names the sibling sdr_tx_disable as the stop mechanism, providing clear routing to the complementary tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
16 tool updates
v0.1.0- First observed
sdr_board_health - First observed
sdr_capture_iq - First observed
sdr_configure_rx - First observed
sdr_get_status - First observed
sdr_list_devices - First observed
sdr_read_attribute - First observed
sdr_scan_band - First observed
sdr_set_fpga_filter - First observed
sdr_spectrum - First observed
sdr_transmit_iq - First observed
sdr_transmit_waveform - First observed
sdr_tune - First observed
sdr_tx_chain_state - First observed
sdr_tx_disable - First observed
sdr_tx_status - First observed
sdr_tx_tone
TDQS
Scored across 16 tools
Most tools have clearly distinct purposes, but sdr_tx_chain_state and sdr_tx_status overlap significantly by both reporting TX LO powerdown state and transmit-chain activity. Similarly, sdr_get_status and sdr_board_health both expose die temperature, which could cause selection confusion.
The names mostly follow a consistent sdr_<verb>_<noun> pattern, like sdr_capture_iq, sdr_configure_rx, and sdr_tx_disable. Minor deviations exist: sdr_spectrum and sdr_board_health are noun-style, and sdr_tx_tone vs sdr_transmit_iq mix 'tx' and 'transmit'.
Sixteen tools is slightly above the ideal range, but the count is reasonable for a full SDR server covering RX, TX, capture, scanning, and health diagnostics. Each tool addresses a real operational need rather than being redundant filler.
The RX path is well covered with tuning, configuration, filtering, capture, spectrum analysis, and scanning. However, the TX path lacks a dedicated tool to set the transmit LO frequency, which is a notable gap since TX tones and IQ transmission only operate relative to that LO.
Maintenance
Related MCP Connectors
Real-time planetary signal engine and Model Context Protocol (MCP) server for autonomous AI agents.
- mytesla.ioOAuthio.mytesla
Control your Tesla from your AI assistant - climate, charging, access, and security.
Give your AI a real phone: place calls, send SMS, fetch recordings and transcripts. Local or hosted.
Turns a phone into a camera+Bluetooth remote so AI assistants can see and control any PC.
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceEnables control of Software Defined Radios and decoding of radio protocols through an AI-friendly Model Context Protocol interface, supporting RTL-SDR and HackRF hardware for signal analysis and protocol decoding.23MIT
- AlicenseNot gradedqualityCmaintenanceConversational AI control for Software Defined Radio via the Model Context Protocol.7MIT
- 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.1MIT
- AlicenseNot gradedqualityBmaintenanceEnables LLMs to control a PicoScope 5000A USB oscilloscope for signal generation, block capture, measurements, and frequency response sweeps.1MIT