jt-mcp
Ask an AI app what WSJT-X is hearing. WSJT-X sends what it is doing and every decode to a UDP Server address; jt-mcp listens there and answers: who is calling CQ, and what kind of CQ (DX, POTA, a contest, a region), who has been heard and how well, what WSJT-X is tuned to, recent decodes and WSPR spots.
Read-only, permanently. jt-mcp never sends WSJT-X a message, so it cannot answer a call, key your transmitter or change a setting. No write, no PTT, no transmit control — a permanent constraint, not a first-version limit. The tests assert it against the source.
WSJT-X first, and WSJT-X defines the protocol. The UDP message definitions come from the
WSJT-X project — Network/NetworkMessage.hpp, at the schema WSJT-X states — because the project
that owns a definition is its authority. The code is
qso-graph-lib's, the same that
qso-graph-sim plays WSJT-X's messages with. JTDX,
WSJT-Z and MSHV are supported where they work with those definitions, and where one does not, its
difference is not implemented here. JS8Call, whose API is its own, follows WSJT-X.
This server was js8call-mcp until 2026-10-29. Part of the qso-graph
project.
Install
uvx jt-mcp # run it; nothing to install
Set up WSJT-X
In WSJT-X: File, Settings, Reporting, UDP Server: 127.0.0.1, port 2237 (WSJT-X's
defaults). That is all jt-mcp needs when WSJT-X runs on the same PC.
Only one program can listen on a UDP port. If GridTracker, JTAlert or another logger already
listens on 2237, give jt-mcp a different port (--udp-port) and point WSJT-X at that one.
Tools
| Tool | Answers |
|---|---|
jt_cq |
Who is calling CQ, and what kind: plain, DX, activity (POTA, SOTA, WWFF, IOTA), contest (TEST, FD, RU, WW), region (NA, EU, ...), or a frequency (CQ 290). The latest per station |
jt_status |
What each WSJT-X is doing: dial frequency and band, mode, DX call and grid, Tx enabled or transmitting, your call and grid |
jt_decodes |
Recent decodes, each read into its parts (who is calling whom, grid, report, sign-off); filter by callsign, CQ only, SNR, band |
jt_heard |
Stations heard: how often, last SNR, last grid, mode and band |
jt_wspr |
WSPR spots WSJT-X decoded: call, grid, power, SNR, drift |
jt_diagnostics |
The listener: where it listens, who may send, what arrived, what was dropped and from where, each WSJT-X's version |
get_version_info |
Service version and status |
Times are UTC. Several WSJT-X instances (two radios, two bands) are kept apart by the Id each
sends, such as WSJT-X - FT-991A.
Questions it will answer
"Who's calling CQ POTA on 20 m right now?"
"Any DX calling CQ in the last ten minutes, strongest first?"
"Has W9XYZ been heard, and how strong?"
"What is WSJT-X tuned to, and is Tx enabled?"
"Why isn't anything showing up?" —
jt_diagnostics
Configure your MCP client
jt-mcp works with any MCP-compatible client. Add the server and restart the client.
Claude Desktop
Add to claude_desktop_config.json (~/Library/Application Support/Claude/ on macOS,
%APPDATA%\Claude\ on Windows):
{
"mcpServers": {
"jt": {
"command": "uvx",
"args": ["jt-mcp"]
}
}
}
Claude Code
claude mcp add jt -- uvx jt-mcp
ChatGPT Desktop
Configure via Settings > Apps & Connectors, or in your agent definition, with the same
command and args as above.
WSJT-X on another PC
By default jt-mcp listens on 127.0.0.1, this PC alone. For WSJT-X on another PC, give one
address of this PC with --bind, and name each PC that may send with --allow:
"args": ["jt-mcp", "--bind", "192.168.1.50", "--allow", "192.168.1.40"]
and set WSJT-X's UDP Server to 192.168.1.50. Listening on every interface at once
(0.0.0.0) is refused, --allow is required with a network address, and names are not
accepted, only IP addresses. A datagram from anyone else is dropped unread and counted, and
jt_diagnostics shows the count and the addresses.
What the allow list does not do. It keeps other machines out. It is not proof of who sent: a UDP sender's address can be forged by anything on the same network. What contains that is that jt-mcp only reads, so a forged datagram can mislead about what WSJT-X is doing and cannot make anything happen.
Options
jt-mcp [--bind ADDR] [--allow ADDR ...] [--udp-port N]
[--transport stdio|streamable-http] [--port N] [--version] [--help]
| Option | Default | |
|---|---|---|
--bind ADDR |
127.0.0.1 |
where to listen for WSJT-X |
--allow ADDR |
this PC | a PC that may send; repeatable; required with a network --bind |
--udp-port N |
2237 |
WSJT-X's UDP Server port |
--transport |
stdio |
streamable-http binds 127.0.0.1 only |
--port N |
8031 |
the streamable-http port |
Licence
GPL-3.0-or-later. See LICENSE.
Metadata
Release files for jt-mcp 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| jt_mcp-0.2.0.tar.gz | 165.3 kB | With provenance | Details for jt_mcp-0.2.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| jt_mcp-0.2.0-py3-none-any.whl | Python 3 | none | any | Details for jt_mcp-0.2.0-py3-none-any.whl |
Total release size: 196.1 kB
Release files / jt_mcp-0.2.0.tar.gz
| Download URL | jt_mcp-0.2.0.tar.gz |
|---|---|
| Size | 165.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
b8497ae39080639d8722033168f3a49d01dfde55c07623d3495f10bfa9ce48d5
|
|
BLAKE2b-256 checksum How to use checksums |
f51145a9fc4e0b2dfa6f98dc40b59f3f530f450ee2767a42179eb8bafe51f681
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 29, 2026.
Transparency logRelease files / jt_mcp-0.2.0-py3-none-any.whl
| Download URL | jt_mcp-0.2.0-py3-none-any.whl |
|---|---|
| Size | 30.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
02297528a55171499fa9f8af005fe91a631127a1914a3d38c8b966b7cf36b630
|
|
BLAKE2b-256 checksum How to use checksums |
c5d867f2ada3846433aff3edc9126fa17e8403f51919ae442047ec8ac1061086
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 29, 2026.
Transparency logSecurity for jt-mcp 0.2.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for jt_mcp-0.2.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 29, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.