AE5VG

Product · MIT

n3fjp-mcp

An MCP server that logs amateur radio QSOs to N3FJP software: Amateur Contact Log and the 100-plus N3FJP contest loggers. It works with MCP-aware clients such as Claude Desktop. Every program in the N3FJP suite has the same TCP control API. n3fjp-mcp talks to that API directly, so you can ask the assistant in plain language to log contacts, read the log, check for dupes, and change band and mode.

Version…
Released…
LicenseMIT
Ships as.mcpb bundle · PyPI

What it does

fldigi-mcp operates the radio, and n3fjp-mcp logs the contacts. The log_qso operation goes through the same steps you would take at the keyboard. It sets the call and fires CALLTAB, which runs the dupe check and looks up any previous contact. Then it fills in the exchange, sends ENTER, and reports how many records were added and any dupe details. To decide whether the QSO was logged, it watches for the QSO count to change or for an ENTEREVENT. It does not rely on ENTERRESPONSE, which can report 0 for a QSO that was written.

The server talks to N3FJP through Python's standard socket library, with no third-party wrapper. Its only runtime dependency is the MCP SDK. It has been verified live against N3FJP's ARRL Field Day Contest Log, API version 2.2. Every program in the suite uses the same protocol, but each contest has its own set of fields. The fields tool shows which fields the running program uses.

Independent project · not affiliated with N3FJP

n3fjp-mcp is an independent, community project by Stefan Brunner (AE5VG), using the N3FJP name with the permission of its owner. It is not affiliated with, endorsed by, or supported by N3FJP Software / Affirmatech. Please direct all support questions for this app to its issue tracker, not to N3FJP. MIT licensed. "N3FJP" is the callsign and trademark of its owner.

Features and benefits

FeatureWhat it gives you
Logging with log_qsoOne operation runs the keyboard sequence that was verified against N3FJP: set the call, CALLTAB, exchange, ENTER. It returns N3FJP's dupe response. It also returns a logged flag, set from the QSO count changing or from an ENTEREVENT. ENTERRESPONSE is not used for this, because it can report 0 for a QSO that was written. Clients retry only when logged is false.
Call lookup from CALLTABAfter CALLTAB, N3FJP sends back a CALLTABEVENT with country, DXCC, zones, bearing and distance. n3fjp-mcp passes that on to you, and tells you if the call is a dupe.
What the tools coverRead queries, reading and writing fields, search and list, dupe and entity checks, band, mode and frequency, direct database operations, and push notifications that you turn on if you want them. They are grouped into tools, and each tool is one permission. For less common commands, and for commands N3FJP adds later, there is the n3fjp_call escape hatch.
Per-contest exchange presetslog_qso takes a contest and its exchange, for example contest="field_day" with class and section. Each contest has its own fields. The fields tool shows which ones the running program uses.
Read tools marked read-onlyYour client can set status, query, fields and search to Always Allow.
Writes need approvalLogging, band and mode, notifications, adding, editing or deleting single records, and the escape hatch are all set to Needs Approval. The server adds no confirmation step of its own, so you can set them to Always Allow for hands-off automation.
Switch for wiping the databaseThis is the only hard block. Raw SQL that could delete or overwrite the whole log (DROP, TRUNCATE, a DELETE or UPDATE with no WHERE) is refused unless the N3FJP_ALLOW_DB_WIPE switch is on. That switch is used for nothing else, and it is off by default. Operations limited to specific records run without it.
Names match N3FJPTools and fields use N3FJP's own terms: Action ENTER, CALLTAB, the TXTENTRY boxes, Class and Section.
DependenciesThe server uses Python's standard socket library for the protocol, with no third-party wrapper. The only runtime dependency is the MCP SDK.
diagnostics toolIt is read-only and does not connect to N3FJP. It reports the resolved N3FJP_HOST and N3FJP_PORT, this process's hostname and Python, and the host's network interfaces. From that you can tell whether the process can reach the target network at all.
N3FJP on another computerA sandboxed client can only reach 127.0.0.1. Run mcp-host-bridge on the client computer and it relays to N3FJP on the LAN. The connector's host setting remains 127.0.0.1.
contest-operating skillIt covers the steps of a contest QSO (CQ, exchange, TU, log) and a playbook for special cases: QRM, garbled callsigns, doubling, repeats after no copy, and callers who send only their callsign. It also covers the verified N3FJP logging sequence and its known quirks. It was used on the air during ARRL Field Day 2026.
Operating Skills Field GuideA PDF about contest-operating and its companion skill, fldigi-operating, which comes with fldigi-mcp. It covers installation, a chapter on the first session for hams new to Claude, the operating standard, the special-case playbook, and worked examples from ARRL Field Day 2026.
Free N3FJP API referenceA reference for the N3FJP TCP API, tested in the field and verified live against API 2.2. It lists every place where 2.2 differs from the public 0.9 documentation. That includes commands that were removed or renamed, CMD_NOT_FOUND, the API port versus the networking port, the CALLTABEVENT lookup, and why ENTER can report 0 and still log in networked mode. A machine-readable spec comes with it.

