An MCP server that controls WSJT-X (FT8/FT4/etc.) over its UDP message protocol.
Strong tool definitions with comprehensive descriptions and clear schemas. All 13 tools have detailed docstrings explaining purpose, parameters, and side effects. Input schemas are well-structured with types and descriptions. Tool naming follows verb_noun convention (status, diagnostics, decodes, reply, free_text, halt_tx, configure, clear, highlight, location, switch_config, wsjtx_call). Key strength: explicit risk classification (READ_ONLY, WRITE, IRREVERSIBLE) and transmit-gate permission model. Weakness: output schemas are not formally documented in the tool definitions themselves, responses are described in docstrings but not as structured JSON Schema. Parameter descriptions are generally good (72 chars avg baseline) but some lack explicit constraints (e.g., 'grid' in location tool lacks format spec for Maidenhead validation). Error handling is present but recovery guidance is minimal.
Clear the Band Activity or Rx Frequency window. Equivalent to the Clear menu. ``window`` selects which to clear: - "band" / "band_activity" / "rx" / "rx_freq" / "rx_frequency" (default: band) - "both" / "all" (clear both windows)
Adjust WSJT-X operating parameters — mode, frequency tolerance, T/R period, etc. Equivalent to the Settings dialog. Each parameter is optional; omit to leave unchanged. ``mode`` and ``submode`` are case-insensitive (FT8, ft8, Ft8 all work). ``frequency_tolerance`` and ``tr_period`` accept ``None`` to reset to WSJT-X's default. Does not change the dial frequency (WSJT-X's UDP protocol cannot do that).
The RX data plane: buffered ``Decode`` / ``WSPRDecode`` lines. operations: - read (limit): the most recent N decodes (default 50). - drain: every decode seen since the last drain — the polling primitive for automation. Advances an internal cursor so each line is returned once. - clear_local: empty our local buffer (does not touch WSJT-X). - replay: ask WSJT-X to re-broadcast its current Band-Activity decodes (each with New=false) followed by a Status — useful to backfill state on connect. (No transmit; safe.) Each decode carries: kind (decode/wspr), New, time, snr, delta_time, delta_frequency, mode, message, low_confidence, off_air, and a `seq` you can pass to the `reply` tool.
Host + network + listener diagnostics for troubleshooting connectivity. Does NOT command WSJT-X. Reports the resolved WSJTX_HOST/PORT, whether the UDP listener is bound (and any bind error), datagram counts by message type, the discovered instances, the transmit-gate state, and this host's network interfaces — so you can tell whether this process can even receive WSJT-X's broadcasts (e.g. host-side vs. sandboxed, or a port already owned by JTAlert / GridTracker).
Output schemas not formally documented. Tool descriptions explain return values in prose, but no structured JSON Schema is provided for responses. This forces LLMs to parse unstructured docstrings and guess field types.
Parameter constraints not formally specified. 'grid' parameter in location tool lacks Maidenhead format validation (4 or 6 chars, A-R, 0-9, a-r). 'window' in clear tool accepts free-form strings instead of enum. LLMs cannot validate inputs without explicit constraints.
Error handling lacks recovery guidance. TransmitBlocked exception is raised but no tool provides a way to discover or set the callsign interactively. Error messages tell the LLM what failed but not how to proceed.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | C | 63 | 2026-07-28+ | v2 |
Transmit a free-form message — **initiates a transmission if send=true** (gated by callsign). Equivalent to typing into the Tx message box and clicking Send (or Ctrl-Return). If ``send=false`` (the default), the message is loaded into the Tx box but not sent — safe, no transmit gate required. If ``send=true``, it transmits immediately and requires the transmit gate (callsign) to be set.
Stop any transmission in progress — **does not key the radio** (safe, no gate). Equivalent to clicking the Halt Tx button. Stops the current transmission immediately. Does not affect "Enable Tx" — that remains as the operator set it. Note: WSJT-X's UDP protocol cannot *enable* Tx, only halt it.
Highlight or clear highlighting for a callsign in the Band Activity window. Equivalent to right-clicking a callsign and choosing a highlight colour. ``callsign`` is the call to highlight (or "CLEARALL!" to clear all highlights). ``background`` and ``foreground`` are ``(r, g, b)`` or ``(r, g, b, a)`` tuples (0-255 each), a named colour (red, green, yellow, …), a "#RRGGBB" hex string, or ``None`` / "clear" to remove highlighting. ``highlight_last`` (default false) if true highlights only the most recent decode from that call.
Set the operator's location (Maidenhead grid square). Equivalent to Settings → General → My Grid. Accepts a 4- or 6-character Maidenhead grid square (case-insensitive). WSJT-X uses this for distance/bearing calculations and in logged QSOs.
Read buffered completed QSOs (``QSOLogged`` paired with ``LoggedADIF``). Observe-only: WSJT-X emits these when the operator accepts its "Log QSO" dialog. Each entry has the structured QSO record (call, grids, frequency, mode, reports, times, exchanges, propagation mode) and the one-record ADIF document — ready to forward to N3FJP via n3fjp-mcp.
Answer a buffered decode — **initiates a transmission** (gated by callsign). Equivalent to double-clicking that decode in the Band Activity window. WSJT-X only acts if the message **exactly** matches a prior decode that is a CQ or QRZ. If WSJT-X's "Auto Seq" is on (the usual FT8/FT4 default) it then sequences the rest of the QSO to completion on its own; if Auto Seq is off this starts only the first transmission (Auto Seq is a UI setting, not UDP-controllable). Identify the decode by `seq` (from the `decodes` tool) or by exact `message` text (the most recent matching buffered decode is used). `modifiers` may be a name or list (shift, ctrl/cmd, alt, meta, keypad, group) to mimic modifier-clicks.
Latest WSJT-X state snapshot plus listener/connection health. Returns the most recent ``Status`` broadcast — dial frequency, mode/sub-mode, Tx Enabled / Transmitting / Decoding, DE/DX call & grid, Rx/Tx DF, T/R period, special-operation mode (e.g. FIELD DAY), configuration name, current Tx message — together with the discovered instances and the transmit-gate state. If no ``Status`` has arrived yet, that is reported with guidance (WSJT-X must have its UDP Server pointed at this host:port).
Switch to a named configuration. Equivalent to the Configuration dropdown. ``name`` is the exact configuration name as it appears in WSJT-X's Settings (case-sensitive). If the name does not exist, WSJT-X ignores the request silently.
Escape hatch: send any WSJT-X control message by name and field values. For advanced use: reach message types added by newer WSJT-X builds, or bypass the grouped-tool abstraction. ``message`` is the message type name (heartbeat, status, reply, clear, halt_tx, free_text, location, highlight, switch_config, configure, etc., case-insensitive). ``fields`` is a dict of field names → values matching the message's schema. Transmit-initiating messages (reply, free_text with send=true, or any keying message) are refused unless the transmit gate (callsign) is set.
wsjtx_call tool is an escape hatch that bypasses the grouped-tool abstraction. While documented as 'advanced use', it creates ambiguity: should an LLM use reply or wsjtx_call with message='reply'? This violates single-responsibility and increases cognitive load.
Pagination not implemented for decodes and log tools. Both return lists (default 50 and 20 items respectively) but no cursor, offset, or total_count is provided. Large result sets could exhaust context windows.