How it works

MAC Claude Desktop n3fjp-mcp mcp-host- bridge WINDOWS PC N3FJP · TCP API 1100 LAN · TCP
N3FJP runs on Windows. The connector often runs on a Mac and reaches N3FJP through mcp-host-bridge.

The N3FJP TCP protocol

Each item below was checked live against N3FJP's ARRL Field Day Contest Log 6.6.10, which reports API version 2.2. The details come from the N3FJP TCP API reference.

TopicWhat was verified
TransportPlain TCP. N3FJP is the server and the connector is the client. Default port 1100. Each command ends with CR LF.
EnvelopeEvery command and response is wrapped as <CMD><COMMANDID><TAG>value</TAG></CMD>. One packet can carry several blocks, so the stream is read continuously and split on </CMD>, never on newlines.
StreamResponses and opt-in notifications share one socket. A background reader sends each block to the request that is waiting for it, or to a notification buffer.
API port, not networking portPort 1100 is the API. Port 1000 is N3FJP's multi-PC networking socket. API commands sent there return nothing.
Unknown commandsN3FJP answers <CMD><CMD_NOT_FOUND></CMD> instead of staying silent. That lets you tell "not supported" apart from "wrong port".
Changed since 0.9There is no APIVERSION command. Read the APIVER tag from PROGRAM instead. READQSOCOUNT became QSOCOUNT. ALLFIELDSVALUES is gone because ALLFIELDS now includes the values. READUSERDATA is not present.
Logging flowUPDATE TXTENTRYCALL, ACTION CALLTAB, UPDATE the exchange boxes, correct band and mode, ACTION ENTER, read the response.
CALLTABEVENTA moment after CALLTAB, one block arrives with country, DXCC, both zones, prefix, continent, bearing, long path and distance. If the call is a dupe, a CALLTABDUPEEVENT follows.
ENTER can report 0 yet still logIn Network mode the master-table commit is asynchronous, so ENTERRESPONSE can return 0 for a QSO that was written. Success is checked by the QSOCOUNT change instead.

Where the connector runs

If N3FJP runs on the same computer as the client, leave the host at 127.0.0.1 and enable Settings → Application Program Interface → TCP API Enabled, port 1100, and you are done.

If N3FJP runs on a different computer, a sandboxed MCP client gets in the way. It runs the connector in a sandbox that can only reach loopback. If you put N3FJP's LAN IP in the settings, the connection times out, even though telnet to that IP works. Running mcp-host-bridge on the client computer fixes this. The diagnostics tool helps you confirm whether you need it. Keep the link on a trusted LAN, because the N3FJP API has no authentication.

Ask it

What is the N3FJP status? status: program, version, API version, QSO count, band, mode, frequency How many QSOs do we have? query qso_count Check if W1AW is a dupe. search dupecheck, with no side effects Log W1AW, 2A in STX. log_qso: set call, CALLTAB, exchange, ENTER; records added and dupe detail come back

Tools

Each tool is one permission and takes an operation argument.

ToolDefaultControls
statusreadsnapshot: program, version, API version, QSO count, band/mode/frequency
queryreadprogram, qso_count, next_serial, log/settings/shared paths, qso_rate, band_mode_freq
fieldsreadread one entry box, or list visible / all fields with values
searchreadlist recent, search, dupecheck (no side effects), entity status
logapprovallog_qso (set call → CALLTAB → exchange → ENTER), set, set_many, calltab, enter, clear, focus
bandmodeapprovalchange_freq, set_band, set_mode, ignore_rig_polls
notificationsapprovalenable / disable push events, drain buffered events
databaseapprovaladd_direct, delete a record, raw sql, checklog, openlog, sqlclose
n3fjp_callapprovalescape hatch: send any raw command, incl. future ones

A tenth tool, diagnostics, is read-only and does not connect to N3FJP. It reports the resolved host and port, this process's hostname and Python, and the host's network interfaces.

Settings

VariableDefaultPurpose
N3FJP_HOST127.0.0.1N3FJP API host
N3FJP_PORT1100N3FJP API port (the suite's default)
N3FJP_TIMEOUT6Socket/response timeout, seconds
N3FJP_ALLOW_DB_WIPEoffDanger. Allow whole-database delete/overwrite (raw SQL DROP/TRUNCATE/unscoped DELETE/UPDATE). Leave off unless you really mean it

Safety

Can touch your log database

Logging does not key a transmitter, so the protection here is for the log. Reads (status, query, fields, search) are marked read-only. Writes are set to Needs Approval, and the server adds no confirmation step of its own. Writes are logging, band and mode, notifications, adding, editing or deleting single records, and the n3fjp_call escape hatch. Raw SQL that could delete or overwrite the whole log is refused unless N3FJP_ALLOW_DB_WIPE is on. That switch is separate from the client's approval prompts, and stricter. Back up your log before you ever turn it on. Where it can, the server relies on N3FJP's own checks and passes N3FJP's responses back to you, instead of repeating those checks itself.

Documents